From: lothar Date: Mon, 3 Nov 2008 11:39:03 +0000 (+0000) Subject: Initial revision X-Git-Tag: v1.5.3~66 X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-redboot.git;a=commitdiff_plain;h=47412fc4bd1aefc0d5498bcb3860a9d727196f16 Initial revision --- diff --git a/packages/compat/linux/v2_0/ChangeLog b/packages/compat/linux/v2_0/ChangeLog new file mode 100644 index 00000000..a7463da8 --- /dev/null +++ b/packages/compat/linux/v2_0/ChangeLog @@ -0,0 +1,95 @@ +2005-03-27 Andrew Lunn + + * include/linux/kernel.h (PTR_ERR): Should be an unsigned long, + not an intager, at least that is what Linux uses. + +2005-01-22 Andrew Lunn + + * include/linux/spinlock.h (DEFINE_SPINLOCK): Added. + * include/linux/slab.h (vfree): Added vmalloc and vfree which map + to malloc and free. + * include/linux/rwsem.h: New file. eCos does not have read/write + semaphores so these are mapped to normal semaphores. + +2004-08-12 Andrew Lunn + + * include/linux/spinlock.h: Add CYG_UNUSED_PARAM() calls to avoid + compiler warnings. + +2004-08-04 Gary Thomas + + * include/linux/list.h (list_for_each_entry): New macro needed for + latest jffs2 code. + +2003-11-12 Thomas Koeller + + * cdl/linux.cdl: + * include/asm/page.h: + Make page size configurable via cdl. + +2003-10-18 Gary Thomas + + * src/rbtree.c (rb_erase): Fix bug in red-black tree which caused + node corruption - merge from external sources, found by Scott + Wilkerson. + +2003-10-18 Savin Zlobec + + * include/linux/rbtree.h: + Fixed 'pointer of type `void *' used in subtraction' compiler warrning. + +2003-07-27 Andrew Lunn + + * include/linux/init.h: + * include/linux/vmalloc.h: New dummy files so that jffs2 will + compile. + +2003-07-27 Michael Checky + Andrew Lunn + + * include/linux/kernel.h: Changed the #define IS_ERR to work correctly + negative error values returned by the jffs2 code. + +2003-06-10 Andrew Lunn + + * include/linux/stat.h: Removed #defines which has been added to + the main eCos sys/stat.h. + +2003-01-21 David Woodhouse + + * New package. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Red Hat. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/compat/linux/v2_0/cdl/linux.cdl b/packages/compat/linux/v2_0/cdl/linux.cdl new file mode 100644 index 00000000..d9b93aa7 --- /dev/null +++ b/packages/compat/linux/v2_0/cdl/linux.cdl @@ -0,0 +1,76 @@ +# ==================================================================== +# +# linux.cdl +# +# Linux compatibility layer data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): dwmw2 +# Contributors: tkoeller +# Date: 2003-01-08 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_LINUX_COMPAT { + display "Linux compatibility layer" + include_dir "" + description " + eCos supports a basic Linux compatibility Layer providing various + functions, equivalents or stubs expected by Linux kernel code, for + assistance in porting drivers and file system code from Linux. + Note this does not provide Linux compatibility to applications." + + compile rbtree.c + + cdl_option CYGNUM_LINUX_COMPAT_PAGE_SIZE_EXPONENT { + display "Define page size" + flavor data + legal_values 10 to 16 + default_value 12 + no_define + define PAGE_SHIFT + description " + Define the page size. The value entered here is used as an + exponent X in the expression 2^^X to ensure that the page + size is always an integer power of two." + } +} + +# EOF linux.cdl diff --git a/packages/compat/linux/v2_0/include/asm/atomic.h b/packages/compat/linux/v2_0/include/asm/atomic.h new file mode 100644 index 00000000..5cb72ff8 --- /dev/null +++ b/packages/compat/linux/v2_0/include/asm/atomic.h @@ -0,0 +1,10 @@ +#ifndef __ASM_ATOMIC_H__ +#define __ASM_ATOMIC_H__ + +#define atomic_t int +#define atomic_inc(atom) (*atom)++ +#define atomic_dec(atom) (*atom)-- +#define atomic_read(atom) (*atom) + + +#endif /* __ASM_ATOMIC_H__ */ diff --git a/packages/compat/linux/v2_0/include/asm/bug.h b/packages/compat/linux/v2_0/include/asm/bug.h new file mode 100644 index 00000000..060eb278 --- /dev/null +++ b/packages/compat/linux/v2_0/include/asm/bug.h @@ -0,0 +1,6 @@ +#ifndef __ASM_BUG_H__ +#define __ASM_BUG_H__ + +#define BUG() do { diag_printf("BUG() at %s %d\n", __FILE__, __LINE__); *(int *)0=0; } while (0) + +#endif /* __ASM_BUG_H__ */ diff --git a/packages/compat/linux/v2_0/include/asm/page.h b/packages/compat/linux/v2_0/include/asm/page.h new file mode 100644 index 00000000..d77a39ac --- /dev/null +++ b/packages/compat/linux/v2_0/include/asm/page.h @@ -0,0 +1,11 @@ +#ifndef __ASM_PAGE_H__ +#define __ASM_PAGE_H__ + +#include + +/* These aren't used by much yet. If that changes, you might want + to make them actually correct :) */ +#define PAGE_SIZE (0x1 << PAGE_SHIFT) + + +#endif /* __ASM_PAGE_H__ */ diff --git a/packages/compat/linux/v2_0/include/asm/semaphore.h b/packages/compat/linux/v2_0/include/asm/semaphore.h new file mode 100644 index 00000000..e8161554 --- /dev/null +++ b/packages/compat/linux/v2_0/include/asm/semaphore.h @@ -0,0 +1,20 @@ +#ifndef __ASM_SEMAPHORE_H__ +#define __ASM_SEMAPHORE_H__ + +#include + +struct semaphore { + cyg_drv_mutex_t x; +}; + +#define DECLARE_MUTEX(x) struct semaphore x = { { 0 } }; +#define DECLARE_MUTEX_LOCKED(x) struct semaphore x = { { 1 } }; + +#define init_MUTEX(sem) cyg_drv_mutex_init((cyg_drv_mutex_t *)sem) +#define init_MUTEX_LOCKED(sem) do { cyg_drv_mutex_init((cyg_drv_mutex_t *)sem); cyg_drv_mutex_lock((cyg_drv_mutex_t *)sem); } while(0) +#define down(sem) cyg_drv_mutex_lock((cyg_drv_mutex_t *)sem) +#define down_interruptible(sem) ({ cyg_drv_mutex_lock((cyg_drv_mutex_t *)sem), 0; }) +#define down_trylock(sem) cyg_drv_mutex_trylock((cyg_drv_mutex_t *)sem) +#define up(sem) cyg_drv_mutex_unlock((cyg_drv_mutex_t *)sem) + +#endif /* __ASM_SEMAPHORE_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/TODO b/packages/compat/linux/v2_0/include/linux/TODO new file mode 100644 index 00000000..df8a6d1a --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/TODO @@ -0,0 +1,11 @@ + +This contains a very limited set of Linux-compatibility headers, initially +just for getting JFFS2 to build. + +Some things are simply stubs which don't _work_, to allow the JFFS2 code +to compile. Note that you may need to implement these _properly_ in order +to use these for making other Linux code work, or indeed for making the +JFFS2 NAND support work. + +The non-working parts include, but are not limited to: + workqueue.h, wait.h, timer.h, spinlock.h, sched.h, compiler.h diff --git a/packages/compat/linux/v2_0/include/linux/compiler.h b/packages/compat/linux/v2_0/include/linux/compiler.h new file mode 100644 index 00000000..fb253651 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/compiler.h @@ -0,0 +1,7 @@ +#ifndef __LINUX_COMPILER_H__ +#define __LINUX_COMPILER_H__ + +#define likely(x) (x) +#define unlikely(x) (x) + +#endif /* __LINUX_COMPILER_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/completion.h b/packages/compat/linux/v2_0/include/linux/completion.h new file mode 100644 index 00000000..f131af83 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/completion.h @@ -0,0 +1,7 @@ +#ifndef __LINUX_COMPLETION_H__ +#define __LINUX_COMPLETION_H__ + +struct completion { } ; + +#endif /* __LINUX_COMPLETION_H__ */ + diff --git a/packages/compat/linux/v2_0/include/linux/config.h b/packages/compat/linux/v2_0/include/linux/config.h new file mode 100644 index 00000000..986e10b4 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/config.h @@ -0,0 +1,5 @@ +#ifndef __LINUX_CONFIG_H__ +#define __LINUX_CONFIG_H__ + + +#endif /* __LINUX_CONFIG_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/crc32.h b/packages/compat/linux/v2_0/include/linux/crc32.h new file mode 100644 index 00000000..8d19a1eb --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/crc32.h @@ -0,0 +1,8 @@ +#ifndef CRC32_H +#define CRC32_H + +#include + +#define crc32(val, s, len) cyg_crc32_accumulate(val, (unsigned char *)s, len) + +#endif diff --git a/packages/compat/linux/v2_0/include/linux/errno.h b/packages/compat/linux/v2_0/include/linux/errno.h new file mode 100644 index 00000000..339f4fc1 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/errno.h @@ -0,0 +1 @@ +#include diff --git a/packages/compat/linux/v2_0/include/linux/fs.h b/packages/compat/linux/v2_0/include/linux/fs.h new file mode 100644 index 00000000..c2f173ac --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/fs.h @@ -0,0 +1,13 @@ +#ifndef __LINUX_FS_H__ +#define __LINUX_FS_H__ + +#include +/* + * File types + */ +#define DT_UNKNOWN 0 +#define DT_DIR 4 +#define DT_REG 8 + + +#endif /* __LINUX_FS_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/init.h b/packages/compat/linux/v2_0/include/linux/init.h new file mode 100644 index 00000000..e4c702f9 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/init.h @@ -0,0 +1,3 @@ +#ifndef __LINUX_INIT_H__ +#define __LINUX_INIT_H__ +#endif diff --git a/packages/compat/linux/v2_0/include/linux/kernel.h b/packages/compat/linux/v2_0/include/linux/kernel.h new file mode 100644 index 00000000..3eb52d0a --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/kernel.h @@ -0,0 +1,32 @@ +#ifndef __LINUX_KERNEL_H__ +#define __LINUX_KERNEL_H__ +#include + +#define jiffies 100 + +#define ERR_PTR(err) ((void*)(err)) +#define PTR_ERR(err) ((unsigned long)(err)) +#define IS_ERR(err) ((unsigned long)err > (unsigned long)-1000L) + +#define CURRENT_TIME cyg_timestamp() + +#define KERN_EMERG "<0>" // system is unusable +#define KERN_ALERT "<1>" // action must be taken immediately +#define KERN_CRIT "<2>" // critical conditions +#define KERN_ERR "<3>" // error conditions +#define KERN_WARNING "<4>" // warning conditions +#define KERN_NOTICE "<5>" // normal but significant condition +#define KERN_INFO "<6>" // informational +#define KERN_DEBUG "<7>" // debug-level messages +#define printk diag_printf + +#define min(x,y) (x + * + *=========================================================================== + *####ECOSGPLCOPYRIGHTBEGIN#### + * ------------------------------------------- + * This file is part of eCos, the Embedded Configurable Operating System. + * Copyright (C) 2003 Red Hat. + * + * eCos is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 or (at your option) any later version. + * + * eCos is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with eCos; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or use macros + * or inline functions from this file, or you compile this file and link it + * with other works to produce a work based on this file, this file does not + * by itself cause the resulting work to be covered by the GNU General Public + * License. However the source code for this file must still be made available + * in accordance with section (3) of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work based on + * this file might be covered by the GNU General Public License. + * + * Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. + * at http://sources.redhat.com/ecos/ecos-license/ + * ------------------------------------------- + *####ECOSGPLCOPYRIGHTEND#### + *=========================================================================== + * + */ + +#ifndef CYGONCE_FS_JFFS2_LIST_H +#define CYGONCE_FS_JFFS2_LIST_H + + +/* -----------------------------------------------------------------------*/ + +/* Doubly linked list implementation to replace the GPL'd one used in + the Linux kernel. */ + +#include +#include + +/* TYPES */ + +struct list_head { + struct list_head *next; + struct list_head *prev; +}; + +/* MACROS */ + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD( _list_ ) \ +CYG_MACRO_START \ +(_list_)->next = (_list_)->prev = (_list_); \ +CYG_MACRO_END + +/* FUNCTIONS */ + +/* Insert an entry _after_ the specified entry */ +static __inline__ void +list_add( struct list_head *newent, struct list_head *afterthisent ) +{ + struct list_head *next = afterthisent->next; + newent->next = next; + newent->prev = afterthisent; + afterthisent->next = newent; + next->prev = newent; +} /* list_add() */ + +/* Insert an entry _before_ the specified entry */ +static __inline__ void +list_add_tail( struct list_head *newent, struct list_head *beforethisent ) +{ + struct list_head *prev = beforethisent->prev; + newent->prev = prev; + newent->next = beforethisent; + beforethisent->prev = newent; + prev->next = newent; +} /* list_add_tail() */ + +/* Delete the specified entry */ +static __inline__ void +list_del( struct list_head *ent ) +{ + ent->prev->next = ent->next; + ent->next->prev = ent->prev; +} /* list_del() */ + +/* Is this list empty? */ +static __inline__ int +list_empty( struct list_head *list ) +{ + return ( list->next == list ); +} /* list_empty() */ + +/* list_entry - Assuming you have a struct of type _type_ that contains a + list which has the name _member_ in that struct type, then given the + address of that list in the struct, _list_, this returns the address + of the container structure */ + +#define list_entry( _list_, _type_, _member_ ) \ + ((_type_ *)((char *)(_list_)-(char *)(offsetof(_type_,_member_)))) + +/* list_for_each - using _ent_, iterate through list _list_ */ + +#define list_for_each( _ent_, _list_ ) \ + for ( (_ent_) = (_list_)->next; \ + (_ent_) != (_list_); \ + (_ent_) = (_ent_)->next ) + +/* + * list_for_each_entry - this function can be use to iterate over all + * items in a list* _list_ with it's head at _head_ and link _item_ + */ +#define list_for_each_entry(_list_, _head_, _item_) \ +for ((_list_) = list_entry((_head_)->next, typeof(*_list_), _item_); \ + &((_list_)->_item_) != (_head_); \ + (_list_) = list_entry((_list_)->_item_.next, typeof(*_list_), _item_)) + +/* -----------------------------------------------------------------------*/ +#endif /* #ifndef CYGONCE_FS_JFFS2_LIST_H */ +/* EOF list.h */ diff --git a/packages/compat/linux/v2_0/include/linux/mtd/compatmac.h b/packages/compat/linux/v2_0/include/linux/mtd/compatmac.h new file mode 100644 index 00000000..cee37492 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/mtd/compatmac.h @@ -0,0 +1,5 @@ +#ifndef __LINUX_MTD_COMPATMAC_H__ +#define __LINUX_MTD_COMPATMAC_H__ + + +#endif /* __LINUX_MTD_COMPATMAC_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/mtd/mtd.h b/packages/compat/linux/v2_0/include/linux/mtd/mtd.h new file mode 100644 index 00000000..817d31cf --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/mtd/mtd.h @@ -0,0 +1,5 @@ +#ifndef __LINUX_MTD_MTD_H__ +#define __LINUX_MTD_MTD_H__ + + +#endif /* __LINUX_MTD_MTD_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/pagemap.h b/packages/compat/linux/v2_0/include/linux/pagemap.h new file mode 100644 index 00000000..fccf9c40 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/pagemap.h @@ -0,0 +1,19 @@ +#ifndef __LINUX_PAGEMAP_H__ +#define __LINUX_PAGEMAP_H__ + +#include +#include + +#define PAGE_CACHE_SHIFT PAGE_SHIFT +#define PAGE_CACHE_SIZE PAGE_SIZE + +#define PageLocked(pg) 1 +#define Page_Uptodate(pg) 0 +#define UnlockPage(pg) +#define PAGE_BUG(pg) BUG() +#define ClearPageUptodate(pg) +#define SetPageError(pg) +#define ClearPageError(pg) +#define SetPageUptodate(pg) + +#endif /* __LINUX_PAGEMAP_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/rbtree.h b/packages/compat/linux/v2_0/include/linux/rbtree.h new file mode 100644 index 00000000..fef5f718 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/rbtree.h @@ -0,0 +1,46 @@ +#ifndef _LINUX_RBTREE_H +#define _LINUX_RBTREE_H + + +struct rb_node { + struct rb_node *rb_left; /* left element */ + struct rb_node *rb_right; /* right element */ + struct rb_node *rb_parent; /* parent element */ + int rb_color; /* node color */ +}; + +struct rb_root { + struct rb_node *rb_node; /* root of the tree */ +}; +#define NULL ((void *)0) +#define RB_ROOT ((struct rb_root){NULL}) +#define rb_entry(p, container, field) \ + ((container *) ((char *)p - ((char *)&(((container *)0)->field)))) + +#define RB_BLACK 0 +#define RB_RED 1 + + +extern void rb_insert_color(struct rb_node *, struct rb_root *); +extern void rb_erase(struct rb_node *, struct rb_root *); + +/* Find logical next and previous nodes in a tree */ +extern struct rb_node *rb_next(struct rb_node *); +extern struct rb_node *rb_prev(struct rb_node *); +extern struct rb_node *rb_first(struct rb_root *); + +/* Fast replacement of a single node without remove/rebalance/add/rebalance */ +extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root); + +static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, + struct rb_node ** rb_link) +{ + node->rb_parent = parent; + node->rb_color = RB_RED; + node->rb_left = node->rb_right = NULL; + + *rb_link = node; +} + +#endif /* _LINUX_RBTREE_H */ diff --git a/packages/compat/linux/v2_0/include/linux/rwsem.h b/packages/compat/linux/v2_0/include/linux/rwsem.h new file mode 100644 index 00000000..d648a150 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/rwsem.h @@ -0,0 +1,20 @@ +#ifndef __LINUX_RWSEM_H__ +#define __LINUX_RWSEM_H__ + +// eCos does not have the concept of a read/write semaphore. So just +// map them onto normal semaphores and hope we don't deadlock +// somewhere. + +#include + +struct rw_semaphore; + +#define down_read(sem) cyg_drv_mutex_lock((cyg_drv_mutex_t *)sem) +#define down_read_trylock(sem) cyg_drv_mutex_trylock((cyg_drv_mutex_t *)sem) +#define down_write(sem) cyg_drv_mutex_lock((cyg_drv_mutex_t *)sem) +#define down_write_trylock(sem) cyg_drv_mutex_trylock((cyg_drv_mutex_t *)sem) +#define up_read(sem) cyg_drv_mutex_unlock((cyg_drv_mutex_t *)sem) +#define up_write(sem) cyg_drv_mutex_unlock((cyg_drv_mutex_t *)sem) +#define downgrade_write(sem) + +#endif // __LINUX_RWSEM_H__ diff --git a/packages/compat/linux/v2_0/include/linux/sched.h b/packages/compat/linux/v2_0/include/linux/sched.h new file mode 100644 index 00000000..14a73597 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/sched.h @@ -0,0 +1,7 @@ +#ifndef __LINUX_SCHED_H__ +#define __LINUX_SCHED_H__ + +#define cond_resched() do { } while(0) +#define signal_pending(x) (0) + +#endif /* __LINUX_SCHED_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/slab.h b/packages/compat/linux/v2_0/include/linux/slab.h new file mode 100644 index 00000000..fff39496 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/slab.h @@ -0,0 +1,14 @@ +#ifndef __LINUX_SLAB_H__ +#define __LINUX_SLAB_H__ + +#include + +#include /* Don't ask. Linux headers are a mess. */ + +#define kmalloc(x, y) malloc(x) +#define kfree(x) free(x) +#define vmalloc(x) malloc(x) +#define vfree(x) free(x) + +#endif /* __LINUX_SLAB_H__ */ + diff --git a/packages/compat/linux/v2_0/include/linux/spinlock.h b/packages/compat/linux/v2_0/include/linux/spinlock.h new file mode 100644 index 00000000..22eba0ba --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/spinlock.h @@ -0,0 +1,34 @@ +#ifndef __LINUX_SPINLOCK_H__ +#define __LINUX_SPINLOCK_H__ + + +typedef struct { } spinlock_t; +#define SPIN_LOCK_UNLOCKED (spinlock_t) { } +#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED + +#define spin_lock_init(lock) \ +CYG_MACRO_START; \ +CYG_UNUSED_PARAM(spinlock_t *, lock); \ +CYG_MACRO_END + +#define spin_lock(lock) \ +CYG_MACRO_START; \ +CYG_UNUSED_PARAM(spinlock_t *, lock); \ +CYG_MACRO_END + +#define spin_unlock(lock) \ +CYG_MACRO_START; \ +CYG_UNUSED_PARAM(spinlock_t *, lock); \ +CYG_MACRO_END + +#define spin_lock_bh(lock) \ +CYG_MACRO_START; \ +CYG_UNUSED_PARAM(spinlock_t *, lock); \ +CYG_MACRO_END + +#define spin_unlock_bh(lock) \ +CYG_MACRO_START; \ +CYG_UNUSED_PARAM(spinlock_t *, lock); \ +CYG_MACRO_END + +#endif /* __LINUX_SPINLOCK_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/stat.h b/packages/compat/linux/v2_0/include/linux/stat.h new file mode 100644 index 00000000..a3efd618 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/stat.h @@ -0,0 +1,12 @@ +#ifndef __LINUX_STAT_H__ +#define __LINUX_STAT_H__ + + +#include + +#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) +#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) +#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) +#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO) + +#endif /* __LINUX_STAT_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/string.h b/packages/compat/linux/v2_0/include/linux/string.h new file mode 100644 index 00000000..fc14ba60 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/string.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_STRING_H__ +#define __LINUX_STRING_H__ + +#include + +#endif /* __LINUX_STRING_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/timer.h b/packages/compat/linux/v2_0/include/linux/timer.h new file mode 100644 index 00000000..80e9ef50 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/timer.h @@ -0,0 +1,10 @@ +#ifndef __LINUX_TIMER_H__ +#define __LINUX_TIMER_H__ + +/* Not yet */ + +struct timer_list { } ; + + +#endif /* __LINUX_TIMER_H__ */ + diff --git a/packages/compat/linux/v2_0/include/linux/types.h b/packages/compat/linux/v2_0/include/linux/types.h new file mode 100644 index 00000000..e58fc253 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/types.h @@ -0,0 +1,13 @@ +#ifndef __LINUX_TYPES_H__ +#define __LINUX_TYPES_H__ + +#include "cyg/infra/cyg_type.h" + +#define uint8_t cyg_uint8 +#define uint16_t cyg_uint16 +#define uint32_t cyg_uint32 +#define loff_t off_t + +#define kvec iovec +#endif /* __LINUX_TYPES_H__ */ + diff --git a/packages/compat/linux/v2_0/include/linux/version.h b/packages/compat/linux/v2_0/include/linux/version.h new file mode 100644 index 00000000..cca2d731 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/version.h @@ -0,0 +1,5 @@ +#ifndef __LINUX_VERSION_H__ +#define __LINUX_VERSION_H__ + + +#endif /* __LINUX_VERSION_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/vmalloc.h b/packages/compat/linux/v2_0/include/linux/vmalloc.h new file mode 100644 index 00000000..6f18ab22 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/vmalloc.h @@ -0,0 +1,3 @@ +#ifndef __LINUX_VMALLOC_H__ +#define __LINUX_VMALLOC_H__ +#endif diff --git a/packages/compat/linux/v2_0/include/linux/wait.h b/packages/compat/linux/v2_0/include/linux/wait.h new file mode 100644 index 00000000..2b422e34 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/wait.h @@ -0,0 +1,15 @@ +#ifndef __LINUX_WAIT_H__ +#define __LINUX_WAIT_H__ + + +typedef struct { } wait_queue_head_t; + +#define init_waitqueue_head(wait) do{} while (0) +#define add_wait_queue(wait,new_wait) do{} while (0) +#define remove_wait_queue(wait,old_wait) do{} while (0) +#define DECLARE_WAITQUEUE(wait,current) do{} while (0) + +static inline void wake_up(wait_queue_head_t *erase_wait) +{ /* Only used for waking up threads blocks on erases. Not used in eCos */ } + +#endif /* __LINUX_WAIT_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/workqueue.h b/packages/compat/linux/v2_0/include/linux/workqueue.h new file mode 100644 index 00000000..8c900a48 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/workqueue.h @@ -0,0 +1,11 @@ +#ifndef __LINUX_WORKQUEUE_H__ +#define __LINUX_WORKQUEUE_H__ + +/* We don't do this yet */ +struct work_struct { } ; + +#define INIT_WORK(x,y,z) /* */ +#define schedule_work(x) do { } while(0) +#define flush_scheduled_work() do { } while(0) + +#endif /* __LINUX_WORKQUEUE_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/zlib.h b/packages/compat/linux/v2_0/include/linux/zlib.h new file mode 100644 index 00000000..9de691e8 --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/zlib.h @@ -0,0 +1,14 @@ +#ifndef __LINUX_ZLIB_H__ +#define __LINUX_ZLIB_H__ + +#include + +#define zlib_deflateInit(x,y) deflateInit(x,y) +#define zlib_deflate(x,y) deflate(x,y) +#define zlib_deflateEnd(x) deflateEnd(x) +#define zlib_inflateInit(x) inflateInit(x) +#define zlib_inflateInit2(x,y) inflateInit2(x,y) +#define zlib_inflate(x,y) inflate(x,y) +#define zlib_inflateEnd(x) inflateEnd(x) + +#endif /* __LINUX_ZLIB_H__ */ diff --git a/packages/compat/linux/v2_0/include/linux/zutil.h b/packages/compat/linux/v2_0/include/linux/zutil.h new file mode 100644 index 00000000..c3774baf --- /dev/null +++ b/packages/compat/linux/v2_0/include/linux/zutil.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_ZUTIL_H__ +#define __LINUX_ZUTIL_H__ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + +#endif /* __LINUX_ZUTIL_H__ */ diff --git a/packages/compat/linux/v2_0/src/rbtree.c b/packages/compat/linux/v2_0/src/rbtree.c new file mode 100644 index 00000000..1ad19c8a --- /dev/null +++ b/packages/compat/linux/v2_0/src/rbtree.c @@ -0,0 +1,409 @@ +/*======================================================================== +// +// rbtree.c +// +// Red Black tree implementation +// +//======================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Niels Provos/OpenBSD +// Contributors: dwmw2 +// Date: 2003-01-21 +// Purpose: This file provides an implementation of red-black trees. +// Description: Derived from OpenBSD src/sys/sys/tree.h +// Usage: +// +//####DESCRIPTIONEND#### +// +//====================================================================== +*/ + +/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ +/* + * Copyright 2002 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +/* Fields renamed to match Linux ones. */ +#include + + +#define RB_HEAD(head) (head)->rb_node +#define RB_LEFT(elm) (elm)->rb_left +#define RB_RIGHT(elm) (elm)->rb_right +#define RB_PARENT(elm) (elm)->rb_parent +#define RB_COLOR(elm) (elm)->rb_color + + +#define RB_SET(elm, parent) do { \ + RB_PARENT(elm) = parent; \ + RB_LEFT(elm) = RB_RIGHT(elm) = NULL; \ + RB_COLOR(elm) = RB_RED; \ +} while (0) + +#define RB_SET_BLACKRED(black, red) do { \ + RB_COLOR(black) = RB_BLACK; \ + RB_COLOR(red) = RB_RED; \ +} while (0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp) do { \ + (tmp) = RB_RIGHT(elm); \ + if ((RB_RIGHT(elm) = RB_LEFT(tmp))) { \ + RB_PARENT(RB_LEFT(tmp)) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp) = RB_PARENT(elm))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm))) \ + RB_LEFT(RB_PARENT(elm)) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm)) = (tmp); \ + } else \ + (head)->rb_node = (tmp); \ + RB_LEFT(tmp) = (elm); \ + RB_PARENT(elm) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp))) \ + RB_AUGMENT(RB_PARENT(tmp)); \ +} while (0) + +#define RB_ROTATE_RIGHT(head, elm, tmp) do { \ + (tmp) = RB_LEFT(elm); \ + if ((RB_LEFT(elm) = RB_RIGHT(tmp))) { \ + RB_PARENT(RB_RIGHT(tmp)) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp) = RB_PARENT(elm))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm))) \ + RB_LEFT(RB_PARENT(elm)) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm)) = (tmp); \ + } else \ + (head)->rb_node = (tmp); \ + RB_RIGHT(tmp) = (elm); \ + RB_PARENT(elm) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp))) \ + RB_AUGMENT(RB_PARENT(tmp)); \ +} while(0) + +/* Note args swapped to match Linux */ +void rb_insert_color(struct rb_node *elm, struct rb_root *head) +{ + struct rb_node *parent, *gparent, *tmp; + while ((parent = RB_PARENT(elm)) && + RB_COLOR(parent) == RB_RED) { + gparent = RB_PARENT(parent); + if (parent == RB_LEFT(gparent)) { + tmp = RB_RIGHT(gparent); + if (tmp && RB_COLOR(tmp) == RB_RED) { + RB_COLOR(tmp) = RB_BLACK; + RB_SET_BLACKRED(parent, gparent); + elm = gparent; + continue; + } + if (RB_RIGHT(parent) == elm) { + RB_ROTATE_LEFT(head, parent, tmp); + tmp = parent; + parent = elm; + elm = tmp; + } + RB_SET_BLACKRED(parent, gparent); + RB_ROTATE_RIGHT(head, gparent, tmp); + } else { + tmp = RB_LEFT(gparent); + if (tmp && RB_COLOR(tmp) == RB_RED) { + RB_COLOR(tmp) = RB_BLACK; + RB_SET_BLACKRED(parent, gparent); + elm = gparent; + continue; + } + if (RB_LEFT(parent) == elm) { + RB_ROTATE_RIGHT(head, parent, tmp); + tmp = parent; + parent = elm; + elm = tmp; + } + RB_SET_BLACKRED(parent, gparent); + RB_ROTATE_LEFT(head, gparent, tmp); + } + } + RB_COLOR(head->rb_node) = RB_BLACK; +} + + +static void rb_remove_color(struct rb_root *head, struct rb_node *parent, + struct rb_node *elm) +{ + struct rb_node *tmp; + while ((elm == NULL || RB_COLOR(elm) == RB_BLACK) && + elm != RB_HEAD(head)) { + if (RB_LEFT(parent) == elm) { + tmp = RB_RIGHT(parent); + if (RB_COLOR(tmp) == RB_RED) { + RB_SET_BLACKRED(tmp, parent); + RB_ROTATE_LEFT(head, parent, tmp); + tmp = RB_RIGHT(parent); + } + if ((RB_LEFT(tmp) == NULL || + RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) && + (RB_RIGHT(tmp) == NULL || + RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK)) { + RB_COLOR(tmp) = RB_RED; + elm = parent; + parent = RB_PARENT(elm); + } else { + if (RB_RIGHT(tmp) == NULL || + RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK) { + struct rb_node *oleft; + if ((oleft = RB_LEFT(tmp))) + RB_COLOR(oleft) = RB_BLACK; + RB_COLOR(tmp) = RB_RED; + RB_ROTATE_RIGHT(head, tmp, oleft); + tmp = RB_RIGHT(parent); + } + RB_COLOR(tmp) = RB_COLOR(parent); + RB_COLOR(parent) = RB_BLACK; + if (RB_RIGHT(tmp)) + RB_COLOR(RB_RIGHT(tmp)) = RB_BLACK; + RB_ROTATE_LEFT(head, parent, tmp); + elm = RB_HEAD(head); + break; + } + } else { + tmp = RB_LEFT(parent); + if (RB_COLOR(tmp) == RB_RED) { + RB_SET_BLACKRED(tmp, parent); + RB_ROTATE_RIGHT(head, parent, tmp); + tmp = RB_LEFT(parent); + } + if ((RB_LEFT(tmp) == NULL || + RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) && + (RB_RIGHT(tmp) == NULL || + RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK)) { + RB_COLOR(tmp) = RB_RED; + elm = parent; + parent = RB_PARENT(elm); + } else { + if (RB_LEFT(tmp) == NULL || + RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) { + struct rb_node *oright; + if ((oright = RB_RIGHT(tmp))) + RB_COLOR(oright) = RB_BLACK; + RB_COLOR(tmp) = RB_RED; + RB_ROTATE_LEFT(head, tmp, oright); + tmp = RB_LEFT(parent); + } + RB_COLOR(tmp) = RB_COLOR(parent); + RB_COLOR(parent) = RB_BLACK; + if (RB_LEFT(tmp)) + RB_COLOR(RB_LEFT(tmp)) = RB_BLACK; + RB_ROTATE_RIGHT(head, parent, tmp); + elm = RB_HEAD(head); + break; + } + } + } + if (elm) + RB_COLOR(elm) = RB_BLACK; +} + +/* Note name changed. Guess why :) */ +void rb_erase(struct rb_node *elm, struct rb_root *head) +{ + struct rb_node *child, *parent, *old = elm; + int color; + if (RB_LEFT(elm) == NULL) + child = RB_RIGHT(elm); + else if (RB_RIGHT(elm) == NULL) + child = RB_LEFT(elm); + else { + struct rb_node *left; + elm = RB_RIGHT(elm); + while ((left = RB_LEFT(elm))) + elm = left; + child = RB_RIGHT(elm); + parent = RB_PARENT(elm); + color = RB_COLOR(elm); + if (child) + RB_PARENT(child) = parent; + if (parent) { + if (RB_LEFT(parent) == elm) + RB_LEFT(parent) = child; + else + RB_RIGHT(parent) = child; + RB_AUGMENT(parent); + } else + RB_HEAD(head) = child; + if (RB_PARENT(elm) == old) + parent = elm; + *(elm) = *(old); + if (RB_PARENT(old)) { + if (RB_LEFT(RB_PARENT(old)) == old) + RB_LEFT(RB_PARENT(old)) = elm; + else + RB_RIGHT(RB_PARENT(old)) = elm; + RB_AUGMENT(RB_PARENT(old)); + } else + RB_HEAD(head) = elm; + RB_PARENT(RB_LEFT(old)) = elm; + if (RB_RIGHT(old)) + RB_PARENT(RB_RIGHT(old)) = elm; + if (parent) { + left = parent; + do { + RB_AUGMENT(left); + } while ((left = RB_PARENT(left))); + } + goto color; + } + parent = RB_PARENT(elm); + color = RB_COLOR(elm); + if (child) + RB_PARENT(child) = parent; + if (parent) { + if (RB_LEFT(parent) == elm) + RB_LEFT(parent) = child; + else + RB_RIGHT(parent) = child; + RB_AUGMENT(parent); + } else + RB_HEAD(head) = child; +color: + if (color == RB_BLACK) + rb_remove_color(head, parent, child); +} + +struct rb_node *rb_next(struct rb_node *elm) +{ + if (RB_RIGHT(elm)) { + elm = RB_RIGHT(elm); + while (RB_LEFT(elm)) + elm = RB_LEFT(elm); + } else { + if (RB_PARENT(elm) && + (elm == RB_LEFT(RB_PARENT(elm)))) + elm = RB_PARENT(elm); + else { + while (RB_PARENT(elm) && + (elm == RB_RIGHT(RB_PARENT(elm)))) + elm = RB_PARENT(elm); + elm = RB_PARENT(elm); + } + } + return (elm); +} + +struct rb_node *rb_prev(struct rb_node *elm) +{ + if (RB_LEFT(elm)) { + elm = RB_LEFT(elm); + while (RB_RIGHT(elm)) + elm = RB_RIGHT(elm); + } else { + if (RB_PARENT(elm) && + (elm == RB_RIGHT(RB_PARENT(elm)))) + elm = RB_PARENT(elm); + else { + while (RB_PARENT(elm) && + (elm == RB_LEFT(RB_PARENT(elm)))) + elm = RB_PARENT(elm); + elm = RB_PARENT(elm); + } + } + return (elm); +} + +/* These ones are lifted from Linux -- but that's OK because I + wrote them. dwmw2. */ +struct rb_node *rb_first(struct rb_root *root) +{ + struct rb_node *n; + + n = root->rb_node; + if (!n) + return 0; + while (n->rb_left) + n = n->rb_left; + return n; +} + +void rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root) +{ + struct rb_node *parent = victim->rb_parent; + + /* Set the surrounding nodes to point to the replacement */ + if (parent) { + if (victim == parent->rb_left) + parent->rb_left = new; + else + parent->rb_right = new; + } else { + root->rb_node = new; + } + if (victim->rb_left) + victim->rb_left->rb_parent = new; + if (victim->rb_right) + victim->rb_right->rb_parent = new; + + /* Copy the pointers/colour from the victim to the replacement */ + *new = *victim; +} diff --git a/packages/compat/posix/v2_0/ChangeLog b/packages/compat/posix/v2_0/ChangeLog new file mode 100644 index 00000000..4eed2095 --- /dev/null +++ b/packages/compat/posix/v2_0/ChangeLog @@ -0,0 +1,1094 @@ +2004-10-01 Oyvind Harboe + + * src/signal.cxx: place the CYGBLD_ATTRIB_INIT_PRI such that it + compiles for gcc 3.4.2 which is more picky about its placement. + +2003-12-02 Sandeep + + * src/mqueue.cxx (new): define a placement new instead of using + +2003-11-19 Rickard Westman + + * src/mqueue.cxx: Fix problem with mq_timedsend() and + mq_timedreceive() timing out with zero timeouts even when there is + room in the queue. + +2003-11-17 Dan Jakubiec + + * src/pthread.cxx (pthread_exit): Added code to disable cancellation + requests during thread exit. This allows thread cleanup handlers + to issue system calls when cleaning up thread resources. + +2003-06-18 Jonathan Larmour + + * src/pthread.cxx (pthread_self_info): Just add some comments so + no-one's tempted to uncomment assert. + (pthread_create): Verify that self is a valid POSIX thread when + needed. + +2003-03-20 Mark Salter + + * include/pthread.h: Avoid conflict with recently introduced gcc + __thread keyword. + +2003-03-13 Bart Veer + + * include/export.h: Only export signal-related functions if + CYGPKG_POSIX_SIGNALS is enabled. + +2003-03-04 Gary Thomas + + * include/pthread.h: Rework prototypes to minimize namespace problems. + +2003-03-03 Jonathan Larmour + + * tests/signal2.c (cause_illegal_access): PowerPC only generates + alignment exceptions in little-endian mode, so make that a special + case. + + * tests/mutex3.c: Include POSIX headers before feature tests to + prevent spurious CYG_TEST_NA. + +2003-02-24 Jonathan Larmour + + * doc/posix.sgml: Expunge EL/IX. Dead standard. + * cdl/posix.cdl: Add doc link. + +2003-02-13 Jonathan Larmour + + * src/mutex.cxx: Include sched.hxx for scheduler lock/unlock primitives. + Reported by Jani Monoses. + +2003-02-10 Gary Thomas + + * tests/signal3.c (main): Reorg code so it builds with older GCC. + +2003-01-31 Nick Garnett + + * src/time.cxx (alarm_action): Added call to + cyg_posix_signal_sigwait() to wake up any sigwait()ing threads. + + * src/signal.cxx (cyg_posix_signal_sigwait): Added this function + to export access to signal_sigwait conditional variable. + (sigtimedwait): Added call to cyg_posix_timer_asr() to allow timer + signals to be delivered here. + + * src/pprivate.h: Added prototype for cyg_posix_signal_sigwait(). + + * cdl/posix.cdl: + * tests/signal3.c: Added this program to test interaction of + timers and signals, particularly sigwait(). Based on a test + program from N.Suresh . + +2003-01-20 Jonathan Larmour + + * src/signal.cxx (cyg_posix_deliver_signals): silence warning. + + * src/time.cxx (cyg_timespec_to_ticks): Remove use of default arg in + definition. + +2003-01-18 Jonathan Larmour + + * src/mqueue.cxx: Fix multi-line string literal warning. + +2003-01-13 Jonathan Larmour + + * doc/posix.sgml: Document them. + + * src/mqueue.cxx (mq_timedreceive): Make fully compliant by dealing + with bogus timeouts. + (mq_timedsend): Ditto. + +2003-01-13 Dmitriy Korovkin + + * src/mqueue.cxx (mq_timedsend): New function. Implementing POSIX + 1003.1d draft definition. + (mq_timedreceive): Ditto. + +2002-12-10 Wade Jensen +2002-12-10 Jonathan Larmour + + * src/mutex.cxx (pthread_cond_timedwait): Initialize clock converters + only once ever. + +2002-11-26 Nick Garnett + + * src/signal.cxx: Changed the three routines added in the last + change so that they can be called safely from non-POSIX threads. + +2002-11-10 Nick Garnett + + * src/signal.cxx: Added three exportable routines that may be used + by other packages to manipulate the signal mask, test for + deliverable signals, and have signals delivered at controlled + points. + + * include/export.h: Added macros to export signal mask management, + detection and delivery to other packages. + +2002-11-05 Jonathan Larmour + + * tests/tm_basic.cxx: Use for diag_printf + prototype. + +2002-05-23 Jesper Skov + + * cdl/posix.cdl: Don't build tests using signals when posix + signals are disabled. + +2002-05-21 Jesper Skov + + * tests/mutex3.c: Added an NA check. + +2002-04-09 Jonathan Larmour + + * src/signal.cxx (cyg_deliver_signals): Don't assert here for an + unhandled signal (unless there's no _exit). Trace it though. + +2002-04-08 Jonathan Larmour + + * src/sem.cxx (sem_getvalue): return 0, and put value in *sval. + +2002-04-03 Jonathan Larmour + + * cdl/posix.cdl: Allow clocks to be configured again. + +2002-03-05 Jesper Skov + + * src/pprivate.h: Correct conditional declaration of timespec + functions. + + * src/sched.cxx (sched_rr_get_interval): Return ENOSYS when + CYGPKG_POSIX_CLOCKS disabled. + +2002-02-27 Robin Farine + + * src/pthread.cxx (pthread_exit): While running thread static + storage destructors, set the thread's value associated with the + current key to NULL before invoking the destructor. + +2002-02-14 Nick Garnett + + * doc/posix.sgml: Generally fixed up and reformatted to make this + file readable by mere humans. Some omissions and outdated + information fixed, but not substantially changed from the + original. + + * cdl/posix.cdl: Changed some definitions and dependencies so that + disabling the timers does not disable threads too. This was + largely a consequence of trying to document the behaviour of these + options. + +2002-02-14 Jonathan Larmour + + * doc/posix.sgml: New file, originally accompanied by this ChangeLog: + 2001-12-22 Jonathan Larmour + + * ecos-elix.sgml: Do a minor cleanup of the function prototype + layouts. + Should be done better than this, but this is at least not + _completely_ wrong any more. + Also several more layout problems due to incorrect tags fixed. + + 2001-12-07 Jonathan Larmour + + * ecos-elix.sgml: Add getcwd as supported now. + + 2001-12-06 Jonathan Larmour + + * ecos-elix.sgml: Created from old framemaker version. + +2002-01-21 Jonathan Larmour + + * src/sched.cxx (sched_get_priority_min): Don't allow idle thread + priority as a valid priority. + Case #106952. + +2001-12-11 Nick Garnett + + * tests/mqueue2.c (cyg_user_start): Added CYG_TEST_INIT() to + NOTAPPLICABLE variant, otherwise the order of breakpoints are all + wrong and the testfarm registers a failure. + +2001-11-06 Gary Thomas + + * include/muttypes.h: Need configuration info, + otherwise structures defined here could have the wrong size. + +2001-10-25 I-Jui Sung + + * src/mqueue.cxx (do_mq_unlink): Nullify table entries' mq as this + is used by mq_open to see if the entry is used. + +2001-10-11 Jesper Skov + + * tests/mutex3.c: Fixed warning. + (new_thread): Fixed allocation: increase counter + before starting threads which have been allocated resources. + + * tests/signal2.c (cause_illegal_access): Fix warning. + +2001-10-10 Jesper Skov + + * cdl/posix.cdl: Only build sem.cxx when the semaphores component + is enabled. + +2001-10-09 Jonathan Larmour + + * src/pprivate.h (pthread_info): Conditionalize signal specific + members. Conditionalize declaration of + cyg_posix_pthread_release_thread(). + + * cdl/posix.cdl (CYGPKG_POSIX_CLOCKS): new option to separately + configure posix clocks from timers. + (CYGPKG_POSIX_TIMERS): require clocks and signals. + + * include/time.h: Make proper ISO C. Conditionalize on + CYGPKG_POSIX_TIMERS correctly wrt the above change. + + * src/pthread.cxx (posix_asr): Call signal and timer subsystems + conditionally. + + * src/pthread.cxx (pthread_reap): Don't destroy signal handling + fields if there is no signal handling subsystem. + (cyg_posix_pthread_release_thread): Conditionalize on signals. + (pthread_create): Init signal subsys conditionally. + + * src/signal.cxx (sleep): Move to... + + * src/time.cxx: ...here. + Conditionalize throughout depending on whether it's POSIX clocks + or more specifically POSIX timers. + (nanosleep): Use PTHREAD_TESTCANCEL() not pthread_testcancel(). + Get current thread from kernel not pthreads to remove pthread + dependency. + +2001-10-09 Jesper Skov + + * tests/signal2.c: Also do NA check for signals. + +2001-10-01 Jonathan Larmour + + * src/mqueue.cxx (mq_open): Conditionalize use of sigev correctly. + (mq_close): Similarly. + +2001-09-28 Jonathan Larmour + + * cdl/pthread.cdl (CYGNUM_POSIX_MAIN_DEFAULT_PRIORITY): Clarify + POSIX thread priority description. + +2001-09-28 Jesper Skov + + * cdl/pthread.cdl: Changed default priority of POSIX main to + 16. This allows service threads (such as DHCP thread) to run when + started from main(). + +2001-09-10 Jonathan Larmour + + * include/pthread.h: Separate mutex and condvar API into separate + header file to fix configury problems. + * include/mutex.h: New file for the above. + * cdl/posix.cdl: provide the correct configury for the isoinfra + package to include the above file. + * cdl/pthread.cdl: Move _POSIX_PTHREAD_PRIO_INHERIT and + _POSIX_THREAD_PRIO_PROTECT to cdl/posix.cdl. + +2001-09-07 Jonathan Larmour + + * src/sem.cxx (sem_trywait): Actually use the return value. + + * src/sched.cxx (sched_get_priority_max): Use MAX not MIN + (sched_get_priority_min): Use MIN not MAX. + +2001-09-06 Jesper Skov + + * cdl/posix.cdl: Moved signal implements statements to the + CYGPKG_POSIX_SIGNALS component. + +2001-08-06 Jonathan Larmour + + * cdl/posix.cdl: Reorganize dependencies so that signals, timers + and pthreads really can be disabled, and the relevant files don't + get built. + Build new mutex.cxx file. + Remove duplicate CYGPKG_POSIX_SCHED dependency for pthreads. + + * include/limits.h: Don't include irrelevant header dependencies. + + * include/muttypes.h: New type defining mutex/cond var types separately + from other pthread types. + + * include/types.h: Remove mutex/cond var types. + + * include/signal.h: Conditionalize on CYGPKG_POSIX_SIGNALS + + * include/sigsetjmp.h: Don't include irrelevant header dependencies. + Rewrite sigsetjmp in a much more compiler friendly (and readable) + way with less type punning. + + * src/misc.cxx: Don't include sysconf cases when pthreads or + CYGPKG_POSIX_TIMERS not enabled. + + * src/mutex.cxx: New file, broken out of pthreads.cxx, as most + of it is not fixed to the pthreads implementation, and I've fixed + the bits that were too tied to it. + + * src/pprivate.h: Conditionalize definitions that are specific + to CYGPKG_POSIX_PTHREAD. Ditto for prototypes for CYGPKG_POSIX_SIGNALS + and CYGPKG_POSIX_TIMERS. Move PTHREAD_ENTRY/RETURN etc. macros + here so they can be used throughout the package. + + * src/pthread.cxx: Remove mutex/cond var implementation, and + entry/return macros, as per above. + + * src/signal.cxx (cyg_sigqueue): Don't just set non-queueable signals + pending - also forcibly wake up any blocked threads. + (siglongjmp): Use new layout of sigjmp_buf. + + * tests/mutex3.c: + * tests/pthread1.c: + * tests/pthread2.c: + * tests/pthread3.c: + * tests/signal1.c: + * tests/sigsetjmp.c: + * tests/timer1.c: + * tests/tm_basic.cxx: + Correct configuration dependencies, and do NA appropriately. + +2001-08-03 Nick Garnett + + Imported from a development branch: + + 2001-06-27 Nick Garnett + + * tests/pthread3.c: + Modified the loop that waits for the threads to get going so that + it will function correctly in an SMP system, where the threads + will run in parallel. + + * tests/mutex3.c: Disabled this test for SMP systems. It depends + too much on predicting the priority-driven execution order of the + threads. In an SMP system, some threads will run in parallel and + falsify the assumptions. + + 2001-05-25 Nick Garnett + + * src/signal.cxx (siglongjmp): Minor change to satisfy latest C++ + compiler. + +2001-06-14 Jonathan Larmour + + * src/pthread.cxx (pthread_attr_setstacksize): Correct stack + size assertion. + +2001-06-12 Jonathan Larmour + + * src/pthread.cxx (MAIN_DEFAULT_STACK_SIZE): Define to use at + least PTHREAD_STACK_MIN for main_stack. + +2001-05-01 Nick Garnett + + [x86 branch] + * tests/signal2.c (cause_illegal_access): Added code for I386 + architecture to provoke General Protection Fault. + + * src/except.cxx: Removed some extraneous diag_printf()s. + +2001-04-25 Bart Veer + + * tests/tm_basic.cxx: + This test is now functional on the synthetic target. + +2001-04-20 Jonathan Larmour + + * src/time.cxx (cyg_ticks_to_timespec): Actually don't bother + with working out seconds using convertors. Instead just divide + down ns from a long long. + +2001-04-19 Jonathan Larmour + + * src/time.cxx (cyg_ticks_to_timespec): Clock convertors round off, + so adjust timespec accordingly. + +2001-02-14 Jonathan Larmour + + * include/pthread.h: Remove pthread_canceled() and + pthread_testcancel_unlock(). + + * src/pthread.cxx: Ditto. + (pthread_join): Restructure to have function exit only at function end + (pthread_cond_timedwait): Check for timeouts and return ETIMEDOUT + + * src/signal.cxx (sigtimedwait): Restructure cancellation testing + + * src/time.cxx (nanosleep): test for cancellation at the end of the + function to keep Nick happy ;). + +2001-02-11 Jonathan Larmour + + * include/pthread.h: Add new pthread_testcancel_unlock and + pthread_canceled functions as eCos extensions. + Rename existing pthread_canceled variable to pthread_cancelled_dummy_var + + * src/pthread.cxx (pthread_canceled): New function to interrogate if + current thread has deferred cancel pending + (pthread_testcancel_unlock): New function. Like testcancel, but unlocks + a mutex before exitting the thread. + (checkforcancel): New internal function + (pthread_join): Add thread cancellation checks. + (pthread_cond_wait): Ditto. + (pthread_cond_timedwait): Ditto. + (pthread_testcancel): Use checkforcancel() + + * src/sem.cxx (sem_wait): Add thread cancellation checks + * src/signal.cxx (sigtimedwait): Ditto. + Also make compilation of this file conditional on CYGPKG_POSIX_SIGNALS + * src/time.cxx (nanosleep): Ditto. + Also make compilation of this file conditional on CYGPKG_POSIX_TIMERS + + * cdl/posix.cdl (CYGPKG_POSIX_TIMERS): Implements POSIX timer ops. + Add explicit kernel and pthread dependencies. + + * tests/sigsetjmp.c (pthread_entry1): Fix incorrect thread no. output + + * tests/pthread3.c: Add deferred cancellation test. + +2001-01-11 Nick Garnett + + * src/pthread.cxx (pthread_testcancel): Added test for self != + NULL in case this gets called from a non-pthread. + +2000-12-22 Jonathan Larmour + + * src/pthread.cxx (pthread_measure_stack_usage): New function + to measure stack usage. + + * include/pthread.h: Prototype it. + + * cdl/pthread.cdl: remove CYGNUM_POSIX_MAIN_DEFAULT_STACK_SIZE and + instead implement CYGINT_LIBC_STARTUP_EXTERNAL_INVOKE_MAIN_POSSIBLE + + * src/pthread.cxx: Use stack size for main from libc_startup package + to prevent confusion + (cyg_posix_pthread_start): Likewise + +2000-12-06 Jonathan Larmour + + * src/signal.cxx: include unistd.h for _exit + +2000-11-20 Nick Garnett + + * src/signal.cxx (cyg_deliver_signals): Added else in code to + handle SIG_DFL. Otherwise if the SA_SIGINFO bit is set we call the + signal handler twice! + +2000-11-07 Jonathan Larmour + + * src/signal.cxx (cyg_posix_thread_siginit): Add extra thread + argument so that threads can inherit parent's sigmask. + + * src/pthread.cxx (pthread_create): Call with parent thread + + * src/pprivate.h: Change cyg_posix_thread_siginit prototype to take + parent thread argument + + * tests/signal1.c: Add more checking of sigwaits, and fix so that it's + only called when the signal is masked. Check errno values too + sometimes. + +2000-11-02 Jonathan Larmour + + * src/signal.cxx (sigtimedwait): return signal number on success, + not 0 + (SIGNAL_RETURN_VALUE): New macro for returning from functions with + valid non-zero returns + (sigwaitinfo): Pass on sigtimedwait result with SIGNAL_RETURN_VALUE + macro as it may return the signal number. + +2000-11-01 Jonathan Larmour + + * src/signal.cxx (sigtimedwait): Check for SIGALRMs as a special + case when looping as it won't have been set pending if it was + masked. + (check_sigalarm): New function extracted from the posix signal ASR + (sigalrm_action): Unconditionally wake up threads waiting in sigwait + so that they can check for pending SIGALRMs even if they were + masked. + (cyg_deliver_signals): Handle SIG_DFL signals properly, and check + for bad signal handlers. + (cyg_posix_signal_start): Initialize default signal actions to SIG_DFL + +2000-10-27 Jesper Skov + + * tests/signal2.c (cause_illegal_access): Don't loop forever. + +2000-10-16 Jonathan Larmour + + * include/sigsetjmp.h (sigsetjmp): Various fixes to make portable + across all HALs (by avoiding CYGARC_JMP_BUF_SIZE) and remove warnings. + * src/signal.cxx (siglongjmp): Likewise + +2000-10-12 Nick Garnett + + * include/sigsetjmp.h: Added this header to define + sigjmp_buf,sigsetjmp() and siglongjmp(). + + * cdl/posix.cdl: + Added support for providing sigsetjmp implementation and header. + Added sigsetjmp test. + + * src/signal.cxx: Added siglongjmp(). + + * tests/sigsetjmp.c: Added this test for sigsetjmp(), siglongjmp() + functionality. This is also a test for longjmping out of signal + handlers. + + * tests/signal2.c: + Ifdeffed around cause_* functions to avoid compiler warnings when + they are not needed. + Changed CYG_TEST_NA() calls to CYG_TEST_INFO() and changed + CYG_TEST_FINISH() to CYG_TEST_PASS_FINISH(). With the _NA's there, + the first unsupported exception just terminates the program, and + does not give any subsequent supported ones a chance to run. + +2000-10-12 Jesper Skov + + * tests/timer1.c (main): Fix exit check. + +2000-10-11 Nick Garnett + + * src/pthread.cxx: Fixed cyg_posix_pthread_release_thread() to + work for _DETACHED threads as well as for _RUNNING ones. Also + fixed a bug in test to decrement counter in this routine. + + * src/pprivate.h: Added note about retaining numerical order of + PTHREAD_STATE_* defines. + + * tests/timer1.c: Fixed some bugs of the how-did-it-ever-work + variety. + +2000-10-05 Nick Garnett + + * src/misc.cxx: + Added a set of compatibility functions to aid portability and + improve standards compliance. + Added cyg_posix_function_[start|finish] to set up and terminate + POSIX API functionality wrt signal and cancellation behaviour. + (Lots more to do here). + + * include/export.h: + Added this file to contain definitions that can be exported from + the POSIX package to others. + + * src/pprivate.h: Added include of export.h + +2000-09-11 Jonathan Larmour + + * include/limits.h (OPEN_MAX): Don't define here - let FS infra do + that. + (LINK_MAX): Ditto + (NAME_MAX): Ditto + (PATH_MAX): Ditto + +2000-09-04 Nick Garnett + + * tests/pthread2.c: + * tests/pthread3.c: + Fixed bug in calculation of thread stack addresses. + + * src/misc.cxx (sysconf): Change zero returns to -1 when a feature + is not supported. + +2000-08-08 Jonathan Larmour + + * include/limits.h: Don't define SSIZE_MAX here, leave it to the + isoinfra default. + +2000-07-27 Jonathan Larmour + + * tests/signal2.c: NA if no setjmp/longjmp + +2000-07-26 Nick Garnett + + * include/pthread.h: + * src/pthread.cxx (pthread_testcancel): Reversed addition of cyg_ + to this symbol. + +2000-07-25 Jonathan Larmour + + * src/pthread.cxx: Define main_stack and main_thread as static + Rename pthread_canceled -> cyg_pthread_canceled - pthread_ may be + a reserved name space but this makes explicit it is implementation- + and not standard-defined + (PTHREAD_ENTRY_VOID): Define for funcs that take no args + (pthread_testcancel): Call PTHREAD_ENTRY_VOID() + + * include/pthread.h: Rename pthread_canceled -> cyg_pthread_canceled + +2000-07-20 Jonathan Larmour + + * src/pthread.cxx: Use isoinfra to determine presence of malloc() + Define pthread_malloc() and pthread_free() as inlines + + * cdl/posix.cdl: Shouldn't define _POSIX_MESSAGE_PASSING at all - that + happens in isoinfra. + +2000-07-20 Nick Garnett + + * cdl/posix.cdl: Added misc.cxx to compile list. Added option to + define _POSIX_MESSAGE_PASSING. Added configury for utsname + structure. + + * include/utsname.h: Added this file to define struct utsname and + uname() function prototype. + + * include/mqueue.h: Moved definition of _POSIX_MESSAGE_PASSING to + CDL. + + * include/limits.h: Added NGROUPS_MAX definition. + + * src/pthread.cxx: + Added support for malloced() thread stacks. + Added implementations of pthread_mutex_setprioceiling() and + pthread_mutex_getprioceiling(). + Changed implementations of pthread_mutex_destroy(), + pthread_mutex_lock() and pthread_mutex_trylock() to conform more + closely to the standard. + Changed pthread_key_create() to assign NULL to all valid thread + slots that correspond to a newly allocated key. + + * src/pprivate.h: Added freestack and stackmem members to manage + malloced thread stacks. + + * src/misc.cxx: Added this file to contain functions that do not + belong in any other files. Currently contains uname() and + sysconf(). + +2000-07-19 Jonathan Larmour + + * src/startup.cxx: Remove unnecessary includes + Use dummy object constructor to do initialization + + * cdl/posix.cdl: + Don't need main.cxx any more + Build startup.cxx into extras.o (via libextras.a) + + * cdl/pthread.cdl (CYGPKG_POSIX_MAIN_THREAD): + Integrate with CYGPKG_LIBC_STARTUP - tell CYGPKG_LIBC_STARTUP to + let pthreads set up main thread + + * src/pthread.cxx: Integrate with CYGPKG_LIBC_STARTUP rather than + calling main() directly. + Track number of threads waiting to be joined, so we can tell in + pthread_exit() if this is the last thread, and therefore whether + to call exit() + + * src/main.cxx: obsolete, removed + +2000-07-13 Nick Garnett + + * src/signal.cxx: Added ISO C compatibility functions signal() and + raise(). + +2000-06-21 Nick Garnett + + * src/pthread.cxx: Added for(;;) loop to end of pthread_exit(). + pthread_exit() is marked with the noreturn attribute, and without + this some compilers generate a call to abort() here in case + Cyg_Thread::exit() returns. The loop avoids this. + +2000-06-06 Jonathan Larmour + + * src/mqueue.cxx (mq_receive): Fix non-portable treatment of mode flags + (mq_send): Ditto + * tests/mqueue2.c (main): Ditto + +2000-05-24 Nick Garnett + + * tests/pthread2.c: Added this program to test per-thread data + handling. + + * tests/pthread3.c: Added this program to test execution of + cancellation handler. + + * src/pthread.cxx: Fixed some bugs revealed by new test programs. + + * cdl/posix.cdl: Added two new pthread tests. + +2000-05-22 Jonathan Larmour + + * cdl/posix.cdl (CYGPKG_POSIX): Require + CYGIMP_KERNEL_SCHED_SORTED_QUEUES + +2000-05-20 Jonathan Larmour + + * tests/mqueue1.c (cyg_user_start): Define correctly + * tests/mqueue2.c (cyg_user_start): Likewise + + * src/pprivate.h (cyg_sigqueue): Make struct sigevent * arg const since + it is, and it prevents warnings elsewhere + * src/signal.cxx (cyg_sigqueue): ditto + + * tests/signal2.c: Use CYG_TEST_NA, not CYG_TEST_INFO (otherwise + the test farm may fail the tests because there are no PASSes or NAs) + + * cdl/posix.cdl (CYGPKG_POSIX): We need errno and error codes, so + require them + Move some of the package implements into the components + Add message queue configuration, build mqueue.cxx and the mqueue1 and + mqueue2 tests + Move some calculated options into isoinfra, implemented as interfaces + so that unistd.h and limits.h can get the values + + * include/limits.h: Move _POSIX_* macros into isoinfra limits.h + since they are implementation independent + + * src/mqueue.cxx: Add POSIX message queue implementation + * tests/mqueue1.c, tests/mqueue2.c: and tests + +2000-05-18 Nick Garnett + + * src/pprivate.h: + * src/pthread.cxx: + * src/signal.cxx: + * src/time.cxx: + Added prioritization of static kernel objects. + +2000-05-17 Nick Garnett + + * src/pthread.cxx: + To reduce the static memory required by this code, the + pthread_info structure for a pthread is now allocated in the stack + memory for that thread, and not in a static table. The table is + now just an array of pointers. The per-thread data array is now + also allocated onto the stack only when first required. + + * include/pthread.h: Removed some redundant code. + + * include/limits.h: Added PTHREAD_STACK_OVERHEAD to record + management overhead imposed on POSIX threads stacks. This is added + to the HAL minimum requirement to generate PTHREAD_STACK_MIN. + + * src/pprivate.h (pthread_info): + * include/types.h (pthread_attr_t): Converted a number of integer + state and boolean fields to bitfields. + + * cdl/pthread.cdl: + Added requirement for CYGFUN_KERNEL_THREADS_STACK_LIMIT. + +2000-05-16 Nick Garnett + + * include/types.h: Added stacksize_valid to pthread_attr_t + structure. + + * include/signal.h: + Added SI_EXCEPT to mark any signals that were caused by an + exception. Removed conditions around SIGBUS. + + * src/startup.cxx (cyg_posix_start): + Added call to cyg_posix_exception_start(). + + * src/signal.cxx: + Rearranged cyg_deliver_signals() so that it is possible to + longjmp() out of a signal handler without leaving signal handling + code in an inconsistent state. + Added handling of SIG_IGN in sigaction(). + + * src/pthread.cxx: Added setting and checking of stacksize_valid. + + * src/pprivate.h: Added cyg_deliver_signals() as an export of + signal system. Added exports from except.cxx. + + * src/except.cxx: Added this file to handle delivery of exceptions + into the POSIX signal mechanism. + + * cdl/posix.cdl: Added except.cxx to compile list, added signal2 + to tests. Added requirement on kernel exception processing. + + * tests/tm_basic.cxx: Tidied up a compilation warning. + + * tests/signal2.c: Added this test for exception signal generation. + + * tests/mutex3.c: Fixed stupid bug. + +2000-05-10 Nick Garnett + + * src/pprivate.h: Added cyg_posix_clock_start() prototype. + + * src/startup.cxx: Added call to cyg_posix_clock_start(). + + * src/time.cxx: Added startup routine to initialize + converters. Fixed error result bug in timer_delete(). + + * include/signal.h: Removed some configuration tests which are now + done in CDL. + + * cdl/posix.cdl: Added configury for the signals component. Added + tm_basic to tests. + + * tests/tm_basic.cxx: + Added this POSIXized version of the tm_basic test. Note that this + has not been entirely converted. While the code being tested is + POSIX, the timing infrastructure remains a mish-mash of kernel, + KAPI and HAL code. + +2000-05-04 Nick Garnett + + * src/time.cxx: + Many changes to implement the delivery of signals on timer expiry. + Also added timer_delete(). + + * src/signal.cxx: + cyg_sigqueue() and cyg_deliver_signals() may now only be called + from within the context of a POSIX thread, either from an API call + or an ASR. + cyg_deliver_signals() can now cope with a signal that has + SA_SIGINFO set but no signals queued. It also determines + dynamically whether to lock the signal_mutex. + cyg_deliver_signals() is no longer called implicitly from + cyg_sigqueue() - so a number of expicit calls have been added. + + * src/sched.cxx: + Added this file to implement scheduling API. + + * src/pthread.cxx: + Moved priority translation macros to pprivate.h. + Removed errno handling, now done in isoinfra package. + Added iterative calls to per-thread data destructors. + + * src/pprivate.h: + Removed error field from pthread_info structure. + Moved priority translation macros here. + Removed prototype for cyg_deliver_signals(). + Added prototype for cyg_posix_timer_asr(). + + * include/time.h: Added timer_delete() which was mysteriously + omitted. + + * cdl/posix.cdl: Added sched.cxx to compile list and timer1.c to + tests. + + * tests/signal1.c: + * tests/pthread1.c: + Fixed bug in use of stack sizes. + + * tests/timer1.c: + Added test for use of timers. + +2000-05-02 Jonathan Larmour + + * include/sched.h: No longer needed - just use the default definition + in isoinfra + + * include/errno.h: No longer needed - errno provision now comes from + CYGPKG_ERROR + + * include/sys/types.h: Moved to include/types.h + + * cdl/posix.cdl, cdl/pthread.cdl: Put include files in cyg/posix, and + configure CYGPKG_ISOINFRA to include the appropriate headers + + * include/semaphore.h: Don't need to check kernel - including + pkgconf/kernel.h would already fail + Give SEM_FAILED a type so casting behaves in C++ + + * include/signal.h: This uses pid_t etc., so include + Add signal() and raise() prototypes (to allow libc compilation, even + though they aren't implemented yet) + + * include/time.h: Remove unnecessary includes. Move clockid_t and + timer_t definitions here from sys/types.h since this is where the + standard says they must live. + + * src/pprivate.h: Include signal.h and limits.h since their contents + are used later in the file. + +2000-04-28 Nick Garnett + + * src/signal.cxx: + Added implementations of alarm(), pause() and sleep(). + Modified cyg_sigqueue() so that it could be called from an ASR. + Added cyg_posix_signal_asr() to do signal processing in ASRs. + Miscellaneous bug fixes. + + * src/pthread.cxx: + Added pthread_count to count number of threads created. + Added call to signal ASR function in main ASR. + Added cyg_posix_pthread_release_thread() to seek out and kick a + thread to which a given set of signals may be delivered. + + * src/pprivate.h: + Added some more functions that are shared between POSIX + subsystems. + + * include/signal.h: + Added alarm(), pause() and sleep() prototypes. + + * tests/signal1.c: Added this test for various aspects of signal + handling. + + * cdl/posix.cdl: Added signal1 test. + +2000-04-20 Nick Garnett + + * src/signal.cxx: Added this file to contain signal handling code. + + * src/time.cxx: Made tick<->timespec converters exported to + rest of POSIX subsystem. Enabled interface to signal mechanism for + notifying timer expiration. + + * src/pthread.cxx: + Made pthread_mutex exported to rest of POSIX subsystem. + Exported pthread_info_id(). + Added thread init and destroy functions for signal subsystem. + + * src/startup.cxx: Added call to cyg_posix_signal_start(). + + * src/pprivate.h: Added signal handling fields support to + pthread_info structure. Added extra internal interfaces to support + signal handling code. + + * include/signal.h: Added _how_ argument values for the sigmask + functions. + + * cdl/posix.cdl: Added signal.cxx to compile list. + +2000-04-13 Nick Garnett + + * include/time.h: + * src/time.cxx: + Added implementation of clock and timer functions. These are + currently untested since they need working signals. + +2000-04-12 Nick Garnett + + * src/pprivate.h: Added cancellation support fields to + pthread_info structure. Made pthread_self_info() exported. + + * include/semaphore.h: Added SEM_FAILED plus misc. tidies. + + * include/pthread.h: Added PTHREAD_CANCELED. + + * include/errno.h: Fixed cyg_pthread_errno_p() return type. + + * src/pthread.cxx: + Added pthread_reap() to clean up exited threads. + Added support for cancellation. + Added cyg_posix_errno_p(). + + * src/time.cxx: + Added this file to implement time functionality. At present only + nanosleep() is actually implemented. + + * src/sem.cxx: + Added this file to implement semaphore functionality. + + * cdl/pthread.cdl: + Added some extra configuration requirements. + + * cdl/posix.cdl: + Added some more files to compile. + Added semaphore configuration. + + * tests/mutex3.c: + Added this test program. This is actually a POSIXized version of + Hugo's splendid kernel test of the same name. It exercises quite a + lot of the pthread infrastructure and is thus a good test to run. + + * tests/pthread1.c: + Added proper comment headers and added full testing stuff. + +2000-04-10 Nick Garnett + + * src/pprivate.h: + * src/pthread.cxx: + Added per-thread data support. + +2000-04-06 Nick Garnett + + * src/pthread.cxx: + Filled in implementations of lots of functions. + + * src/main.cxx: + Added this file to contain a default main. This is currenly just a + duplicate of the same file from the C library. Work is needed to + combine these. + + * include/sys/types.h: + Modified pthread_mutex_t to conform to kernel structure. + + * cdl/pthread.cdl: + Added support for main thread. + + * cdl/posix.cdl: + Added main.cxx to compile list. + +2000-03-31 Nick Garnett + + * cdl/pthread.cdl: + * cdl/posix.cdl: + Added CDL files to configure POSIX subsystem. + + * src/pprivate.h: + * src/pthread.cxx: + * src/startup.cxx: + Added these files to begin implementation of POSIX package. + + * include/pthread.h: + * include/sched.h: + * include/signal.h: + * include/time.h: + * include/sys/types.h: + Many changes needed by implementation work. + + * include/limits.h: + * include/errno.h: + Added these header files. + +2000-03-24 Nick Garnett + + * include/sys/types.h: + * include/time.h: + * include/sched.h: + * include/pthread.h: + * include/signal.h: + * include/semaphore.h: + * include/mqueue.h: + Roughed out (most of) the set of POSIX headers for the + functionality we are currently going to support. These files are + currently neither fully standard conformant nor implementation + ready. Much work is still needed to make them so. Watch this + space. + +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### diff --git a/packages/compat/posix/v2_0/cdl/posix.cdl b/packages/compat/posix/v2_0/cdl/posix.cdl new file mode 100644 index 00000000..86b3aa22 --- /dev/null +++ b/packages/compat/posix/v2_0/cdl/posix.cdl @@ -0,0 +1,317 @@ +# ==================================================================== +# +# posix.cdl +# +# POSIX layer configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): nickg +# Contributors: +# Date: 2000-3-28 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_POSIX { + display "POSIX compatibility layer" + description "This package enables the POSIX compatibility + layer that implements IEEE 1003.1." + doc ref/posix-compatibility.html + include_dir cyg/posix + + requires CYGPKG_KERNEL + requires CYGPKG_ISOINFRA + requires CYGPKG_ERROR + requires CYGINT_ISO_ERRNO + requires CYGINT_ISO_ERRNO_CODES + requires CYGIMP_KERNEL_SCHED_SORTED_QUEUES + + implements CYGINT_ISO_SCHED_IMPL + implements CYGINT_ISO_POSIX_LIMITS + implements CYGINT_ISO_PMUTEXTYPES + implements CYGINT_ISO_PTHREAD_MUTEX + requires { CYGBLD_ISO_POSIX_LIMITS_HEADER == \ + "" } + requires { CYGBLD_ISO_PMUTEXTYPES_HEADER == \ + "" } + requires { CYGBLD_ISO_PTHREAD_MUTEX_HEADER == \ + "" } + + compile mqueue.cxx mutex.cxx misc.cxx + compile -library=libextras.a startup.cxx + + cdl_option _POSIX_THREAD_PRIO_INHERIT { + display "POSIX mutex priority inheritance feature test macro" + flavor bool + default_value 1 + requires CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT + description "This option defines the POSIX feature test macro + for supporting priority inheritance protocol in + mutexes." + } + + cdl_option _POSIX_THREAD_PRIO_PROTECT { + display "POSIX mutex priority ceiling feature test macro" + flavor bool + default_value 1 + requires CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING + description "This option defines the POSIX feature test macro + for supporting priority ceiling protocol in mutexes." + } + + # ---------------------------------------------------------------- + # Scheduling component + + cdl_component CYGPKG_POSIX_SCHED { + display "POSIX scheduling configuration" + flavor bool + default_value 1 + description "This component provides controls over scheduling + in POSIX." + requires CYGPKG_POSIX_CLOCKS + compile sched.cxx + + cdl_option _POSIX_PRIORITY_SCHEDULING { + display "POSIX priority scheduling feature test macro" + flavor bool + calculated 1 + requires CYGSEM_KERNEL_SCHED_MLQUEUE + description "This option defines the POSIX feature test macro + that indicates that priority scheduling is present. + This should not be undefined." + } + } + + # ---------------------------------------------------------------- + # Pthreads component + + cdl_component CYGPKG_POSIX_PTHREAD { + display "POSIX pthread configuration" + flavor bool + default_value 1 + description "This component provides configuration controls for + the POSIX pthreads package." + compile pthread.cxx + script pthread.cdl + } + + # ---------------------------------------------------------------- + # Timers component + + cdl_option CYGPKG_POSIX_CLOCKS { + display "POSIX clocks" + flavor bool + default_value 1 + implements CYGINT_ISO_POSIX_CLOCK_TYPES + implements CYGINT_ISO_POSIX_CLOCKS + implements CYGINT_ISO_POSIX_SLEEP + requires { CYGBLD_ISO_POSIX_CLOCK_TYPES_HEADER == \ + "" } + requires { CYGBLD_ISO_POSIX_CLOCKS_HEADER == \ + "" } + requires CYGPKG_KERNEL + requires CYGVAR_KERNEL_COUNTERS_CLOCK + compile time.cxx + description "This component provides configuration controls for + the POSIX clocks." + } + + # ---------------------------------------------------------------- + # Timers component + + cdl_option CYGPKG_POSIX_TIMERS { + display "POSIX timers" + flavor bool + default_value 1 + implements CYGINT_ISO_POSIX_TIMER_TYPES + implements CYGINT_ISO_POSIX_TIMERS + implements CYGINT_ISO_POSIX_TIMER_OPS + requires { CYGBLD_ISO_POSIX_TIMER_TYPES_HEADER == \ + "" } + requires { CYGBLD_ISO_POSIX_TIMERS_HEADER == \ + "" } + requires CYGPKG_KERNEL + requires CYGVAR_KERNEL_COUNTERS_CLOCK + requires CYGPKG_POSIX_PTHREAD + requires CYGPKG_POSIX_CLOCKS + requires CYGPKG_POSIX_SIGNALS + description "This component provides configuration controls for + the POSIX timers." + } + + # ---------------------------------------------------------------- + # Semaphores component + + cdl_option CYGPKG_POSIX_SEMAPHORES { + display "POSIX semaphores" + flavor bool + default_value 1 + implements CYGINT_ISO_SEMAPHORES + requires { CYGBLD_ISO_SEMAPHORES_HEADER == \ + "" } + description "This component provides configuration controls for + POSIX semaphores." + + compile sem.cxx + } + + # ---------------------------------------------------------------- + # Message queues component + + cdl_component CYGPKG_POSIX_MQUEUES { + display "POSIX message queues" + flavor bool + default_value 1 + implements CYGINT_ISO_MQUEUE + requires CYGPKG_KERNEL + requires CYGINT_ISO_MALLOC + requires CYGINT_ISO_ERRNO + requires CYGINT_ISO_STRING_STRFUNCS + description "This component provides configuration controls for + POSIX message queues." + + cdl_option CYGNUM_POSIX_MQUEUE_OPEN_MAX { + display "Maximum number of message queues" + flavor data + default_value 8 + legal_values 1 to 999999 + } + + cdl_option CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR { + display "Validate queue descriptors" + flavor bool + default_value 1 + description " + This option turns on checking that message queue descriptors + (of type mqd_t) passed into mq_* functions are valid. If so, + the functions will fail with EBADF, as POSIX 1003.1 mandates. + If this option is disabled, if an invalid descriptor is used, + random corruption may occur, or the system may crash. If + you are confident invalid descriptors will not be used, + you may wish to be disable this to save some per-instance + memory and execution time." + } + + cdl_option CYGFUN_POSIX_MQUEUE_NOTIFY { + display "Allow empty queue notification" + flavor bool + requires CYGPKG_POSIX_SIGNALS + default_value CYGPKG_POSIX_SIGNALS + description " + Enabling this option adds the function mq_notify() to the + API. Without it, some code and per-message queue descriptor + space is saved, as well as no longer requiring POSIX realtime + signal support." + } + } + + # ---------------------------------------------------------------- + # Signals component + + cdl_component CYGPKG_POSIX_SIGNALS { + display "POSIX signals configuration" + flavor bool + default_value 1 + requires CYGPKG_KERNEL_EXCEPTIONS + requires CYGPKG_POSIX_PTHREAD + requires CYGPKG_POSIX_TIMERS + implements CYGINT_POSIX_REALTIME_SIGNALS + implements CYGINT_ISO_SIGSETJMP + requires { CYGBLD_ISO_SIGSETJMP_HEADER == \ + "" } + implements CYGINT_ISO_SIGNAL_NUMBERS + implements CYGINT_ISO_SIGNAL_IMPL + requires { CYGBLD_ISO_SIGNAL_NUMBERS_HEADER == \ + "" } + requires { CYGBLD_ISO_SIGNAL_IMPL_HEADER == \ + "" } + description "This component provides configuration controls for + the POSIX signals." + compile signal.cxx except.cxx + } + + # ---------------------------------------------------------------- + # uname structure component + + cdl_component CYGPKG_POSIX_UTSNAME { + display "POSIX utsname configuration" + flavor bool + default_value 1 + requires { CYGBLD_ISO_UTSNAME_HEADER == \ + "" } + description "This component provides configuration controls for + the POSIX utsname structure and the uname() function." + + cdl_option CYG_POSIX_UTSNAME_LENGTH { + display "Length of name strings in utsname structure" + flavor data + default_value 65 + legal_values 1 to 99999999 + } + + cdl_option CYG_POSIX_UTSNAME_NODENAME_LENGTH { + display "Length of nodename string in utsname structure" + flavor data + default_value { CYG_POSIX_UTSNAME_LENGTH } + legal_values 1 to 99999999 + } + + } + + # ---------------------------------------------------------------- + # Tests + + cdl_option CYGPKG_POSIX_TESTS { + display "POSIX tests" + flavor data + no_define + calculated { + "tests/pthread1 tests/pthread2 tests/pthread3 tests/mutex3 tests/mqueue2" + . ((CYGPKG_POSIX_SIGNALS) ? " tests/mqueue1 tests/signal1 tests/signal2 tests/signal3 tests/sigsetjmp tests/timer1 tests/tm_basic" : "") + } + description " + This option specifies the set of tests for the POSIX package." + } + +} + +# ==================================================================== +# End of posix.cdl + + diff --git a/packages/compat/posix/v2_0/cdl/pthread.cdl b/packages/compat/posix/v2_0/cdl/pthread.cdl new file mode 100644 index 00000000..d170356f --- /dev/null +++ b/packages/compat/posix/v2_0/cdl/pthread.cdl @@ -0,0 +1,197 @@ +# ==================================================================== +# +# pthread.cdl +# +# POSIX pthread configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): nickg +# Contributors: jlarmour +# Date: 2000-3-28 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_option CYGPKG_POSIX_PTHREAD_REQUIREMENTS { + display "Generic requirements of pthread package" + flavor bool + calculated 1 + implements CYGINT_ISO_PTHREADTYPES + implements CYGINT_ISO_PTHREAD_IMPL + requires CYGPKG_POSIX_SCHED + requires CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE + requires CYGSEM_KERNEL_SCHED_ASR_SUPPORT + requires CYGSEM_KERNEL_SCHED_ASR_GLOBAL + requires !CYGSEM_KERNEL_SCHED_ASR_DATA_GLOBAL + requires CYGFUN_KERNEL_THREADS_STACK_LIMIT + requires { CYGBLD_ISO_PTHREADTYPES_HEADER == \ + "" } + requires { CYGBLD_ISO_PTHREAD_IMPL_HEADER == \ + "" } + description "This option exists merely to carry the pthread + package requirements." + +} + +# ==================================================================== + +cdl_component CYGPKG_POSIX_PTHREAD_VALUES { + display "Constant values used in pthread package" + flavor bool + calculated 1 + description "These are values that are either configurable, or derived + from system parameters." + + cdl_option CYGNUM_POSIX_PTHREAD_DESTRUCTOR_ITERATIONS { + display "Maximum number of iterations of key destructors" + flavor data + legal_values 4 to 100 + default_value 4 + description "Maximum number of iterations of key destructors allowed." + } + + cdl_option CYGNUM_POSIX_PTHREAD_KEYS_MAX { + display "Maximum number of per-thread data keys allowed" + flavor data + legal_values 128 to 65535 + default_value 128 + description "Number of per-thread data keys supported." + } + + cdl_option CYGNUM_POSIX_PTHREAD_THREADS_MAX { + display "Maximum number of threads allowed" + flavor data + legal_values 64 to 1024 + default_value 64 + description "Maximum number of threads supported." + } + +} + +# ==================================================================== + +cdl_component CYGPKG_POSIX_PTHREAD_FEATURES { + display "Fixed Feature test macros for POSIX" + flavor bool + calculated 1 + description "These options define POSIX feature test macros that + describe the eCos implementation of pthreads. These + are not changeable configuration options." + + cdl_option _POSIX_THREADS { + display "POSIX thread support feature test macro" + flavor bool + calculated 1 + requires CYGSEM_KERNEL_SCHED_TIMESLICE + requires CYGVAR_KERNEL_THREADS_DATA + description "This option defines the POSIX feature test macro + for thread support." + } + + cdl_option _POSIX_THREAD_PRIORITY_SCHEDULING { + display "POSIX thread priority scheduling feature test macro" + flavor bool + calculated 1 + requires CYGSEM_KERNEL_SCHED_MLQUEUE + requires _POSIX_THREADS + description "This option defines the POSIX feature test macro + for thread priority scheduling support." + } + + cdl_option _POSIX_THREAD_ATTR_STACKADDR { + display "POSIX stack address attribute feature test macro" + flavor bool + calculated 1 + description "This option defines the POSIX feature test macro + for supporting the thread stack address in the thread + attribute object." + } + + cdl_option _POSIX_THREAD_ATTR_STACKSIZE { + display "POSIX stack size attribute feature test macro" + flavor bool + calculated 1 + description "This option defines the POSIX feature test macro + for supporting the thread stack size in the thread + attribute object." + } + + cdl_option _POSIX_THREAD_PROCESS_SHARED { + display "POSIX process shared attribute feature test macro" + flavor bool + calculated 0 + description "This option defines the POSIX feature test macro + for supporting process shared mutexes. Since eCos + does not have processes, this attribute is undefined." + } + +} + +# ==================================================================== + +cdl_component CYGPKG_POSIX_MAIN_THREAD { + display "Main thread configuration" + flavor bool + calculated 1 + requires { 0 != CYGPKG_LIBC_STARTUP } + requires CYGSEM_LIBC_STARTUP_MAIN_OTHER + implements CYGINT_LIBC_STARTUP_EXTERNAL_INVOKE_MAIN_POSSIBLE + description "These options control the thread used to + run the main() application entry routine." + + cdl_option CYGNUM_POSIX_MAIN_DEFAULT_PRIORITY { + display "main()'s default thread priority" + flavor data + legal_values 0 to 31 + default_value 16 + description " + POSIX compatibility requires that the application's + main() function be invoked in a thread. + This option controls the priority of that thread. This + priority is the POSIX priority and is NOT the same as + an eCos thread priority. With POSIX thread priorities, + lower numbers are lower priority, and higher numbers are + higher priority." + } +} + +# ==================================================================== +# End of pthread.cdl + + diff --git a/packages/compat/posix/v2_0/doc/posix.sgml b/packages/compat/posix/v2_0/doc/posix.sgml new file mode 100644 index 00000000..3434a81f --- /dev/null +++ b/packages/compat/posix/v2_0/doc/posix.sgml @@ -0,0 +1,1568 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +eCos POSIX compatibility layer + + +POSIX Standard Support + + + + + eCos contains support for the POSIX Specification (ISO/IEC + 9945-1)[POSIX]. + + + POSIX support is divided between the POSIX and the FILEIO + packages. The POSIX package provides support for threads, + signals, synchronization, timers and message queues. The FILEIO + package provides support for file and device I/O. The two + packages may be used together or separately, depending on + configuration. + + + This document takes a functional approach to the POSIX + library. Support for a function implies that the data types and + definitions necessary to support that function, and the objects + it manipulates, are also defined. Any exceptions to this are + noted, and unless otherwise noted, implemented functions behave + as specified in the POSIX standard. + + + This document only covers the differences between the eCos + implementation and the standard; it does not provide complete + documentation. For full information, see the POSIX standard + [POSIX]. Online, the Open Group Single Unix + Specification [SUS2] provides complete documentation + of a superset of POSIX. If you have access to a Unix system with + POSIX compatibility, then the manual pages for this will be of + use. There are also a number of books available. + [Lewine] covers the process, signal, file and I/O + functions, while [Lewis1], [Lewis2], + [Nichols] and [Norton] cover Pthreads and + related topics (see Bibliography, xref). However, many of these + books are oriented toward using POSIX in non-embedded systems, + so care should be taken in applying them to programming under + eCos. + + + The remainder of this chapter broadly follows the structure + of the POSIX Specification. References to the appropriate + section of the Standard are included. + + + Omitted functions marked with “// TBA” + are potential candidates for later implementation. + + + + + + +Process Primitives [POSIX Section 3] + + + + +Functions Implemented + + +int kill(pid_t pid, int sig); +int pthread_kill(pthread_t thread, int sig); +int sigaction(int sig, const struct sigaction *act, + struct sigaction *oact); +int sigqueue(pid_t pid, int sig, const union sigval value); +int sigprocmask(int how, const sigset_t *set, + sigset_t *oset); +int pthread_sigmask(int how, const sigset_t *set, + sigset_t *oset); +int sigpending(sigset_t *set); +int sigsuspend(const sigset_t *set); +int sigwait(const sigset_t *set, int *sig); +int sigwaitinfo(const sigset_t *set, siginfo_t *info); +int sigtimedwait(const sigset_t *set, siginfo_t *info, + const struct timespec *timeout); +int sigemptyset(sigset_t *set); +int sigfillset(sigset_t *set); +int sigaddset(sigset_t *set, int signo); +int sigdelset(sigset_t *set, int signo); +int sigismember(const sigset_t *set, int signo); +unsigned int alarm( unsigned int seconds ); +int pause( void ); +unsigned int sleep( unsigned int seconds ); + + + + + + +Functions Omitted + + +pid_t fork(void); +int execl( const char *path, const char *arg, ... ); +int execv( const char *path, char *const argv[] ); +int execle( const char *path, const char *arg, ... ); +int execve( const char *path, char *const argv[], + char *const envp[] ); +int execlp( const char *path, const char *arg, ... ); +int execvp( const char *path, char *const argv[] ); +int pthread_atfork( void(*prepare)(void), + void (*parent)(void), + void (*child)() ); +pid_t wait( int *stat_loc ); +pid_t waitpid( pid_t pid, int *stat_loc, + int options ); +void _exit( int status ); + + + + + + +Notes + + + + Signal handling may be enabled or disabled with the + CYGPKG_POSIX_SIGNALS option. Since signals are used + by other POSIX components, such as timers, disabling signals will + disable those components too. + + + + + + kill() and + sigqueue() may only take a + pid argument of zero, + which maps to the current process. + + + + + + The SIGEV_THREAD notification type is + not currently implemented. + + + + + + Job Control and Memory Protection signals are + not supported. + + + + + + An extra implementation defined + si_code value, + SI_EXCEPT, is defined to + distinguish hardware generated exceptions from + others. + + + + + + Extra signals are defined: + _SIGTRAP_,_SIGIOT_, + _SIGEMT_, and _SIGSYS_. These are + largely to maintain compatibility with the signal numbers used by + GDB. + + + + + + Signal delivery may currently occur at unexpected places in some + API functions. Using longjmp() to transfer + control out of a signal handler may result in the interrupted + function not being able to complete properly. This may result in + later function calls failing or deadlocking. + + + + + + + + + + + + +Process Environment [POSIX Section 4] + + + + +Functions Implemented + + +int uname( struct utsname *name ); +time_t time( time_t *tloc ); +char *getenv( const char *name ); +int isatty( int fd ); +long sysconf( int name ); + + + + + + +Functions Omitted + +pid_t getpid( void ); +pid_t getppid( void ); +uid_t getuid( void ); +uid_t geteuid( void ); +gid_t getgid( void ); +gid_t getegid( void ); +int setuid( uid_t uid ); +int setgid( gid_t gid ); +int getgroups( int gidsetsize, gid_t grouplist[] ); +char *getlogin( void ); +int getlogin_r( char *name, size_t namesize ); +pid_t getpgrp( void ); +pid_t setsid( void ); +int setpgid( pid_t pid, pid_t pgid ); +char *ctermid( char *s); +char *ttyname( int fd ); // TBA +int ttyname_r( int fd, char *name, size_t namesize); // TBA +clock_t times( struct tms *buffer ); // TBA + + + + + + +Notes + + + The fields of the utsname + structure are initialized as follows: + + sysname “eCos” + nodename “” (gethostname() is currently not available) + + release Major version number of the kernel + version Minor version number of the kernel + machine “” (Requires some config tool changes) + + + + The sizes of these strings are defined by + CYG_POSIX_UTSNAME_LENGTH and + CYG_POSIX_UTSNAME_NODENAME_LENGTH. The + latter defaults to the value of the former, but may also + be set independently to accommodate a longer node name. + + + + + + The time() function is currently + implemented in the C library. + + + + + A set of environment strings may be defined at configuration + time with the CYGDAT_LIBC_DEFAULT_ENVIRONMENT + option. The application may also define an environment by direct + assignment to the environ + variable. + + + + + + At present isatty() assumes that + any character device is a tty and that all other devices are not + ttys. Since the only kind of device that eCos currently supports + is serial character devices, this is an adequate + distinction. + + + + + + All system variables supported by sysconf will yield a + value. However, those that are irrelevant to eCos will + either return the default minimum defined in + <limits.h>, + or zero. + + + + + + + + + + + +Files and Directories [POSIX Section 5] + + + + +Functions Implemented + + +DIR *opendir( const char *dirname ); +struct dirent *readdir( DIR *dirp ); +int readdir_r( DIR *dirp, struct dirent *entry, + struct dirent **result ); +void rewinddir( DIR *dirp ); +int closedir( DIR *dirp ); +int chdir( const char *path ); +char *getcwd( char *buf, size_t size ); +int open( const char * path , int oflag , ... ); +int creat( const char * path, mode_t mode ); +int link( const char *existing, const char *new ); +int mkdir( const char *path, mode_t mode ); +int unlink( const char *path ); +int rmdir( const char *path ); +int rename( const char *old, const char *new ); +int stat( const char *path, struct stat *buf ); +int fstat( int fd, struct stat *buf ); +int access( const char *path, int amode ); +long pathconf(const char *path, int name); +long fpathconf(int fd, int name); + + + + + + +Functions Omitted + + +mode_t umask( mode_t cmask ); +int mkfifo( const char *path, mode_t mode ); +int chmod( const char *path, mode_t mode ); // TBA +int fchmod( int fd, mode_t mode ); // TBA +int chown( const char *path, uid_t owner, gid_t group ); +int utime( const char *path, const struct utimbuf *times ); // TBA +int ftruncate( int fd, off_t length ); // TBA + + + + + + +Notes + + + + + If a call to open() or creat() supplies + the third _mode_ parameter, it will + currently be ignored. + + + + + Most of the functionality of these functions depends on + the underlying filesystem. + + + + + Currently access() only checks the + F_OK mode explicitly, the others are + all assumed to be true by default. + + + + + The maximum number of open files allowed is supplied by + the CYGNUM_FILEIO_NFILE option. The maximum number + of file descriptors is supplied by the CYGNUM_FILEIO_NFD + option. + + + + + + + + + + +Input and Output [POSIX Section 6] + + + + +Functions Implemented + + +int dup( int fd ); +int dup2( int fd, int fd2 ); +int close(int fd); +ssize_t read(int fd, void *buf, size_t nbyte); +ssize_t write(int fd, const void *buf, size_t nbyte); +int fcntl( int fd, int cmd, ... ); +off_t lseek(int fd, off_t offset, int whence); +int fsync( int fd ); +int fdatasync( int fd ); + + + + + +Functions Omitted + +int pipe( int fildes[2] ); +int aio_read( struct aiocb *aiocbp ); // TBA +int aio_write( struct aiocb *aiocbp ); // TBA +int lio_listio( int mode, struct aiocb *const list[], + int nent, struct sigevent *sig); // TBA +int aio_error( struct aiocb *aiocbp ); // TBA +int aio_return( struct aiocb *aiocbp ); // TBA +int aio_cancel( int fd, struct aiocb *aiocbp ); // TBA +int aio_suspend( const struct aiocb *const list[], + int nent, const struct timespec *timeout ); // TBA +int aio_fsync( int op, struct aiocb *aiocbp ); +// TBA + + + + + + +Notes + + + + Only the F_DUPFD command + of fcntl() is currently implemented. + + + + + Most of the functionality of these functions depends on + the underlying filesystem. + + + + + + + + + + +Device and Class Specific Functions [POSIX Section 7] + + + + +Functions Implemented + +speed_t cfgetospeed( const struct termios *termios_p ); +int cfsetospeed( struct termios *termios_p, speed_t speed ); +speed_t cfgetispeed( const struct termios *termios_p ); +int cfsetispeed( struct termios *termios_p, speed_t speed ); +int tcgetattr( int fd, struct termios *termios_p ); +int tcsetattr( int fd, int optional_actions, + const struct termios *termios_p ); +int tcsendbreak( int fd, int duration ); +int tcdrain( int fd ); +int tcflush( int fd, int queue_selector ); +int tcsendbreak( int fd, int action ); + + + + + + +Functions Omitted + + +pid_t tcgetpgrp( int fd ); +int tcsetpgrp( int fd, pid_t pgrp ); + + + + + +Notes + + + + Only the functionality relevant to basic serial device + control is implemented. Only very limited support for + canonical input is provided, and then only via the + “tty” devices, not the “serial” + devices. None of the functionality relevant to job + control, controlling terminals and sessions is + implemented. + + + + + Only MIN = 0 and + TIME = 0 functionality is + provided. + + + + + Hardware flow control is supported if the underlying + device driver and serial port support it. + + + + + Support for break, framing and parity errors depends on + the functionality of the hardware and device driver. + + + + + + + + + + +C Language Services [POSIX Section 8] + + + + +Functions Implemented + +char *setlocale( int category, const char *locale ); +int fileno( FILE *stream ); +FILE *fdopen( int fd, const char *type ); +int getc_unlocked( FILE *stream); +int getchar_unlocked( void ); +int putc_unlocked( FILE *stream ); +int putchar_unlocked( void ); +char *strtok_r( char *s, const char *sep, + char **lasts ); +char *asctime_r( const struct tm *tm, char *buf ); +char *ctime_r( const time_t *clock, char *buf ); +struct tm *gmtime_r( const time_t *clock, + struct tm *result ); +struct tm *localtime_r( const time_t *clock, + struct tm *result ); +int rand_r( unsigned int *seed ); + + + + + + +Functions Omitted + +void flockfile( FILE *file ); +int ftrylockfile( FILE *file ); +void funlockfile( FILE *file ); +int sigsetjmp( sigjmp_buf env, int savemask ); // TBA +void siglongjmp( sigjmp_buf env, int val ); // TBA +void tzset(void); // TBA + + + + + + +Notes + + + + setlocale() is implemented in the C + library Internationalization package. + + + + + Functions fileno() and + fdopen() are implemented in the C + library STDIO package. + + + + + Functions getc_unlocked(), + getchar_unlocked(), + putc_unlocked() and + putchar_unlocked() are defined + but are currently identical to their non-unlocked + equivalents. + + + + + strtok_r(), asctime_r(), + ctime_r(), gmtime_r(), + localtime_r() and + rand_r() are all currently in + the C library, alongside their non-reentrant versions. + + + + + + + + + + +System Databases [POSIX Section 9] + + + + +Functions Implemented + + +<none> + + + + + + + +Functions Omitted + + +struct group *getgrgid( gid_t gid ); +int getgrgid( gid_t gid, struct group *grp, char *buffer, + size_t bufsize, struct group **result ); +struct group *getgrname( const char *name ); +int getgrname_r( const char *name, struct group *grp, + char *buffer, size_t bufsize, struct group **result ); +struct passwd *getpwuid( uid_t uid ); +int getpwuid_r( uid_t uid, struct passwd *pwd, + char *buffer, size_t bufsize, struct passwd **result ); +struct passwd *getpwnam( const char *name ); +int getpwnam_r( const char *name, struct passwd *pwd, + char *buffer, size_t bufsize, struct passwd **result ); + + + + + + +Notes + + + + None of the functions in this section are implemented. + + + + + + + + + + +Data Interchange Format [POSIX Section 10] + + +This section details tar and +cpio formats. Neither of these is supported by +eCos. + + + + + + + +Synchronization [POSIX Section 11] + + + + + +Functions Implemented + + +int sem_init(sem_t *sem, int pshared, unsigned int value); +int sem_destroy(sem_t *sem); +int sem_wait(sem_t *sem); +int sem_trywait(sem_t *sem); +int sem_post(sem_t *sem); +int sem_getvalue(sem_t *sem, int *sval); +int pthread_mutexattr_init( pthread_mutexattr_t *attr); +int pthread_mutexattr_destroy( pthread_mutexattr_t *attr); +int pthread_mutex_init(pthread_mutex_t *mutex, + const pthread_mutexattr_t *mutex_attr); +int pthread_mutex_destroy(pthread_mutex_t *mutex); +int pthread_mutex_lock(pthread_mutex_t *mutex); +int pthread_mutex_trylock(pthread_mutex_t *mutex); +int pthread_mutex_unlock(pthread_mutex_t *mutex); +int pthread_condattr_init(pthread_condattr_t *attr); +int pthread_condattr_destroy(pthread_condattr_t *attr); +int pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *attr); +int pthread_cond_destroy(pthread_cond_t *cond); +int pthread_cond_signal(pthread_cond_t *cond); +int pthread_cond_broadcast(pthread_cond_t *cond); +int pthread_cond_wait(pthread_cond_t *cond, + pthread_mutex_t *mutex); +int pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); + + + + + + +Functions Omitted + + +sem_t *sem_open(const char *name, int oflag, ...); // TBA +int sem_close(sem_t *sem); // TBA +int sem_unlink(const char *name); // TBA +int pthread_mutexattr_getpshared( const pthread_mutexattr_t *attr, + int *pshared ); +int pthread_mutexattr_setpshared( const pthread_mutexattr_t *attr, + int pshared ); +int pthread_condattr_getpshared( const pthread_condattr_t *attr, + int *pshared); +int pthread_condattr_setpshared( const pthread_condattr_t *attr, + int pshared); + + + + + +Notes + + + + The presence of semaphores is controlled by the + CYGPKG_POSIX_SEMAPHORES option. This in turn + causes the _POSIX_SEMAPHORES feature test + macro to be defined and the semaphore API to be made + available. + + + + + + The pshared argument to + sem_init() is not implemented, + its value is ignored. + + + + + + Functions sem_open(), + sem_close() and + sem_unlink() are present but + always return an error (ENOSYS). + + + + + + The exact priority inversion protocols supported may be + controlled with the + _POSIX_THREAD_PRIO_INHERIT and + _POSIX_THREAD_PRIO_PROTECT + configuration options. + + + + + + {_POSIX_THREAD_PROCESS_SHARED} is + not defined, so the + process-shared mutex + and condition variable attributes are not supported, and + neither are the functions + pthread_mutexattr_getpshared(), + pthread_mutexattr_setpshared(), + pthread_condattr_getpshared() and + pthread_condattr_setpshared(). + + + + + + Condition variables do not become bound to a particular + mutex when + pthread_cond_wait() is + called. Hence different threads may wait on a condition + variable with different mutexes. This is at variance with + the standard, which requires a condition variable to + become (dynamically) bound by the first waiter, and + unbound when the last finishes. However, this difference + is largely benign, and the cost of policing this feature + is non-trivial. + + + + + + + + + + +Memory Management [POSIX Section 12] + + + + +Functions Implemented + + +<none> + + + + + + +Functions Omitted + + +int mlockall( int flags ); +int munlockall( void ); +int mlock( const void *addr, size_t len ); +int munlock( const void *addr, size_t len ); +void mmap( void *addr, size_t len, int prot, int flags, + int fd, off_t off ); +int munmap( void *addr, size_t len ); +int mprotect( const void *addr, size_t len, int prot ); +int msync( void *addr, size_t len, int flags ); +int shm_open( const char *name, int oflag, mode_t mode ); +int shm_unlink( const char *name ); + + + + + + +Notes + +None of these functions are currently provided. Some may +be implemented in a restricted form in the future. + + + + + + + + + +Execution Scheduling [POSIX Section 13] + + + + +Functions Implemented + + +int sched_yield(void); +int sched_get_priority_max(int policy); +int sched_get_priority_min(int policy); +int sched_rr_get_interval(pid_t pid, struct timespec *t); +int pthread_attr_setscope(pthread_attr_t *attr, int scope); +int pthread_attr_getscope(const pthread_attr_t *attr, int *scope); +int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit); +int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit); +int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); +int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy); +int pthread_attr_setschedparam( pthread_attr_t *attr, const struct sched_param *param); +int pthread_attr_getschedparam( const pthread_attr_t *attr, + struct sched_param *param); +int pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param); +int pthread_getschedparam(pthread_t thread, int *policy, + struct sched_param *param); +int pthread_mutexattr_setprotocol( pthread_mutexattr_t *attr, + int protocol); +int pthread_mutexattr_getprotocol( pthread_mutexattr_t *attr, + int *protocol); +int pthread_mutexattr_setprioceiling( pthread_mutexattr_t *attr, + int prioceiling); +int pthread_mutexattr_getprioceiling( pthread_mutexattr_t *attr, + int *prioceiling); +int pthread_mutex_setprioceiling( pthread_mutex_t *mutex, + int prioceiling, + int *old_ceiling); +int pthread_mutex_getprioceiling( pthread_mutex_t *mutex, + int *prioceiling); + + + + + + +Functions Omitted + + +int sched_setparam(pid_t pid, const struct sched_param *param); +int sched_getparam(pid_t pid, struct sched_param *param); +int sched_setscheduler(pid_t pid, int policy, + const struct sched_param *param); +int sched_getscheduler(pid_t pid); + + + + + + +Notes + + + + The functions sched_setparam(), + sched_getparam(), + sched_setscheduler() and + sched_getscheduler() are present + but always return an error. + + + + + The scheduler policy SCHED_OTHER is + equivalent to SCHED_RR. + + + + + Only PTHREAD_SCOPE_SYSTEM + is supported as a + contentionscope + attribute. + + + + + The default thread scheduling attributes are: + + contentionscope PTHREAD_SCOPE_SYSTEM + inheritsched PTHREAD_INHERIT_SCHED + schedpolicy SCHED_OTHER + schedparam.sched 0 + + + + + + Mutex priority inversion protection is controlled by a + number of kernel configuration options. + If CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT + is defined then + {_POSIX_THREAD_PRIO_INHERIT} + will be defined and PTHREAD_PRIO_INHERIT may + be set as the protocol in a + pthread_mutexattr_t + object. + If CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING + is defined then + {_POSIX_THREAD_PRIO_PROTECT} + will be defined and PTHREAD_PRIO_PROTECT may + be set as the protocol in a + pthread_mutexattr_t object. + + + + + The default attribute values set by + pthread_mutexattr_init() + is to set the protocol attribute to + PTHREAD_PRIO_NONE and the prioceiling + attribute to zero. + + + + + + + + + + + +Clocks and Timers [POSIX Section 14] + + + + +Functions Implemented + + +int clock_settime( clockid_t clock_id, +const struct timespec *tp); +int clock_gettime( clockid_t clock_id, struct timespec *tp); +int clock_getres( clockid_t clock_id, struct timespec *tp); +int timer_create( clockid_t clock_id, struct sigevent *evp, + timer_t *timer_id); +int timer_delete( timer_t timer_id ); +int timer_settime( timer_t timerid, int flags, + const struct itimerspec *value, + struct itimerspec *ovalue ); +int timer_gettime( timer_t timerid, struct itimerspec *value ); +int timer_getoverrun( timer_t timerid ); +int nanosleep( const struct timespec *rqtp, struct timespec *rmtp); + + + + + + + + +Functions Omitted + + +<none> + + + + + + + +Notes + + + + + Currently timer_getoverrun() only + reports timer notifications that are delayed in the timer + subsystem. If they are delayed in the signal subsystem, due to + signal masks for example, this is not counted as an overrun. + + + + + + The option CYGPKG_POSIX_TIMERS allows the timer support to be + enabled or disabled, and causes _POSIX_TIMERS to be defined + appropriately. This will cause other parts of the POSIX system to + have limited functionality. + + + + + + + + + + + + +Message Passing [POSIX Section 15] + + + + +Functions Implemented + + +mqd_t mq_open( const char *name, int oflag, ... ); +int mq_close( mqd_t mqdes ); +int mq_unlink( const char *name ); +int mq_send( mqd_t mqdes, const char *msg_ptr, + size_t msg_len, unsigned int msg_prio ); +ssize_t mq_receive( mqd_t mqdes, char *msg_ptr, + size_t msg_len, unsigned int *msg_prio ); +int mq_setattr( mqd_t mqdes, const struct mq_attr *mqstat, + struct mq_attr *omqstat ); +int mq_getattr( mqd_t mqdes, struct mq_attr *mqstat ); +int mq_notify( mqd_t mqdes, const struct sigevent *notification ); + +From POSIX 1003.1d draft: + +int mq_send( mqd_t mqdes, const char *msg_ptr, + size_t msg_len, unsigned int msg_prio, + const struct timespec *abs_timeout ); +ssize_t mq_receive( mqd_t mqdes, char *msg_ptr, + size_t msg_len, unsigned int *msg_prio, + const struct timespec *abs_timeout ); + + + + + + +Functions Omitted + + +<none> + + + + + + + +Notes + + + + + The presence of message queues is controlled by the + CYGPKG_POSIX_MQUEUES option. Setting this will + cause [_POSIX_MESSAGE_PASSING] to + be defined and the message queue API to be made available. + + + + + + Message queues are not currently filesystem objects. They live in + their own name and descriptor spaces. + + + + + + + + + + + +Thread Management [POSIX Section 16] + + + + +Functions Implemented + + +int pthread_attr_init(pthread_attr_t *attr); +int pthread_attr_destroy(pthread_attr_t *attr); +int pthread_attr_setdetachstate(pthread_attr_t *attr, + int detachstate); +int pthread_attr_getdetachstate(const pthread_attr_t *attr, + int *detachstate); +int pthread_attr_setstackaddr(pthread_attr_t *attr, + void *stackaddr); +int pthread_attr_getstackaddr(const pthread_attr_t *attr, + void **stackaddr); +int pthread_attr_setstacksize(pthread_attr_t *attr, + size_t stacksize); +int pthread_attr_getstacksize(const pthread_attr_t *attr, + size_t *stacksize); +int pthread_create( pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), + void *arg); +pthread_t pthread_self( void ); +int pthread_equal(pthread_t thread1, pthread_t thread2); +void pthread_exit(void *retval); +int pthread_join(pthread_t thread, void **thread_return); +int pthread_detach(pthread_t thread); +int pthread_once(pthread_once_t *once_control, + void (*init_routine)(void)); + + + + + + + +Functions Omitted + + +<none> + + + + + + + +Notes + + + + + The presence of thread support as a whole is controlled by the the + CYGPKG_POSIX_PTHREAD configuration option. Note that disabling + this will also disable many other features of the POSIX package, + since these are intimately bound up with the thread mechanism. + + + + + + The default (non-scheduling) thread attributes are: + + + detachstate PTHREAD_CREATE_JOINABLE + stackaddr unset + stacksize unset + + + + + + Dynamic thread stack allocation is only provided if there is an + implementation of + malloc() configured (i.e. a package + implements the + CYGINT_MEMALLOC_MALLOC_ALLOCATORS + interface). If there is no malloc() available, then the thread + creator must supply a stack. If only a stack address is supplied + then the stack is assumed to be PTHREAD_STACK_MIN + bytes long. This size is seldom useful for any but the most + trivial of threads. If a different sized stack is used, both + the stack address and stack size must be supplied. + + + + + + The value of PTHREAD_THREADS_MAX is supplied by + the CYGNUM_POSIX_PTHREAD_THREADS_MAX + option. This defines the maximum number of threads allowed. The + POSIX standard requires this value to be at least 64, and this + is the default value set. + + + + + + When the POSIX package is installed, the thread that calls + main() is initialized as a POSIX thread. The + priority of that thread is controlled by the + CYGNUM_POSIX_MAIN_DEFAULT_PRIORITY option. + + + + + + + + + + + +Thread-Specific Data [POSIX Section 17] + + + + +Functions Implemented + + +int pthread_key_create(pthread_key_t *key, + void (*destructor)(void *)); +int pthread_setspecific(pthread_key_t key, const void *pointer); +void *pthread_getspecific(pthread_key_t key); +int pthread_key_delete(pthread_key_t key); + + + + + + + +Functions Omitted + +<none> + + + + + + +Notes + + + + + The value of PTHREAD_DESTRUCTOR_ITERATIONS is + provided by the + CYGNUM_POSIX_PTHREAD_DESTRUCTOR_ITERATIONS + option. This controls the number of times that a key destructor + will be called while the data item remains non-NULL. + + + + + + The value of PTHREAD_KEYS_MAX is provided + by the CYGNUM_POSIX_PTHREAD_KEYS_MAX + option. This defines the maximum number of per-thread data items + supported. The POSIX standard calls for this to be a minimum of + 128, which is rather large for an embedded system. The default + value for this option is set to 128 for compatibility but it + should be reduced to a more usable value. + + + + + + + + + + + +Thread Cancellation [POSIX Section 18] + + + + +Functions Implemented + + +int pthread_cancel(pthread_t thread); +int pthread_setcancelstate(int state, int *oldstate); +int pthread_setcanceltype(int type, int *oldtype); +void pthread_testcancel(void); +void pthread_cleanup_push( void (*routine)(void *), + void *arg); +void pthread_cleanup_pop( int execute); + + + + + + + +Functions Omitted + +<none> + + + + + + +Notes + +Asynchronous cancellation is only partially implemented. In +particular, cancellation may occur in unexpected places in some +functions. It is strongly recommended that only synchronous +cancellation be used. + + + + + + + + +Non-POSIX Functions + + +In addition to the standard POSIX functions defined above, the +following non-POSIX functions are defined in the FILEIO package. + + + + + +General I/O Functions + +int ioctl( int fd, CYG_ADDRWORD com, CYG_ADDRWORD data ); +int select( int nfd, fd_set *in, fd_set *out, fd_set *ex, struct timeval *tv); + + + + + + + +Socket Functions + +int socket( int domain, int type, int protocol); +int bind( int s, const struct sockaddr *sa, unsigned int len); +int listen( int s, int len); +int accept( int s, struct sockaddr *sa, socklen_t *addrlen); +int connect( int s, const struct sockaddr *sa, socklen_t len); +int getpeername( int s, struct sockaddr *sa, socklen_t *len); +int getsockname( int s, struct sockaddr *sa, socklen_t *len); +int setsockopt( int s, int level, int optname, const void *optval, + socklen_t optlen); +int getsockopt( int s, int level, int optname, void *optval, + socklen_t *optlen); +ssize_t recvmsg( int s, struct msghdr *msg, int flags); +ssize_t recvfrom( int s, void *buf, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +ssize_t recv( int s, void *buf, size_t len, int flags); +ssize_t sendmsg( int s, const struct msghdr *msg, int flags); +ssize_t sendto( int s, const void *buf, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen); +ssize_t send( int s, const void *buf, size_t len, int flags); +int shutdown( int s, int how); + + + + + + +Notes + + + + The precise behaviour of these functions depends mainly on the + functionality of the underlying filesystem or network stack to + which they are applied. + + + + + + + + + + + + + +References and Bibliography + + + [Lewine] + + Donald + A. + Lweine + + Posix Programmer’s Guide: Writing Portable Unix + Programs With the POSIX.1 Standard O’Reilly & + Associates; ISBN: 0937175730. + + + [Lewis1] + + Bil + Lewis + + + Daniel + J. + Berg + + Threads Primer: A Guide to Multithreaded Programming + Prentice Hall + ISBN: 013443698 + + + + [Lewis2] + + Bil + Lewis + + + Daniel + J. + Berg + + Multithreaded Programming With Pthreads + + Prentice Hall Computer Books + + ISBN: 0136807291 + + + + [Nichols] + + Bradford + Nichols + + + Dick + Buttlar + + + Jacqueline + Proulx + Farrell + + Pthreads Programming: A POSIX Standard for Better + Multiprocessing (O’Reilly Nutshell) + O’Reilly & Associates + + ISBN: 1565921151 + + + + [Norton] + + Scott + J. + Norton + + + Mark + D. + Depasquale + + Thread Time: The MultiThreaded Programming Guide + Prentice Hall + + ISBN: 0131900676 + + + + [POSIX] + Portable Operating System Interface(POSIX) - +Part 1: System Application Programming Interface (API)[C +Language] + ISO/IEC 9945-1:1996, IEEE + + + [SUS2] + Open Group; Single Unix Specification, Version 2 + http://www.opengroup.org/public/pubs/online/7908799/index.html + + + + + + + diff --git a/packages/compat/posix/v2_0/include/export.h b/packages/compat/posix/v2_0/include/export.h new file mode 100644 index 00000000..36edf0d5 --- /dev/null +++ b/packages/compat/posix/v2_0/include/export.h @@ -0,0 +1,114 @@ +#ifndef CYGONCE_POSIX_EXPORT_H +#define CYGONCE_POSIX_EXPORT_H +//============================================================================= +// +// export.h +// +// POSIX export header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2002 Nick Garnett +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-09-18 +// Purpose: POSIX export header +// Description: This header contains definitions that the POSIX package exports +// to other packages. These are generally interfaces that are not +// provided by the public API. +// +// +// Usage: +// #ifdef CYGPKG_POSIX +// #include +// #endif +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include + +#include + +#include // NULL, size_t + +#include +#include + +#include + +#include // SCHED_* + +//============================================================================= +// POSIX API function management. +// These macros should be inserted near the start and all returns of +// any function that is part of the POSIX API. + +__externC void cyg_posix_function_start(); +__externC void cyg_posix_function_finish(); + +#define CYG_POSIX_FUNCTION_START() cyg_posix_function_start() + +#define CYG_POSIX_FUNCTION_FINISH() cyg_posix_function_finish() + +//----------------------------------------------------------------------------- +// Signal mask management +// +// These are exported to allow functions in other packages to +// manipulate the current threads signal mask. they are currently only +// used in the implementation of cyg_pselect() in the FILEIO package. + +#ifdef CYGPKG_POSIX_SIGNALS +__externC void cyg_pthread_sigmask_set (const sigset_t *set, sigset_t *oset); +__externC cyg_bool cyg_posix_sigpending(void); +__externC void cyg_posix_deliver_signals(const sigset_t *mask); + +#define CYG_PTHREAD_SIGMASK_SET cyg_pthread_sigmask_set + +#define CYG_POSIX_SIGPENDING() cyg_posix_sigpending() + +#define CYG_POSIX_DELIVER_SIGNALS cyg_posix_deliver_signals +#endif + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_POSIX_EXPORT_H +// End of export.h diff --git a/packages/compat/posix/v2_0/include/limits.h b/packages/compat/posix/v2_0/include/limits.h new file mode 100644 index 00000000..2974ba14 --- /dev/null +++ b/packages/compat/posix/v2_0/include/limits.h @@ -0,0 +1,131 @@ +#ifndef CYGONCE_LIMITS_H +#define CYGONCE_LIMITS_H +//============================================================================= +// +// limits.h +// +// POSIX limits header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-03-17 +// Purpose: POSIX limits header +// Description: This file contains the compile time definitions that describe +// the minima and current values of various values and defined +// in POSIX.1 section 2.8. +// +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + +//----------------------------------------------------------------------------- +// Runtime invariants +// These are all equal to or greater than the minimum values defined above. + +// From table 2-4 + +#define NGROUPS_MAX _POSIX_NGROUPS_MAX + +// From table 2-5 + +#define AIO_LISTIO_MAX _POSIX_AIO_LISTIO_MAX + +#define AIO_MAX _POSIX_AIO_MAX + +#define AIO_PRIO_DELTA_MAX 0 + +#define ARG_MAX _POSIX_ARG_MAX + +#define CHILD_MAX _POSIX_CHILD_MAX + +#define DELAYTIMER_MAX _POSIX_DELAYTIMER_MAX + +#define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX + +#define PAGESIZE 1 + +#define PTHREAD_DESTRUCTOR_ITERATIONS CYGNUM_POSIX_PTHREAD_DESTRUCTOR_ITERATIONS + +#define PTHREAD_KEYS_MAX CYGNUM_POSIX_PTHREAD_KEYS_MAX + +// Minimum size needed on a pthread stack to contain its per-thread control +// structures and per-thread data. Since we cannot include all the headers +// necessary to calculate this value here, the following is a generous estimate. +#define PTHREAD_STACK_OVERHEAD (0x180+(PTHREAD_KEYS_MAX*sizeof(void *))) + +#define PTHREAD_STACK_MIN (CYGNUM_HAL_STACK_SIZE_MINIMUM+PTHREAD_STACK_OVERHEAD) + +#define PTHREAD_THREADS_MAX CYGNUM_POSIX_PTHREAD_THREADS_MAX + +#define RTSIG_MAX _POSIX_RTSIG_MAX + +#define SEM_NSEMS_MAX _POSIX_SEM_NSEMS_MAX + +#define SEM_VALUE_MAX _POSIX_SEM_VALUE_MAX + +#define SIGQUEUE_MAX _POSIX_SIGQUEUE_MAX + +#define STREAM_MAX _POSIX_STREAM_MAX + +#define TIMER_MAX _POSIX_TIMER_MAX + +#define TTY_NAME_MAX _POSIX_TTY_NAME_MAX + +#define TZNAME_MAX _POSIX_TZNAME_MAX + + +// From table 2-6. + +#define MAX_CANON _POSIX_MAX_CANON + +#define MAX_INPUT _POSIX_MAX_INPUT + +#define PIPE_BUF _POSIX_PIPE_BUF + + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_LIMITS_H +// End of limits.h diff --git a/packages/compat/posix/v2_0/include/mutex.h b/packages/compat/posix/v2_0/include/mutex.h new file mode 100644 index 00000000..687479e5 --- /dev/null +++ b/packages/compat/posix/v2_0/include/mutex.h @@ -0,0 +1,172 @@ +#ifndef CYGONCE_POSIX_MUTEX_H +#define CYGONCE_POSIX_MUTEX_H +//============================================================================= +// +// mutex.h +// +// POSIX mutex and condition variable function definitions +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg,jlarmour +// Contributors: +// Date: 2001-09-10 +// Purpose: POSIX mutex and condition variable function definitions +// Description: This header contains POSIX API definitions for mutexes +// and cond vars. +// +// Usage: #include +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + +#include // pthread_* types + +//============================================================================= +// Mutexes + +//----------------------------------------------------------------------------- +// Mutex attributes manipulation functions + +// Initialize attribute object +externC int pthread_mutexattr_init ( pthread_mutexattr_t *attr); + +// Destroy attribute object +externC int pthread_mutexattr_destroy ( pthread_mutexattr_t *attr); + +#if defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT) + +// Set priority inversion protection protocol +externC int pthread_mutexattr_setprotocol ( pthread_mutexattr_t *attr, + int protocol); + +// Get priority inversion protection protocol +externC int pthread_mutexattr_getprotocol ( pthread_mutexattr_t *attr, + int *protocol); + +#if defined(_POSIX_THREAD_PRIO_PROTECT) + +// Set priority for priority ceiling protocol +externC int pthread_mutexattr_setprioceiling ( pthread_mutexattr_t *attr, + int prioceiling); + +// Get priority for priority ceiling protocol +externC int pthread_mutexattr_getprioceiling ( pthread_mutexattr_t *attr, + int *prioceiling); + +// Set priority ceiling of given thread, returning old ceiling. +externC int pthread_mutex_setprioceiling( pthread_mutex_t *mutex, + int prioceiling, + int *old_ceiling); + +// Get priority ceiling of given thread +externC int pthread_mutex_getprioceiling( pthread_mutex_t *mutex, + int *prioceiling); +#endif + +#endif + +//----------------------------------------------------------------------------- +// Mutex functions + +// Initialize mutex. If mutex_attr is NULL, use default attributes. +externC int pthread_mutex_init (pthread_mutex_t *mutex, + const pthread_mutexattr_t *mutex_attr); + +// Destroy mutex. +externC int pthread_mutex_destroy (pthread_mutex_t *mutex); + +// Lock mutex, waiting for it if necessary. +externC int pthread_mutex_lock (pthread_mutex_t *mutex); + +// Try to lock mutex. +externC int pthread_mutex_trylock (pthread_mutex_t *mutex); + + +// Unlock mutex. +externC int pthread_mutex_unlock (pthread_mutex_t *mutex); + + + +//============================================================================= +// Condition Variables + +//----------------------------------------------------------------------------- +// Attribute manipulation functions +// We do not actually support any attributes at present, so these do nothing. + +// Initialize condition variable attributes +externC int pthread_condattr_init (pthread_condattr_t *attr); + +// Destroy condition variable attributes +externC int pthread_condattr_destroy (pthread_condattr_t *attr); + +//----------------------------------------------------------------------------- +// Condition variable functions + +// Initialize condition variable. +externC int pthread_cond_init (pthread_cond_t *cond, + const pthread_condattr_t *attr); + +// Destroy condition variable. +externC int pthread_cond_destroy (pthread_cond_t *cond); + +// Wake up one thread waiting for condition variable +externC int pthread_cond_signal (pthread_cond_t *cond); + +// Wake up all threads waiting for condition variable +externC int pthread_cond_broadcast (pthread_cond_t *cond); + +// Block on condition variable until signalled. The mutex is +// assumed to be locked before this call, will be unlocked +// during the wait, and will be re-locked on wakeup. +externC int pthread_cond_wait (pthread_cond_t *cond, + pthread_mutex_t *mutex); + +// Block on condition variable until signalled, or the timeout expires. +externC int pthread_cond_timedwait (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); + + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_POSIX_MUTEX_H +// End of mutex.h diff --git a/packages/compat/posix/v2_0/include/muttypes.h b/packages/compat/posix/v2_0/include/muttypes.h new file mode 100644 index 00000000..91ddc867 --- /dev/null +++ b/packages/compat/posix/v2_0/include/muttypes.h @@ -0,0 +1,138 @@ +#ifndef CYGONCE_POSIX_MUTTYPES_H +#define CYGONCE_POSIX_MUTTYPES_H +//============================================================================= +// +// muttypes.h +// +// POSIX mutex types header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg,jlarmour +// Date: 2000-03-17 +// Purpose: POSIX types header +// Description: This header contains POSIX type definitions for mutexes +// and cond vars. These types are implementation defined. +// +// Usage: #include +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include + +#include + +//----------------------------------------------------------------------------- +// Mutex object +// This structure must exactly correspond in size and layout to the underlying +// eCos C++ class that implements this object. Because we have to support +// PTHREAD_MUTEX_INITIALIZER we cannot abstract this object very easily. + +typedef struct +{ + CYG_WORD32 locked; + CYG_ADDRESS owner; + CYG_ADDRESS queue; + +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC + CYG_WORD32 protocol; // this mutex's protocol +#endif + +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING + CYG_WORD32 ceiling; // mutex priority ceiling +#endif + +} pthread_mutex_t; + +#if defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC) &&\ + defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING) +#define PTHREAD_MUTEX_INITIALIZER { 0, 0, 0, 0, 0 } +#elif defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC) ||\ + defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING) +#define PTHREAD_MUTEX_INITIALIZER { 0, 0, 0, 0 } +#else +#define PTHREAD_MUTEX_INITIALIZER { 0, 0, 0 } +#endif + +//----------------------------------------------------------------------------- +// Mutex attributes structure + +typedef struct +{ + int protocol; +#ifdef _POSIX_THREAD_PRIO_PROTECT + int prioceiling; +#endif +} pthread_mutexattr_t; + +// Values for protocol +#define PTHREAD_PRIO_NONE 1 +#if defined(_POSIX_THREAD_PRIO_INHERIT) +#define PTHREAD_PRIO_INHERIT 2 +#endif +#if defined(_POSIX_THREAD_PRIO_PROTECT) +#define PTHREAD_PRIO_PROTECT 3 +#endif + +//----------------------------------------------------------------------------- +// Condition Variable structure. +// Like mutexes, this must match the underlying eCos implementation class. + +typedef struct +{ + CYG_ADDRESS mutex; + CYG_ADDRESS queue; +} pthread_cond_t; + +#define PTHREAD_COND_INITIALIZER { 0, 0 } + +//----------------------------------------------------------------------------- +// Condition variable attributes structure + +typedef struct +{ + int dummy; +} pthread_condattr_t; + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_POSIX_MUTTYPES_H +// End of muttypes.h diff --git a/packages/compat/posix/v2_0/include/pthread.h b/packages/compat/posix/v2_0/include/pthread.h new file mode 100644 index 00000000..a7a5c15a --- /dev/null +++ b/packages/compat/posix/v2_0/include/pthread.h @@ -0,0 +1,320 @@ +#ifndef CYGONCE_PTHREAD_H +#define CYGONCE_PTHREAD_H +//============================================================================= +// +// pthread.h +// +// POSIX pthread header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-03-17 +// Purpose: POSIX pthread header +// Description: This header contains all the definitions needed to support +// pthreads under eCos. The reader is referred to the POSIX +// standard or equivalent documentation for details of the +// functionality contained herein. +// +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include + +#include + +#include // CYGNUM_HAL_STACK_SIZE_MINIMUM + +#include // NULL, size_t + +#include + +#include + +#include // SCHED_* + +//============================================================================= +// General thread operations + +//----------------------------------------------------------------------------- +// Thread creation and management. + +// Create a thread. +__externC int pthread_create (pthread_t *__pthread, + const pthread_attr_t *__attr, + void *(*__start_routine) (void *), + void *__arg); + +// Get current thread id. +__externC pthread_t pthread_self (void); + +// Compare two thread identifiers. +__externC int pthread_equal (pthread_t __thread1, pthread_t __thread2); + +// Terminate current thread. +__externC void pthread_exit (void *__retval) CYGBLD_ATTRIB_NORET; + +// Wait for the thread to terminate. If thread_return is not NULL then +// the retval from the thread's call to pthread_exit() is stored at +// *thread_return. +__externC int pthread_join (pthread_t __pthread, void **__thread_return); + +// Set the detachstate of the thread to "detached". The thread then does not +// need to be joined and its resources will be freed when it exits. +__externC int pthread_detach (pthread_t __pthread); + +//----------------------------------------------------------------------------- +// Thread attribute handling. + +// Initialize attributes object with default attributes: +// detachstate == PTHREAD_JOINABLE +// scope == PTHREAD_SCOPE_SYSTEM +// inheritsched == PTHREAD_EXPLICIT_SCHED +// schedpolicy == SCHED_OTHER +// schedparam == unset +// stackaddr == unset +// stacksize == 0 +// +__externC int pthread_attr_init (pthread_attr_t *__attr); + +// Destroy thread attributes object +__externC int pthread_attr_destroy (pthread_attr_t *__attr); + + +// Set the detachstate attribute +__externC int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate); + +// Get the detachstate attribute +__externC int pthread_attr_getdetachstate (const pthread_attr_t *__attr, + int *__detachstate); + + +// Set scheduling contention scope +__externC int pthread_attr_setscope (pthread_attr_t *__attr, int __scope); + +// Get scheduling contention scope +__externC int pthread_attr_getscope (const pthread_attr_t *__attr, int *__scope); + + +// Set scheduling inheritance attribute +__externC int pthread_attr_setinheritsched (pthread_attr_t *__attr, int __inherit); + +// Get scheduling inheritance attribute +__externC int pthread_attr_getinheritsched (const pthread_attr_t *__attr, + int *__inherit); + + +// Set scheduling policy +__externC int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy); + +// Get scheduling policy +__externC int pthread_attr_getschedpolicy (const pthread_attr_t *__attr, + int *__policy); + + +// Set scheduling parameters +__externC int pthread_attr_setschedparam (pthread_attr_t *__attr, + const struct sched_param *__param); + +// Get scheduling parameters +__externC int pthread_attr_getschedparam (const pthread_attr_t *__attr, + struct sched_param *__param); + + +// Set starting address of stack. Whether this is at the start or end of +// the memory block allocated for the stack depends on whether the stack +// grows up or down. +__externC int pthread_attr_setstackaddr (pthread_attr_t *__attr, void *__stackaddr); + +// Get any previously set stack address. +__externC int pthread_attr_getstackaddr (const pthread_attr_t *__attr, + void **__stackaddr); + + +// Set minimum creation stack size. +__externC int pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize); + +// Get current minimal stack size. +__externC int pthread_attr_getstacksize (const pthread_attr_t *__attr, + size_t *__stacksize); + +//----------------------------------------------------------------------------- +// Thread scheduling controls + +// Set scheduling policy and parameters for the thread +__externC int pthread_setschedparam (pthread_t __pthread, + int __policy, + const struct sched_param *__param); + +// Get scheduling policy and parameters for the thread +__externC int pthread_getschedparam (pthread_t __pthread, + int *__policy, + struct sched_param *__param); + + + +//============================================================================= +// Dynamic package initialization + +// Initializer for pthread_once_t instances +#define PTHREAD_ONCE_INIT 0 + +// Call init_routine just the once per control variable. +__externC int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + + + +//============================================================================= +//Thread specific data + +// Create a key to identify a location in the thread specific data area. +// Each thread has its own distinct thread-specific data area but all are +// addressed by the same keys. The destructor function is called whenever a +// thread exits and the value associated with the key is non-NULL. +__externC int pthread_key_create (pthread_key_t *__key, + void (*__destructor) (void *)); + +// Delete key. +__externC int pthread_key_delete (pthread_key_t __key); + +// Store the pointer value in the thread-specific data slot addressed +// by the key. +__externC int pthread_setspecific (pthread_key_t __key, const void *__pointer); + +// Retrieve the pointer value in the thread-specific data slot addressed +// by the key. +__externC void *pthread_getspecific (pthread_key_t __key); + + + +//============================================================================= +// Thread Cancellation + +//----------------------------------------------------------------------------- +// Data structure used to manage cleanup functions + +struct pthread_cleanup_buffer +{ + struct pthread_cleanup_buffer *prev; // Chain cleanup buffers + void (*routine) (void *); // Function to call + void *arg; // Arg to pass +}; + +//----------------------------------------------------------------------------- +// Thread cancelled return value. +// This is a value returned as the retval in pthread_join() of a +// thread that has been cancelled. By making it the address of a +// location we define we can ensure that it differs from NULL and any +// other valid pointer (as required by the standard). + +__externC int pthread_canceled_dummy_var; + +#define PTHREAD_CANCELED ((void *)(&pthread_canceled_dummy_var)) + +//----------------------------------------------------------------------------- +// Cancelability enable and type + +#define PTHREAD_CANCEL_ENABLE 1 +#define PTHREAD_CANCEL_DISABLE 2 + +#define PTHREAD_CANCEL_ASYNCHRONOUS 1 +#define PTHREAD_CANCEL_DEFERRED 2 + +//----------------------------------------------------------------------------- +// Functions + +// Set cancel state of current thread to ENABLE or DISABLE. +// Returns old state in *oldstate. +__externC int pthread_setcancelstate (int __state, int *__oldstate); + +// Set cancel type of current thread to ASYNCHRONOUS or DEFERRED. +// Returns old type in *oldtype. +__externC int pthread_setcanceltype (int __type, int *__oldtype); + +// Cancel the thread. +__externC int pthread_cancel (pthread_t __pthread); + +// Test for a pending cancellation for the current thread and terminate +// the thread if there is one. +__externC void pthread_testcancel (void); + +// Install a cleanup routine. +// Note that pthread_cleanup_push() and pthread_cleanup_pop() are macros that +// must be used in matching pairs and at the same brace nesting level. +#define pthread_cleanup_push(__routine, __arg) \ + { \ + struct pthread_cleanup_buffer _buffer_; \ + pthread_cleanup_push_inner (&_buffer_, (__routine), (__arg)); + +// Remove a cleanup handler installed by the matching pthread_cleanup_push(). +// If execute is non-zero, the handler function is called. +#define pthread_cleanup_pop(__execute) \ + pthread_cleanup_pop_inner (&_buffer_, (__execute)); \ + } + + +// These two functions actually implement the cleanup push and pop functionality. +__externC void pthread_cleanup_push_inner (struct pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg); + +__externC void pthread_cleanup_pop_inner (struct pthread_cleanup_buffer *__buffer, + int __execute); + + +// ------------------------------------------------------------------------- +// eCos-specific function to measure stack usage of the supplied thread + +#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT +__externC size_t pthread_measure_stack_usage (pthread_t __pthread); +#endif + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_PTHREAD_H +// End of pthread.h diff --git a/packages/compat/posix/v2_0/include/semaphore.h b/packages/compat/posix/v2_0/include/semaphore.h new file mode 100644 index 00000000..2f88a6d0 --- /dev/null +++ b/packages/compat/posix/v2_0/include/semaphore.h @@ -0,0 +1,127 @@ +#ifndef CYGONCE_SEMAPHORE_H +#define CYGONCE_SEMAPHORE_H +//============================================================================= +// +// semaphore.h +// +// POSIX semaphore header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-03-17 +// Purpose: POSIX semaphore header +// Description: This header contains all the definitions needed to support +// semaphores under eCos. The reader is referred to the POSIX +// standard or equivalent documentation for details of the +// functionality contained herein. +// +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include + +#include // NULL, size_t + +#include + +#include + +//----------------------------------------------------------------------------- +// Semaphore object definition + +// This structure must exactly correspond in size and layout to the underlying +// eCos C++ class that implements this object. + +typedef struct +{ + CYG_WORD32 sem_value; + CYG_ADDRESS sem_queue; +} sem_t; + +//----------------------------------------------------------------------------- +// Semaphore functions + +// Initialize semaphore to value. +// pshared is not supported under eCos. +externC int sem_init (sem_t *sem, int pshared, unsigned int value); + +// Destroy the semaphore. +externC int sem_destroy (sem_t *sem); + +// Decrement value if >0 or wait for a post. +externC int sem_wait (sem_t *sem); + +// Decrement value if >0, return -1 if not. +externC int sem_trywait (sem_t *sem); + +// Increment value and wake a waiter if one is present. +externC int sem_post (sem_t *sem); + +// Get current value +externC int sem_getvalue (sem_t *sem, int *sval); + +//----------------------------------------------------------------------------- +// Named semaphore functions +// These are an optional feature under eCos + +// Open an existing named semaphore, or create it. +externC sem_t *sem_open (const char *name, int oflag, ...); + +// Close descriptor for semaphore. +externC int sem_close (sem_t *sem); + +// Remove named semaphore +externC int sem_unlink (const char *name); + +//----------------------------------------------------------------------------- +// Special return value for sem_open() + +#define SEM_FAILED ((sem_t *)NULL) + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_SEMAPHORE_H +// End of semaphore.h diff --git a/packages/compat/posix/v2_0/include/signal.h b/packages/compat/posix/v2_0/include/signal.h new file mode 100644 index 00000000..2ccde693 --- /dev/null +++ b/packages/compat/posix/v2_0/include/signal.h @@ -0,0 +1,313 @@ +#ifndef CYGONCE_SIGNAL_H +#define CYGONCE_SIGNAL_H +//============================================================================= +// +// signal.h +// +// POSIX signal header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg, jlarmour +// Contributors: +// Date: 2000-03-17 +// Purpose: POSIX signal header +// Description: This header contains all the definitions needed to support +// the POSIX signal API under eCos. +// +// Usage: This file can either be included directly, or indirectly via +// the C library signal.h header. +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include + +#ifdef CYGPKG_POSIX_SIGNALS + +#include // NULL, size_t + +#include +#include + +//----------------------------------------------------------------------------- +// POSIX feature test macros + +// We do not support job control +#undef _POSIX_JOB_CONTROL + +//----------------------------------------------------------------------------- +// Manifest constants + +#ifdef _POSIX_REALTIME_SIGNALS +// For now we define the topmost 8 signals as realtime +#define SIGRTMIN 24 +#define SIGRTMAX 31 +#endif + +//----------------------------------------------------------------------------- +// forward references + +struct timespec; + +//----------------------------------------------------------------------------- +// Sigval structure + +union sigval +{ + int sival_int; // used when application-defined value is an int + void *sival_ptr; // used when application-defined value is a pointer +}; + +//----------------------------------------------------------------------------- +// Siginfo structure passed to an SA_SIGINFO style handler + +typedef struct +{ + int si_signo; // signal number + int si_code; // cause of signal + union sigval si_value; // signal value +} siginfo_t; + +// Values for si_code +# define SI_USER 1 +# define SI_QUEUE 2 +# define SI_TIMER 3 +# define SI_ASYNCIO 4 +# define SI_MESGQ 5 +# define SI_EXCEPT 6 // signal is result of an exception delivery + +//----------------------------------------------------------------------------- +// Basic types + +// Integral type that can be accessed atomically - from ISO C 7.7 +typedef cyg_atomic sig_atomic_t; + +// Type of signal handler functions +typedef void (*sa_sighandler_t)(int); + +// Type of signal handler used if SA_SIGINFO is set in sa_flags +typedef void (*sa_siginfoaction_t)(int signo, siginfo_t *info, + void *context); + +//----------------------------------------------------------------------------- +//Signal handlers for use with signal() and sigaction(). We avoid 0 +//because in an embedded system this may be start of ROM and thus +//a possible function pointer for reset. + +#define SIG_DFL ((sa_sighandler_t) 1) // Default action +#define SIG_IGN ((sa_sighandler_t) 2) // Ignore action +#define SIG_ERR ((sa_sighandler_t)-1) // Error return + +//----------------------------------------------------------------------------- +// Signal values + +#define SIGNULL 0 // Reserved signal - do not use (POSIX 3.3.1.1) +#define SIGHUP 1 // Hangup on controlling terminal (POSIX) +#define SIGINT 2 // Interactive attention (ISO C) +#define SIGQUIT 3 // Interactive termination (POSIX) +#define SIGILL 4 // Illegal instruction (not reset when caught) (ISO C) +#define SIGTRAP 5 // Trace trap (not reset when caught) +#define SIGIOT 6 // IOT instruction +#define SIGABRT 6 // Abnormal termination - used by abort() (ISO C) +#define SIGEMT 7 // EMT instruction +#define SIGFPE 8 // Floating Point Exception e.g. div by 0 (ISO C) +#define SIGKILL 9 // Kill (cannot be caught or ignored) (POSIX) +#define SIGBUS 10 // Bus error (POSIX) +#define SIGSEGV 11 // Invalid memory reference (ISO C) +#define SIGSYS 12 // Bad argument to system call (used by anything?) +#define SIGPIPE 13 // Write on a pipe with no one to read it (POSIX) +#define SIGALRM 14 // Alarm timeout (POSIX) +#define SIGTERM 15 // Software termination request (ISO C) +#define SIGUSR1 16 // Application-defined signal 1 (POSIX) +#define SIGUSR2 17 // Application-defined signal 2 (POSIX) + + +//----------------------------------------------------------------------------- +// Signal sets. +// At present we define a single 32 bit integer mask. We may need, at +// some future point, to extend this to 64 bits, or a structure +// containing an array of masks. + +typedef cyg_uint32 sigset_t; + +//----------------------------------------------------------------------------- +// struct sigaction describes the action to be taken when we get a signal + +struct sigaction +{ + sigset_t sa_mask; // Additional signals to be blocked + int sa_flags; // Special flags + union + { + sa_sighandler_t sa_handler; // signal handler + sa_siginfoaction_t sa_sigaction; // Function to call instead of + // sa_handler if SA_SIGINFO is + // set in sa_flags + } sa_sigactionhandler; +#define sa_handler sa_sigactionhandler.sa_handler +#define sa_sigaction sa_sigactionhandler.sa_sigaction +}; + +// sa_flag bits +#define SA_NOCLDSTOP 1 // Don't generate SIGCHLD when children stop +#define SA_SIGINFO 2 // Use the sa_siginfoaction_t style signal + // handler, instead of the single argument handler + +//----------------------------------------------------------------------------- +// Sigevent structure. + +struct sigevent +{ + int sigev_notify; + int sigev_signo; + union sigval sigev_value; + void (*sigev_notify_function) (union sigval); + pthread_attr_t *sigev_notify_attributes; +}; + +# define SIGEV_NONE 1 +# define SIGEV_SIGNAL 2 +# define SIGEV_THREAD 3 + +//----------------------------------------------------------------------------- +// Functions to generate signals + +// Deliver sig to a process. +// eCos only supports the value 0 for pid. +externC int kill (pid_t pid, int sig); + +externC int pthread_kill (pthread_t thread, int sig); + +//----------------------------------------------------------------------------- +// Functions to catch signals + +// Install signal handler for sig. +externC int sigaction (int sig, const struct sigaction *act, + struct sigaction *oact); + +// Queue signal to process with value. +externC int sigqueue (pid_t pid, int sig, const union sigval value); + +//----------------------------------------------------------------------------- +// Functions to deal with current blocked and pending masks + +// Set process blocked signal mask +externC int sigprocmask (int how, const sigset_t *set, sigset_t *oset); + +// Set calling thread's blocked signal mask +externC int pthread_sigmask (int how, const sigset_t *set, sigset_t *oset); + +// Get set of pending signals for this process +externC int sigpending (sigset_t *set); + +// Values for the how arguments: +#define SIG_BLOCK 1 +#define SIG_UNBLOCK 2 +#define SIG_SETMASK 3 + +//----------------------------------------------------------------------------- +// Wait for or accept signals + +// Block signals in set and wait for a signal +externC int sigsuspend (const sigset_t *set); + +// Wait for a signal in set to arrive +externC int sigwait (const sigset_t *set, int *sig); + +// Do the same as sigwait() except return a siginfo_t object too. +externC int sigwaitinfo (const sigset_t *set, siginfo_t *info); + +// Do the same as sigwaitinfo() but return anyway after timeout. +externC int sigtimedwait (const sigset_t *set, siginfo_t *info, + const struct timespec *timeout); + +//----------------------------------------------------------------------------- +// Signal sets + +// Clear all signals from set. +externC int sigemptyset (sigset_t *set); + +// Set all signals in set. +externC int sigfillset (sigset_t *set); + +// Add signo to set. +externC int sigaddset (sigset_t *set, int signo); + +// Remove signo from set. +externC int sigdelset (sigset_t *set, int signo); + +// Test whether signo is in set +externC int sigismember (const sigset_t *set, int signo); + +//----------------------------------------------------------------------------- +// alarm, pause and sleep + +// Generate SIGALRM after some number of seconds +externC unsigned int alarm( unsigned int seconds ); + +// Wait for a signal to be delivered. +externC int pause( void ); + +// Wait for a signal, or the given number of seconds +externC unsigned int sleep( unsigned int seconds ); + +//----------------------------------------------------------------------------- +// signal() - ISO C 7.7.1 // +// +// Installs a new signal handler for the specified signal, and returns +// the old handler +// + +externC sa_sighandler_t signal(int __sig, sa_sighandler_t __handler); + +// raise() - ISO C 7.7.2 // +// +// Raises the signal, which will cause the current signal handler for +// that signal to be called + +externC int raise(int __sig); + +#endif // ifdef CYGPKG_POSIX_SIGNALS + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_SIGNAL_H +// End of signal.h diff --git a/packages/compat/posix/v2_0/include/sigsetjmp.h b/packages/compat/posix/v2_0/include/sigsetjmp.h new file mode 100644 index 00000000..ff4a332d --- /dev/null +++ b/packages/compat/posix/v2_0/include/sigsetjmp.h @@ -0,0 +1,94 @@ +#ifndef CYGONCE_SIGSETJMP_H +#define CYGONCE_SIGSETJMP_H +//============================================================================= +// +// sigsetjmp.h +// +// POSIX sigsetjmp header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg, jlarmour +// Contributors: +// Date: 2000-03-17 +// Purpose: POSIX sigsetjmp header +// Description: This header contains all the definitions needed to support +// the POSIX sigsetjmp/siglongjmp API under eCos. +// +// Usage: This file must be included indirectly via +// the C library setjmp.h header. +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include // hal_jmp_buf + +//============================================================================= +// sigjmp_buf structure +// The API requires this to be an array type, but this array actually +// contains three fields: +// 0..sizeof(hal_jmp_buf)-1 HAL jump buffer +// sizeof(hal_jmp_buf) savemask value (an int) +// sizeof(hal_jmp_buf)+sizeof(int)... sigset_t containing saved mask + +typedef struct { + hal_jmp_buf __jmp_buf; + int __savemask; + sigset_t __sigsavemask; +} sigjmp_buf[1]; + +//============================================================================= +// sigsetjmp() macro + +#define sigsetjmp( _env_, _savemask_ ) \ +( \ + ((_env_)[0].__savemask = _savemask_), \ + ((_savemask_)?pthread_sigmask(SIG_BLOCK,NULL,&((_env_)[0].__sigsavemask)):0),\ + hal_setjmp((_env_)[0].__jmp_buf) \ +) + +//============================================================================= +// siglongjmp function + +__externC void siglongjmp( sigjmp_buf env, int val ); + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_SIGSETJMP_H +// End of sigsetjmp.h diff --git a/packages/compat/posix/v2_0/include/time.h b/packages/compat/posix/v2_0/include/time.h new file mode 100644 index 00000000..67cdbdb6 --- /dev/null +++ b/packages/compat/posix/v2_0/include/time.h @@ -0,0 +1,151 @@ +#ifndef CYGONCE_POSIX_TIME_H +#define CYGONCE_POSIX_TIME_H +/*============================================================================= +// +// time.h +// +// POSIX time header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg, jlarmour +// Date: 2000-03-17 +// Purpose: POSIX time header +// Description: This header contains all the definitions needed to support +// the POSIX timer and timer API under eCos. +// +// Usage: Do not include this file directly - instead include +// +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include +#include + +/*---------------------------------------------------------------------------*/ +/* Types for timers and clocks */ + +typedef int clockid_t; + +#ifdef CYGPKG_POSIX_TIMERS +typedef int timer_t; + +/* forward declaration - if the app uses it it will have to include + * signal.h anyway + */ +struct sigevent; +#endif + +/*---------------------------------------------------------------------------*/ +/* Structures */ + +struct timespec +{ + time_t tv_sec; + long tv_nsec; +}; + +#ifdef CYGPKG_POSIX_TIMERS +struct itimerspec +{ + struct timespec it_interval; + struct timespec it_value; +}; +#endif + +/*---------------------------------------------------------------------------*/ +/* Manifest constants */ + +#define CLOCK_REALTIME 0 + +#ifdef CYGPKG_POSIX_TIMERS +#define TIMER_ABSTIME 1 +#endif + +/*---------------------------------------------------------------------------*/ +/* Clock functions */ + +/* Set the clocks current time */ +__externC int clock_settime( clockid_t clock_id, const struct timespec *tp); + +/* Get the clocks current time */ +__externC int clock_gettime( clockid_t clock_id, struct timespec *tp); + +/* Get the clocks resolution */ +__externC int clock_getres( clockid_t clock_id, struct timespec *tp); + + +/*---------------------------------------------------------------------------*/ +/* Timer functions */ + +#ifdef CYGPKG_POSIX_TIMERS + +/* Create a timer based on the given clock. */ +__externC int timer_create( clockid_t clock_id, + struct sigevent *evp, + timer_t *timer_id); + +/* Delete the timer */ +__externC int timer_delete( timer_t timer_id ); + +/* Set the expiration time of the timer. */ +__externC int timer_settime( timer_t timerid, int flags, + const struct itimerspec *value, + struct itimerspec *ovalue ); + +/* Get current timer values */ +__externC int timer_gettime( timer_t timerid, struct itimerspec *value ); + +/* Get number of missed triggers */ +__externC int timer_getoverrun( timer_t timerid ); + +#endif + +/*---------------------------------------------------------------------------*/ +/* Nanosleep */ + +/* Sleep for the given time. */ +__externC int nanosleep( const struct timespec *rqtp, + struct timespec *rmtp); + + +/*---------------------------------------------------------------------------*/ +#endif /* ifndef CYGONCE_POSIX_TIME_H */ +/* End of time.h */ diff --git a/packages/compat/posix/v2_0/include/types.h b/packages/compat/posix/v2_0/include/types.h new file mode 100644 index 00000000..dc74e0f7 --- /dev/null +++ b/packages/compat/posix/v2_0/include/types.h @@ -0,0 +1,112 @@ +#ifndef CYGONCE_POSIX_TYPES_H +#define CYGONCE_POSIX_TYPES_H +//============================================================================= +// +// types.h +// +// POSIX types header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-03-17 +// Purpose: POSIX types header +// Description: This header contains various POSIX type definitions. These types +// are implementation defined. +// +// Usage: #include +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include + +#include + +//----------------------------------------------------------------------------- +// Basic types. + +typedef cyg_uint32 pthread_t; +typedef int pthread_key_t; +typedef int pthread_once_t; + +//----------------------------------------------------------------------------- +// Scheduling parameters. At present only the priority is defined. +// Strictly this should be in , but the requirement for pthread_attr_t +// to contain a sched_param object means that it must be here. + +struct sched_param +{ + int sched_priority; +}; + +//----------------------------------------------------------------------------- +// Thread attribute structure. + +typedef struct pthread_attr_t +{ + unsigned int detachstate:2, + scope:2, + inheritsched:2, + schedpolicy:2, + stackaddr_valid:1, + stacksize_valid:1; + struct sched_param schedparam; + void *stackaddr; + size_t stacksize; +} pthread_attr_t; + +// Values for detachstate +#define PTHREAD_CREATE_JOINABLE 1 +#define PTHREAD_CREATE_DETACHED 2 + +// Values for scope +#define PTHREAD_SCOPE_SYSTEM 1 +#define PTHREAD_SCOPE_PROCESS 2 + +// Values for inheritsched +#define PTHREAD_INHERIT_SCHED 1 +#define PTHREAD_EXPLICIT_SCHED 2 + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_POSIX_TYPES_H +// End of types.h diff --git a/packages/compat/posix/v2_0/include/utsname.h b/packages/compat/posix/v2_0/include/utsname.h new file mode 100644 index 00000000..3f0b79c9 --- /dev/null +++ b/packages/compat/posix/v2_0/include/utsname.h @@ -0,0 +1,98 @@ +#ifndef CYGONCE_UTSNAME_H +#define CYGONCE_UTSNAME_H +//============================================================================= +// +// utsname.h +// +// POSIX utsname header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-03-17 +// Purpose: POSIX utsname header +// Description: This header contains all the definitions needed to support +// utsnames under eCos. The reader is referred to the POSIX +// standard or equivalent documentation for details of the +// functionality contained herein. +// +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include + +#include + +#include // CYGNUM_HAL_STACK_SIZE_MINIMUM + +#include // NULL, size_t + +#include + +#include + +#include // SCHED_* + +//============================================================================= +// UTSName structure + +struct utsname +{ + char sysname[CYG_POSIX_UTSNAME_LENGTH]; + char nodename[CYG_POSIX_UTSNAME_NODENAME_LENGTH]; + char release[CYG_POSIX_UTSNAME_LENGTH]; + char version[CYG_POSIX_UTSNAME_LENGTH]; + char machine[CYG_POSIX_UTSNAME_LENGTH]; +}; + +//============================================================================= +// uname() function + +__externC int uname( struct utsname *name ); + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_UTSNAME_H +// End of utsname.h diff --git a/packages/compat/posix/v2_0/src/except.cxx b/packages/compat/posix/v2_0/src/except.cxx new file mode 100644 index 00000000..a82913b9 --- /dev/null +++ b/packages/compat/posix/v2_0/src/except.cxx @@ -0,0 +1,343 @@ +//========================================================================== +// +// except.cxx +// +// POSIX exception translation +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-03-27 +// Purpose: POSIX exception translation +// Description: This file contains code to translate eCos hardware +// exceptions into POSIX signals. +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include + +#include // base kernel types +#include // tracing macros +#include // assertion macros + +#include + +#include "pprivate.h" // POSIX private header + +#include // our header + +#include + +//========================================================================== +// Translation table from eCos exceptions to POSIX signals. + +static const struct +{ + cyg_code exception; + int signal; +} exception_signal_mapping[] = +{ +#ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS + {CYGNUM_HAL_EXCEPTION_DATA_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_WRITE + {CYGNUM_HAL_EXCEPTION_DATA_WRITE, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_ACCESS + {CYGNUM_HAL_EXCEPTION_CODE_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_WRITE + {CYGNUM_HAL_EXCEPTION_CODE_WRITE, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_EXECUTE + {CYGNUM_HAL_EXCEPTION_CODE_EXECUTE, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_IO_ACCESS + {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_IO_WRITE + {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS + {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE + {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS + {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE + {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS + {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE + {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS + {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE + {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS + {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE + {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS + {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE + {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION + {CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, SIGILL}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_INTERRUPT + {CYGNUM_HAL_EXCEPTION_INTERRUPT, SIGINT}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_TRAP + {CYGNUM_HAL_EXCEPTION_TRAP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO + {CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_OVERFLOW + {CYGNUM_HAL_EXCEPTION_OVERFLOW, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_BOUNDS + {CYGNUM_HAL_EXCEPTION_BOUNDS, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_SINGLE_STEP + {CYGNUM_HAL_EXCEPTION_SINGLE_STEP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP + {CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP + {CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_BP + {CYGNUM_HAL_EXCEPTION_DATA_BP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP + {CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW + {CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_STACK_FAULT + {CYGNUM_HAL_EXCEPTION_STACK_FAULT, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_PARITY + {CYGNUM_HAL_EXCEPTION_PARITY, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_FPU + {CYGNUM_HAL_EXCEPTION_FPU, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL + {CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW + {CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW + {CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO + {CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_SYSTEM_CALL + {CYGNUM_HAL_EXCEPTION_SYSTEM_CALL, SIGSYS}, +#endif + {0, 0} // dummy value to ensure compiler is happy +}; + +//========================================================================== +// POSIX exception handler + +static void cyg_posix_exception_handler( + CYG_ADDRWORD data, // user supplied data == signal number + cyg_code exception_number, // exception being raised + CYG_ADDRWORD exception_info // any exception specific info + ) +{ + int signo = 0; + + pthread_info *self = pthread_self_info(); + + if( self == NULL ) + { + // Not a POSIX thread, just return + return; + } + +#ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE + + signo = data; + +#else + + for( int i = 0; exception_signal_mapping[i].signal != 0; i++ ) + { + if( exception_signal_mapping[i].exception == exception_number ) + { + signo = exception_signal_mapping[i].signal; + break; + } + } + +#endif + + if( sigismember( &self->sigmask, signo ) ) + { + // The signal is masked in the current thread. POSIX says that + // the behaviour is undefined here. We choose to ignore it. + + return; + } + + // The kernel exception handler may have disabled interrupts, so + // we (re-)enable them here. From this point on we are running in + // a context that is effectively just pushed onto the stack of the + // current thread. If we return we will unwind and resume + // execution from the excepting code. We can also, in theory, + // longjump out of the signal handler, and although that is + // deprecated, we make sure in cyg_deliver_signals() that it is + // possible to do it. + + HAL_ENABLE_INTERRUPTS(); + + struct sigevent sev; + + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = signo; + sev.sigev_value.sival_ptr = (void *)exception_info; + + // Generate the signal + cyg_sigqueue( &sev, SI_EXCEPT ); + + // And try to deliver it + cyg_deliver_signals(); +} + +//========================================================================== +// Install all the exception handlers + +static void install_handlers( Cyg_Thread *thread) +{ +#ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE + + // With decoded exceptions, we must install a separate exception + // handler for each supported exception. + + for( int i = 0; exception_signal_mapping[i].signal != 0; i++ ) + { + thread->register_exception( exception_signal_mapping[i].exception, + cyg_posix_exception_handler, + exception_signal_mapping[i].signal,, + NULL, + NULL); + } + +#else + + // Otherwise there is just one exception handler for all exceptions. + + thread->register_exception( CYGNUM_HAL_EXCEPTION_MIN, + cyg_posix_exception_handler, + 0, + NULL, + NULL); + +#endif + +} + +//========================================================================== +// Initialization + +externC void cyg_posix_exception_start() +{ +#ifdef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL + + // With global exceptions, we only need to install a single static + // set of exception handlers. Note that by this point in system + // initialization the idle thread should be installed as the + // current thread, so we pass a pointer to that to + // install_handlers(). The identity of the thread passed is + // actually irrelevant in this case and is just used as a handle + // into the thread class. + + install_handlers( Cyg_Thread::self() ); + +#endif +} + +//========================================================================== +// Per thread exception initialization and destruction + +externC void cyg_pthread_exception_init(pthread_info *thread) +{ +#ifndef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL + + // With non-global exceptions we must install a new set of handlers + // for each thread. + + install_handlers( thread->thread ); + +#endif +} + +externC void cyg_pthread_exception_destroy(pthread_info *thread) +{ + // Nothing to do at present. +} + +// ------------------------------------------------------------------------- +// EOF except.cxx diff --git a/packages/compat/posix/v2_0/src/misc.cxx b/packages/compat/posix/v2_0/src/misc.cxx new file mode 100644 index 00000000..d56ef915 --- /dev/null +++ b/packages/compat/posix/v2_0/src/misc.cxx @@ -0,0 +1,386 @@ +//========================================================================== +// +// misc.cxx +// +// POSIX misc function implementations +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-07-18 +// Purpose: POSIX misc function implementation +// Description: This file contains the implementation of miscellaneous POSIX +// functions that do not belong elsewhere. +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include +#include + +#include // base kernel types +#include // tracing macros +#include // assertion macros + +#include "pprivate.h" // POSIX private header + +#include +#include // My header +#include // strcpy +#include +#include + +#include + +#include + +// ------------------------------------------------------------------------- +// Supply some suitable values for constants that may not be present +// in all configurations. + +#ifndef MQ_OPEN_MAX +#define MQ_OPEN_MAX 0 +#endif +#ifndef MQ_PRIO_MAX +#define MQ_PRIO_MAX 0 +#endif + +// ------------------------------------------------------------------------- + +#define __string(_x) #_x +#define __xstring(_x) __string(_x) + +// ------------------------------------------------------------------------- +// uname() + +__externC int uname( struct utsname *name ) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + + strcpy( name->sysname, "eCos" ); + strcpy( name->nodename, "" ); // should use gethostname() + strcpy( name->release, __xstring( CYGNUM_KERNEL_VERSION_MAJOR ) ); + strcpy( name->version, __xstring( CYGNUM_KERNEL_VERSION_MINOR ) ); + strcpy( name->machine, "" ); + + CYG_REPORT_RETVAL(0); + return 0; +} + +// ------------------------------------------------------------------------- +// sysconf() + +#define SC_CASE( _name, _val ) case _name: return _val + +__externC long sysconf( int name ) +{ + + switch( name ) + { + SC_CASE( _SC_AIO_LISTIO_MAX, AIO_LISTIO_MAX ); + SC_CASE( _SC_AIO_MAX, AIO_MAX ); + SC_CASE( _SC_AIO_PRIO_DELTA_MAX, AIO_PRIO_DELTA_MAX ); + SC_CASE( _SC_ARG_MAX, ARG_MAX ); + SC_CASE( _SC_CHILD_MAX, CHILD_MAX ); + SC_CASE( _SC_DELAYTIMER_MAX, DELAYTIMER_MAX ); + SC_CASE( _SC_GETGR_R_SIZE_MAX, 0 ); + SC_CASE( _SC_GETPW_R_SIZE_MAX, 0 ); + SC_CASE( _SC_LOGIN_NAME_MAX, LOGIN_NAME_MAX ); + SC_CASE( _SC_MQ_OPEN_MAX, MQ_OPEN_MAX ); + SC_CASE( _SC_MQ_PRIO_MAX, MQ_PRIO_MAX ); + SC_CASE( _SC_NGROUPS_MAX, NGROUPS_MAX ); + SC_CASE( _SC_OPEN_MAX, OPEN_MAX ); + SC_CASE( _SC_PAGESIZE, PAGESIZE ); + SC_CASE( _SC_RTSIG_MAX, RTSIG_MAX ); + SC_CASE( _SC_SEM_NSEMS_MAX, SEM_NSEMS_MAX ); + SC_CASE( _SC_SEM_VALUE_MAX, SEM_VALUE_MAX ); + SC_CASE( _SC_SIGQUEUE_MAX, SIGQUEUE_MAX ); + SC_CASE( _SC_STREAM_MAX, STREAM_MAX ); +#ifdef CYGPKG_POSIX_PTHREAD + SC_CASE( _SC_THREAD_DESTRUCTOR_ITERATIONS, PTHREAD_DESTRUCTOR_ITERATIONS ); + SC_CASE( _SC_THREAD_KEYS_MAX, PTHREAD_KEYS_MAX ); + SC_CASE( _SC_THREAD_STACK_MIN, PTHREAD_STACK_MIN ); + SC_CASE( _SC_THREAD_THREADS_MAX, PTHREAD_THREADS_MAX ); +#endif + SC_CASE( _SC_TIMER_MAX, TIMER_MAX ); + SC_CASE( _SC_TTY_NAME_MAX, TTY_NAME_MAX ); + SC_CASE( _SC_TZNAME_MAX, TZNAME_MAX ); + SC_CASE( _SC_VERSION, _POSIX_VERSION ); + +#ifdef CYGPKG_POSIX_TIMERS + case _SC_CLK_TCK: + { + struct timespec ts; + ts.tv_sec = 1; + ts.tv_nsec = 0; + cyg_tick_count ticks = cyg_timespec_to_ticks( &ts ); + return ticks; + } +#endif + + case _SC_ASYNCHRONOUS_IO: + #ifdef _POSIX_ASYNCHRONOUS_IO + return 1; + #else + return -1; + #endif + + case _SC_FSYNC: + #ifdef _POSIX_FSYNC + return 1; + #else + return -1; + #endif + + case _SC_JOB_CONTROL: + #ifdef _POSIX_JOB_CONTROL + return 1; + #else + return -1; + #endif + + case _SC_MAPPED_FILES: + #ifdef _POSIX_MAPPED_FILES + return 1; + #else + return -1; + #endif + + case _SC_MEMLOCK: + #ifdef _POSIX_MEMLOCK + return 1; + #else + return -1; + #endif + + case _SC_MEMLOCK_RANGE: + #ifdef _POSIX_MEMLOCK_RANGE + return 1; + #else + return -1 ; + #endif + + case _SC_MEMORY_PROTECTION: + #ifdef _POSIX_MEMORY_PROTECTION + return 1; + #else + return -1; + #endif + + case _SC_MESSAGE_PASSING: + #ifdef _POSIX_MESSAGE_PASSING + return 1; + #else + return -1; + #endif + + case _SC_PRIORITIZED_IO: + #ifdef _POSIX_PRIORITIZED_IO + return 1; + #else + return -1; + #endif + + case _SC_PRIORITY_SCHEDULING: + #ifdef _POSIX_PRIORITY_SCHEDULING + return 1; + #else + return -1; + #endif + + case _SC_REALTIME_SIGNALS: + #ifdef _POSIX_REALTIME_SIGNALS + return 1; + #else + return -1; + #endif + + case _SC_SAVED_IDS: + #ifdef _POSIX_SAVED_IDS + return 1; + #else + return -1; + #endif + + case _SC_SEMAPHORES: + #ifdef _POSIX_SEMAPHORES + return 1; + #else + return -1; + #endif + + case _SC_SHARED_MEMORY_OBJECTS: + #ifdef _POSIX_SHARED_MEMORY_OBJECTS + return 1; + #else + return -1; + #endif + + case _SC_SYNCHRONIZED_IO: + #ifdef _POSIX_SYNCHRONIZED_IO + return 1; + #else + return -1; + #endif + + case _SC_THREADS: + #ifdef _POSIX_THREADS + return 1; + #else + return -1; + #endif + + case _SC_THREAD_ATTR_STACKADDR: + #ifdef _POSIX_THREAD_ATTR_STACKADDR + return 1; + #else + return -1; + #endif + + case _SC_THREAD_ATTR_STACKSIZE: + #ifdef _POSIX_THREAD_ATTR_STACKSIZE + return 1; + #else + return -1; + #endif + + case _SC_THREAD_PRIO_INHERIT: + #ifdef _POSIX_THREAD_PRIO_INHERIT + return 1; + #else + return -1; + #endif + + case _SC_THREAD_PRIO_PROTECT: + #ifdef _POSIX_THREAD_PRIO_PROTECT + return 1; + #else + return -1; + #endif + + case _SC_THREAD_PRIORITY_SCHEDULING: + #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING + return 1; + #else + return -1; + #endif + + case _SC_THREAD_PROCESS_SHARED: + #ifdef _POSIX_THREAD_PROCESS_SHARED + return 1; + #else + return -1; + #endif + + case _SC_THREAD_SAFE_FUNCTIONS: + #ifdef _POSIX_THREAD_SAFE_FUNCTIONS + return 1; + #else + return -1; + #endif + + case _SC_TIMERS: + #ifdef _POSIX_TIMERS + return 1; + #else + return -1; + #endif + + + default: + errno = EINVAL; + return -1; + } +} + +//========================================================================== +// Some trivial compatibility functions. +// These are merely present to permit existing code to be ported a little +// more easily, and to provide adequate standards compatibility. + +__externC pid_t getpid ( void ) { return 42; } +__externC pid_t getppid ( void ) { return 41; } +__externC uid_t getuid ( void ) { return 666; } +__externC uid_t geteuid ( void ) { return 666; } +__externC gid_t getgid ( void ) { return 88; } +__externC gid_t getegid ( void ) { return 88; } +__externC int setuid ( uid_t uid ) { errno = EPERM; return -1; } +__externC int setgid ( uid_t gid ) { errno = EPERM; return -1; } +__externC int getgroups ( int gidsetsize, gid_t grouplist[] ) { return 0; }; +__externC pid_t getpgrp ( void ) { return 42; } +__externC pid_t setsid ( void ) { errno = EPERM; return -1; } +__externC int setpgid ( pid_t pid, pid_t pgid ) { errno = ENOSYS; return -1; } + +//========================================================================== +// Exports to other packages + +// ------------------------------------------------------------------------- +// POSIX API function entry + +__externC void cyg_posix_function_start() +{ + Cyg_Thread *self = Cyg_Scheduler::get_current_thread(); + + // Inhibit ASR delivery in this function until it returns. + + self->set_asr_inhibit(); +} + +// ------------------------------------------------------------------------- + +__externC void cyg_posix_function_finish() +{ + Cyg_Thread *self = Cyg_Scheduler::get_current_thread(); + + // Re-allow ASR delivery. + + self->clear_asr_inhibit(); + + // After clearing the inhibit flag, blip the scheduler lock + // to get any pending ASRs delivered. + Cyg_Scheduler::lock(); + Cyg_Scheduler::unlock(); +} + +// ------------------------------------------------------------------------- +// EOF misc.cxx diff --git a/packages/compat/posix/v2_0/src/mqueue.cxx b/packages/compat/posix/v2_0/src/mqueue.cxx new file mode 100644 index 00000000..350950a2 --- /dev/null +++ b/packages/compat/posix/v2_0/src/mqueue.cxx @@ -0,0 +1,1005 @@ +/*======================================================================== +// +// mqueue.cxx +// +// Message queues tests +// +//======================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jlarmour +// Contributors: +// Date: 2000-05-14 +// Purpose: This file provides the implementation for POSIX message +// queues +// Description: It uses eCos kernel mqueues as the underlying +// implementation +// Usage: +// +//####DESCRIPTIONEND#### +// +//====================================================================== +*/ + +/* CONFIGURATION */ + +#include + +#ifdef CYGPKG_POSIX_MQUEUES + +#include + +/* INCLUDES */ + +#include // common types etc. +#include // Assertion support +#include // Tracing support +#include // eCos Mqueue Header +#include // Cyg_Scheduler::lock() +#include // inlines for above +#include // Standard POSIX mqueue header +#include // mode_t, ssize_t +#include // PATH_MAX +#include // malloc, etc. +#include // errno +#include // O_* +#include // varargs +#include // mutexes +#include // strncpy +#ifdef CYGFUN_POSIX_MQUEUE_NOTIFY +# include +# include "pprivate.h" // cyg_sigqueue() +#endif +#ifdef CYGFUN_KERNEL_THREADS_TIMER +# include +# include "pprivate.h" // cyg_timespec_to_ticks() +#endif + +/* CONSTANTS */ + +#define MQ_VALID_MAGIC 0x6db256c1 + +/* TYPE DEFINITIONS */ + +struct mqtabent; + +// this is a queue user - each one of these corresponds to a mqd_t +struct mquser { + int flags; // O_RDONLY, O_WRONLY, O_RDWR, O_NONBLOCK + struct mqtabent *tabent; // back pointer to table entry + struct mquser *next; + bool notifieruser; // POSIX sucks so bad. It requires a mq_close + // to only deregister the notification if it + // was done via this descriptor. So we have to + // know if it was this one +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + cyg_uint32 magic; // magic number: MQ_VALID_MAGIC if valid +#endif +}; + +struct mqtabent { + char name[ PATH_MAX ]; // ascii name - set to "" when unused + Cyg_Mqueue *mq; // the underlying queue object + long maxmsg; // as set on creation + long msgsize; // as set on creation + bool unlinkme; // unlink when final user closes? + struct mquser *users; // each user + +#ifdef CYGFUN_POSIX_MQUEUE_NOTIFY + const struct sigevent *sigev; // notification event +#endif +}; + +/* GLOBALS */ + +static struct mqtabent mqtab[ CYGNUM_POSIX_MQUEUE_OPEN_MAX ]; +static pthread_mutex_t mqtab_mut = PTHREAD_MUTEX_INITIALIZER; + +/* LOCAL FUNCTIONS */ + +//------------------------------------------------------------------------ + +// placement new definition +inline void *operator new(size_t size, void *ptr) +{ + CYG_CHECK_DATA_PTR( ptr, "Bad pointer" ); + return ptr; +} + +// Deallocation callback from Cyg_Mqueue +static void +my_free( void *ptr, size_t ) +{ + free( ptr ); +} + +//------------------------------------------------------------------------ + +// Do the actual "unlink" of a queue, i.e. mark it invalid in the table. +// The table mutex is assumed to be locked +static void +do_mq_unlink( struct mqtabent *tabent ) +{ + CYG_REPORT_FUNCTION(); + CYG_CHECK_DATA_PTRC( tabent ); + + tabent->name[0] = '\0'; // won't match anything the user sends now + tabent->mq->~Cyg_Mqueue(); + free( tabent->mq ); + tabent->mq=NULL; + + CYG_REPORT_RETURN(); +} + +//------------------------------------------------------------------------ + +#ifdef CYGFUN_POSIX_MQUEUE_NOTIFY + +static void +notifyme( Cyg_Mqueue &q, CYG_ADDRWORD data ) +{ + CYG_REPORT_FUNCTION(); + struct mquser *user = (struct mquser *)data; + CYG_CHECK_DATA_PTRC( user ); + struct mqtabent *tabent = user->tabent; + CYG_CHECK_DATA_PTRC( tabent ); + + Cyg_Scheduler::lock(); + // we may have been pre-empted before this, so check there's still a + // notification to do + + if ( NULL == tabent->sigev ) { + Cyg_Scheduler::unlock(); + CYG_REPORT_RETURN(); + return; + } // if + + const struct sigevent *ev = tabent->sigev; + + // first deregister + q.setnotify( NULL, 0 ); + tabent->sigev = NULL; + user->notifieruser = false; // not any more + + // now the rest of the world can go + Cyg_Scheduler::unlock(); + + // queue event. If it fails... nothing we can do :-( so ignore return code + cyg_sigqueue( ev, SI_MESGQ ); + + cyg_deliver_signals(); + + CYG_REPORT_RETURN(); +} + +#endif // ifdef CYGFUN_POSIX_MQUEUE_NOTIFY + +//------------------------------------------------------------------------ + +/* EXPORTED FUNCTIONS */ + +externC mqd_t +mq_open( const char *name, int oflag, ... ) +{ + CYG_REPORT_FUNCTYPE( "returning %08x" ); + CYG_REPORT_FUNCARG2( "name=%08x, oflag=%d", name, oflag ); + CYG_CHECK_DATA_PTRC( name ); + + if ( ((oflag & O_RDONLY) != O_RDONLY) && + ((oflag & O_WRONLY) != O_WRONLY) && + ((oflag & O_RDWR) != O_RDWR)) { + // user didn't specify mode + errno = EINVAL; + CYG_REPORT_RETVAL( -1 ); + return (mqd_t)-1; + } // if + + mqd_t retval; + cyg_ucount32 i; + struct mqtabent *qtabent=NULL; + int interr; + + interr = pthread_mutex_lock( &mqtab_mut ); + // should never fail + CYG_ASSERT( interr == 0, "internal lock failed!" ); + + // find if a matching entry exists first + // FIXME: Should check for length and return ENAMETOOLONG + for ( i=0; i < CYGNUM_POSIX_MQUEUE_OPEN_MAX; i++ ) { + if ( 0 == strncmp(name, mqtab[i].name, PATH_MAX) ) { + qtabent = &mqtab[i]; + break; + } // if + } // for + + if ( (NULL != qtabent) && (O_EXCL == (oflag & O_EXCL)) ) { + errno = EEXIST; + retval = (mqd_t)-1; + goto exit_unlock; + } + + if ( (NULL == qtabent) && (O_CREAT != (oflag & O_CREAT)) ) { + errno = ENOENT; + retval = (mqd_t)-1; + goto exit_unlock; + } + + // so if we didn't find something, we must be being asked to create it + if (NULL == qtabent) { + mode_t mode; // FIXME: mode ignored for now + const struct mq_attr *attr; + const struct mq_attr default_attr = { 0, MQ_OPEN_MAX, 128 }; + va_list args; + + va_start( args, oflag ); + mode = va_arg( args, mode_t ); + attr = va_arg( args, struct mq_attr * ); + va_end( args ); + + // find an empty table entry + for ( i=0; i < CYGNUM_POSIX_MQUEUE_OPEN_MAX; i++ ) { + if ( NULL == mqtab[i].mq ) + break; + } + + // if not found, table is full + if ( i == CYGNUM_POSIX_MQUEUE_OPEN_MAX ) { + errno = ENFILE; + retval = (mqd_t)-1; + goto exit_unlock; + } + + Cyg_Mqueue::qerr_t qerr; + + // user can specify NULL attr, which means arbitrary message queue + // size! Duh. + if ( NULL == attr ) + attr = &default_attr; + else { + // if they do supply one, POSIX says we're meant to check it + if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0) { + errno = EINVAL; + retval = (mqd_t)-1; + goto exit_unlock; + } + } // else + + // allocate the underlying queue + Cyg_Mqueue *mqholder = (Cyg_Mqueue *)malloc( sizeof(Cyg_Mqueue) ); + if ( NULL == mqholder ) { + errno = ENOSPC; + retval = (mqd_t)-1; + goto exit_unlock; + } + + // construct it with placement new + mqtab[i].mq = new (mqholder) Cyg_Mqueue( attr->mq_maxmsg, + attr->mq_msgsize, + &malloc, &my_free, &qerr ); + + switch (qerr) { + case Cyg_Mqueue::OK: + break; + case Cyg_Mqueue::NOMEM: + free( mqholder ); + errno = ENOSPC; + retval = (mqd_t)-1; + goto exit_unlock; + default: + CYG_FAIL("Unhandled Cyg_Mqueue constructor return error"); + break; + } // switch + + mqtab[i].users = (struct mquser *) malloc( sizeof(struct mquser) ); + if ( NULL == mqtab[i].users ) { + mqtab[i].mq->~Cyg_Mqueue(); + free( mqholder ); + errno = ENOSPC; + retval = (mqd_t)-1; + goto exit_unlock; + } + + // initialize mqtab[i] + mqtab[i].maxmsg = attr->mq_maxmsg; + mqtab[i].msgsize = attr->mq_msgsize; + mqtab[i].unlinkme = false; +#ifdef CYGFUN_POSIX_MQUEUE_NOTIFY + mqtab[i].sigev = NULL; +#endif + strncpy( mqtab[i].name, name, PATH_MAX ); + + // initialize first mqtab[i].users + mqtab[i].users->next = NULL; + // set the mode for later, but also note that O_NONBLOCK can + // be set in oflags *or* the attr the user passed + mqtab[i].users->flags = oflag | (attr->mq_flags & O_NONBLOCK); + + // set back pointer so that message queue handle can find actual queue + mqtab[i].users->tabent = &mqtab[i]; + + mqtab[i].users->notifieruser = false; + +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + mqtab[i].users->magic = MQ_VALID_MAGIC; // now valid +#endif + + retval=(mqd_t)mqtab[i].users; + + goto exit_unlock; + } // if (NULL == qtabent) + + // so we're not creating, and we have a valid qtabent + + // But this qtabent may be being unlinked. If so, we are permitted + // to return an error, so we will. (see under mq_unlink() in POSIX) + // Which error though? EINVAL seems best, but POSIX doesn't say :-/ + + if (true == qtabent->unlinkme) { + errno = EINVAL; + retval = (mqd_t)-1; + goto exit_unlock; + } + + // now we have a usable qtabent + + struct mquser *user; + user = (struct mquser *) malloc( sizeof(struct mquser) ); + if ( NULL == user ) { + errno = ENOSPC; + retval = (mqd_t)-1; + goto exit_unlock; + } + + // prepend to qtab user list + user->next = qtabent->users; + qtabent->users = user; + + // set back pointer so that message queue handle can find actual queue + user->tabent = qtabent; + + user->flags = oflag; + +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + user->magic = MQ_VALID_MAGIC; // now valid +#endif + + retval=(mqd_t)user; + + exit_unlock: + interr = pthread_mutex_unlock( &mqtab_mut ); + // should never fail + CYG_ASSERT( interr == 0, "internal lock failed!" ); + CYG_REPORT_RETVAL( retval ); + return retval; +} // mq_open() + +//------------------------------------------------------------------------ + +// NOTE: It is the *user*'s responsibility to ensure that nothing is +// blocked in mq_send() or mq_receive() when closing the queue with +// that descriptor. The standard does not specify the behaviour, so that's +// what I am assuming + +externC int +mq_close( mqd_t mqdes ) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + CYG_REPORT_FUNCARG1XV( mqdes ); + + struct mquser *user = (struct mquser *)mqdes; + +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + if ( user->magic != MQ_VALID_MAGIC ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return -1; + } +#endif + + int interr; + + interr = pthread_mutex_lock( &mqtab_mut ); + // should never fail + CYG_ASSERT( interr == 0, "internal lock failed!" ); + + struct mqtabent *tabent = user->tabent; + struct mquser *usertmp; + + // perhaps should return EBADF instead of assert? + CYG_ASSERT( tabent->users != NULL, "Null message queue user list" ); + +#ifdef CYGFUN_POSIX_MQUEUE_NOTIFY + // deregister notification iff this was the message queue descriptor + // that was used to register it (POSIX says) + if ( true == user->notifieruser ) { + tabent->mq->setnotify( NULL, 0 ); + tabent->sigev = NULL; + // not worth clearing notifieruser + } +#endif + + // find in the list for this queue and remove - sucks a bit, but seems + // best over all - the list shouldn't be too long + if ( tabent->users == user ) { + tabent->users = user->next; // remove + } else { + for ( usertmp=tabent->users; + NULL != usertmp->next; + usertmp = usertmp->next ) { + if ( usertmp->next == user ) + break; + } // for + + // perhaps should return EBADF instead of assert? + CYG_ASSERT( usertmp->next != NULL, "Couldn't find message queue user" ); + + usertmp->next = user->next; // remove + } // else + +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + user->magic = 0; // invalidate +#endif + + // free it up + free( user ); + + if ( (true == tabent->unlinkme) && (NULL == tabent->users) ) { + do_mq_unlink( tabent ); + } // if + + interr = pthread_mutex_unlock( &mqtab_mut ); + // should never fail + CYG_ASSERT( interr == 0, "internal lock failed!" ); + CYG_REPORT_RETVAL( 0 ); + return 0; +} // mq_close() + + +//------------------------------------------------------------------------ + +externC int +mq_unlink( const char *name ) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + CYG_REPORT_FUNCARG1( "name=%s", name ); + + int retval, interr; + cyg_ucount32 i; + struct mqtabent *qtabent=NULL; + + interr = pthread_mutex_lock( &mqtab_mut ); + // should never fail + CYG_ASSERT( interr == 0, "internal lock failed!" ); + + // find the entry first + // FIXME: Should check for length and return ENAMETOOLONG + for ( i=0; i < CYGNUM_POSIX_MQUEUE_OPEN_MAX; i++ ) { + if ( 0 == strncmp(name, mqtab[i].name, PATH_MAX) ) { + qtabent = &mqtab[i]; + break; + } // if + } // for + + if ( NULL == qtabent ) { // not found + errno = ENOENT; + retval = -1; + goto exit_unlock; + } + + if ( NULL != qtabent->users ) { // still in use + qtabent->unlinkme = true; // so mark it as pending deletion + } else { + do_mq_unlink( qtabent ); + } // else + + retval = 0; + + exit_unlock: + interr = pthread_mutex_unlock( &mqtab_mut ); + // should never fail + CYG_ASSERT( interr == 0, "internal lock failed!" ); + CYG_REPORT_RETVAL( retval ); + return retval; +} // mq_unlink() + +//------------------------------------------------------------------------ + +externC int +mq_send( mqd_t mqdes, const char *msg_ptr, size_t msg_len, + unsigned int msg_prio ) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + CYG_REPORT_FUNCARG4( "mqdes=%08x, msg_ptr=%08x, msg_len=%u, msg_prio=%u", + mqdes, msg_ptr, msg_len, msg_prio ); + CYG_CHECK_DATA_PTRC( msg_ptr ); + + struct mquser *user = (struct mquser *)mqdes; + struct mqtabent *tabent = user->tabent; + +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + if ( user->magic != MQ_VALID_MAGIC ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return -1; + } +#endif + + if ( msg_len > (size_t)tabent->msgsize ) { + errno = EMSGSIZE; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + if ( msg_prio > MQ_PRIO_MAX ) { + errno = EINVAL; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + if ( (O_WRONLY != (user->flags & O_WRONLY)) && + (O_RDWR != (user->flags & O_RDWR)) ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + // go for it + Cyg_Mqueue::qerr_t err; + err = tabent->mq->put( msg_ptr, msg_len, msg_prio, + ((user->flags & O_NONBLOCK) != O_NONBLOCK) ); + switch (err) { + + case Cyg_Mqueue::INTR: + errno = EINTR; + CYG_REPORT_RETVAL( -1 ); + return -1; + + case Cyg_Mqueue::WOULDBLOCK: + CYG_ASSERT( (user->flags & O_NONBLOCK) == O_NONBLOCK, + "Message queue assumed non-blocking when blocking requested" + ); + errno = EAGAIN; + CYG_REPORT_RETVAL( -1 ); + return -1; + + case Cyg_Mqueue::OK: + CYG_REPORT_RETVAL( 0 ); + return 0; + + default: + CYG_FAIL( "unhandled message queue return code" ); + return -1; // keep compiler happy + } // switch +} // mq_send() + +//------------------------------------------------------------------------ + + +externC ssize_t +mq_receive( mqd_t mqdes, char *msg_ptr, size_t msg_len, + unsigned int *msg_prio ) +{ + CYG_REPORT_FUNCTYPE( "returning %ld" ); + CYG_REPORT_FUNCARG4( "mqdes=%08x, msg_ptr=%08x, msg_len=%u, msg_prio=%08x", + mqdes, msg_ptr, msg_len, msg_prio ); + CYG_CHECK_DATA_PTRC( msg_ptr ); + CYG_CHECK_DATA_PTRC( msg_ptr+msg_len-1 ); + if ( NULL != msg_prio ) + CYG_CHECK_DATA_PTRC( msg_prio ); + + + struct mquser *user = (struct mquser *)mqdes; + struct mqtabent *tabent = user->tabent; + +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + if ( user->magic != MQ_VALID_MAGIC ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return (ssize_t)-1; + } +#endif + + if ( (O_RDONLY != (user->flags & O_RDONLY)) && + (O_RDWR != (user->flags & O_RDWR)) ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return (ssize_t)-1; + } + + if ( msg_len < (size_t)tabent->msgsize ) { + errno = EMSGSIZE; + CYG_REPORT_RETVAL( -1 ); + return (ssize_t)-1; + } + + // go for it + Cyg_Mqueue::qerr_t err; + err = tabent->mq->get( msg_ptr, &msg_len, msg_prio, + ((user->flags & O_NONBLOCK) != O_NONBLOCK) ); + switch (err) { + + case Cyg_Mqueue::INTR: + errno = EINTR; + CYG_REPORT_RETVAL( -1 ); + return (ssize_t)-1; + + case Cyg_Mqueue::WOULDBLOCK: + CYG_ASSERT( (user->flags & O_NONBLOCK) == O_NONBLOCK, + "Message queue assumed non-blocking when blocking requested" + ); + errno = EAGAIN; + CYG_REPORT_RETVAL( -1 ); + return (ssize_t)-1; + + case Cyg_Mqueue::OK: + CYG_ASSERT( msg_len <= (size_t)tabent->msgsize, + "returned message too long" ); + if ( NULL != msg_prio ) + CYG_ASSERT( *msg_prio <= MQ_PRIO_MAX, + "returned message has invalid priority" ); + CYG_REPORT_RETVAL( msg_len ); + return (ssize_t)msg_len; + + default: + CYG_FAIL( "unhandled message queue return code" ); + return (ssize_t)-1; // keep compiler happy + } // switch + +} // mq_receive() + + +//------------------------------------------------------------------------ +#ifdef CYGFUN_KERNEL_THREADS_TIMER +externC int +mq_timedsend( mqd_t mqdes, const char *msg_ptr, size_t msg_len, + unsigned int msg_prio, const struct timespec *abs_timeout) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + CYG_REPORT_FUNCARG6( "mqdes=%08x, msg_ptr=%08x, msg_len=%u, msg_prio=%u, " + "abs_timeout = %lu, %ld", + mqdes, msg_ptr, msg_len, msg_prio, + abs_timeout->tv_sec, abs_timeout->tv_nsec); + CYG_CHECK_DATA_PTRC( msg_ptr ); + + struct mquser *user = (struct mquser *)mqdes; + struct mqtabent *tabent = user->tabent; + +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + if ( user->magic != MQ_VALID_MAGIC ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return -1; + } +#endif + + if ( msg_len > (size_t)tabent->msgsize ) { + errno = EMSGSIZE; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + if ( msg_prio > MQ_PRIO_MAX ) { + errno = EINVAL; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + if ( (O_WRONLY != (user->flags & O_WRONLY)) && + (O_RDWR != (user->flags & O_RDWR)) ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + // go for it + Cyg_Mqueue::qerr_t err; + bool nonblocking = ((user->flags & O_NONBLOCK) == O_NONBLOCK); + bool badtimespec = (abs_timeout->tv_nsec < 0) || + (abs_timeout->tv_nsec > 999999999l); + cyg_tick_count abs_ticks = cyg_timespec_to_ticks(abs_timeout); + + // We should never time out if there is room in the queue. Simplest + // way to ensure this is to try the non-blocking put() first. + err = tabent->mq->put( msg_ptr, msg_len, msg_prio, false, abs_ticks ); + + // If the blocking variant would have blocked and that is what's wanted + if ( Cyg_Mqueue::WOULDBLOCK == err && !nonblocking && !badtimespec ) { + err = tabent->mq->put( msg_ptr, msg_len, msg_prio, true, + abs_ticks ); + } + + switch (err) { + + case Cyg_Mqueue::INTR: + errno = EINTR; + CYG_REPORT_RETVAL( -1 ); + return -1; + + case Cyg_Mqueue::WOULDBLOCK: + if (badtimespec) { + errno = EINVAL; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + CYG_ASSERT( (user->flags & O_NONBLOCK) == O_NONBLOCK, + "Message queue assumed non-blocking when blocking requested" + ); + errno = EAGAIN; + CYG_REPORT_RETVAL( -1 ); + return -1; + + case Cyg_Mqueue::TIMEOUT: + errno = ETIMEDOUT; + CYG_REPORT_RETVAL( -1 ); + return -1; + + case Cyg_Mqueue::OK: + CYG_REPORT_RETVAL( 0 ); + return 0; + + default: + CYG_FAIL( "unhandled message queue return code" ); + return -1; // keep compiler happy + } // switch +} // mq_timedsend() + +//------------------------------------------------------------------------ + + +externC ssize_t +mq_timedreceive( mqd_t mqdes, char *msg_ptr, size_t msg_len, + unsigned int *msg_prio, const struct timespec *abs_timeout) +{ + CYG_REPORT_FUNCTYPE( "returning %ld" ); + CYG_REPORT_FUNCARG6( "mqdes=%08x, msg_ptr=%08x, msg_len=%u, msg_prio=%08x, " + "abs_timeout = %lu, %ld", + mqdes, msg_ptr, msg_len, msg_prio, + abs_timeout->tv_sec, abs_timeout->tv_nsec ); + CYG_CHECK_DATA_PTRC( msg_ptr ); + CYG_CHECK_DATA_PTRC( msg_ptr+msg_len-1 ); + if ( NULL != msg_prio ) + CYG_CHECK_DATA_PTRC( msg_prio ); + + + struct mquser *user = (struct mquser *)mqdes; + struct mqtabent *tabent = user->tabent; + +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + if ( user->magic != MQ_VALID_MAGIC ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return (ssize_t)-1; + } +#endif + + if ( (O_RDONLY != (user->flags & O_RDONLY)) && + (O_RDWR != (user->flags & O_RDWR)) ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return (ssize_t)-1; + } + + if ( msg_len < (size_t)tabent->msgsize ) { + errno = EMSGSIZE; + CYG_REPORT_RETVAL( -1 ); + return (ssize_t)-1; + } + + // go for it + Cyg_Mqueue::qerr_t err; + bool nonblocking = ((user->flags & O_NONBLOCK) == O_NONBLOCK); + bool badtimespec = (abs_timeout->tv_nsec < 0) || + (abs_timeout->tv_nsec > 999999999l); + cyg_tick_count abs_ticks = cyg_timespec_to_ticks(abs_timeout); + + // We should never time out if there is something to read. Simplest + // way to ensure this is to try the non-blocking get() first. + err = tabent->mq->get( msg_ptr, &msg_len, msg_prio, false, abs_ticks ); + + // If the blocking variant would have blocked and that is what's wanted + if ( Cyg_Mqueue::WOULDBLOCK == err && !nonblocking && !badtimespec ) { + err = tabent->mq->get( msg_ptr, &msg_len, msg_prio, true, abs_ticks ); + } + + switch (err) { + + case Cyg_Mqueue::INTR: + errno = EINTR; + CYG_REPORT_RETVAL( -1 ); + return (ssize_t)-1; + + case Cyg_Mqueue::WOULDBLOCK: + if (badtimespec) { + errno = EINVAL; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + CYG_ASSERT( (user->flags & O_NONBLOCK) == O_NONBLOCK, + "Message queue assumed non-blocking when blocking requested" + ); + errno = EAGAIN; + CYG_REPORT_RETVAL( -1 ); + return (ssize_t)-1; + + case Cyg_Mqueue::TIMEOUT: + errno = ETIMEDOUT; + CYG_REPORT_RETVAL( -1 ); + return -1; + + case Cyg_Mqueue::OK: + CYG_ASSERT( msg_len <= (size_t)tabent->msgsize, + "returned message too long" ); + if ( NULL != msg_prio ) + CYG_ASSERT( *msg_prio <= MQ_PRIO_MAX, + "returned message has invalid priority" ); + CYG_REPORT_RETVAL( msg_len ); + return (ssize_t)msg_len; + + default: + CYG_FAIL( "unhandled message queue return code" ); + return (ssize_t)-1; // keep compiler happy + } // switch + +} // mq_timedreceive() + +//------------------------------------------------------------------------ +#endif + +#ifdef CYGFUN_POSIX_MQUEUE_NOTIFY + +externC int +mq_notify( mqd_t mqdes, const struct sigevent *notification ) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + CYG_REPORT_FUNCARG2( "mqdes=%08x, notification=%08x", mqdes, notification ); + if ( NULL != notification ) + CYG_CHECK_DATA_PTRC( notification ); + + struct mquser *user = (struct mquser *)mqdes; + struct mqtabent *tabent = user->tabent; + +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + if ( user->magic != MQ_VALID_MAGIC ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return -1; + } +#endif + + // lock scheduler since we test and set non-atomically + Cyg_Scheduler::lock(); + + // we are being told to clear the notification function + if ( NULL == notification ) { + tabent->mq->setnotify( NULL, 0 ); + tabent->sigev = NULL; + Cyg_Scheduler::unlock(); + CYG_REPORT_RETVAL( 0 ); + return 0; + } // if + + if ( NULL != tabent->sigev ) { // already registered + Cyg_Scheduler::unlock(); + errno = EBUSY; + CYG_REPORT_RETVAL( -1 ); + return -1; + } // if + + tabent->sigev = notification; + user->notifieruser = true; // Used for deciding about whether to + // deregister in mq_close() + tabent->mq->setnotify( ¬ifyme, (CYG_ADDRWORD) user ); + Cyg_Scheduler::unlock(); + + CYG_REPORT_RETVAL( 0 ); + return 0; +} // mq_notify() + +#endif // ifdef CYGFUN_POSIX_MQUEUE_NOTIFY + +//------------------------------------------------------------------------ + +externC int +mq_setattr( mqd_t mqdes, const struct mq_attr *mqstat, + struct mq_attr *omqstat ) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + CYG_REPORT_FUNCARG3( "mqdes=%08x, mqstat=%08x, omqstat=%08x", + mqdes, mqstat, omqstat ); + CYG_CHECK_DATA_PTRC( mqstat ); + + struct mquser *user = (struct mquser *)mqdes; + +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + if ( user->magic != MQ_VALID_MAGIC ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return -1; + } +#endif + + if ( NULL != omqstat ) { + CYG_CHECK_DATA_PTRC( omqstat ); + mq_getattr( mqdes, omqstat ); + } // if + + // Two-stage update, so lock sched since it's quick + Cyg_Scheduler::lock(); + user->flags &= ~O_NONBLOCK; // clear + if ( (mqstat->mq_flags & O_NONBLOCK) == O_NONBLOCK ) { + user->flags |= O_NONBLOCK; + } // if + Cyg_Scheduler::unlock(); + + CYG_REPORT_RETVAL( 0 ); + return 0; +} // mq_setattr() + +//------------------------------------------------------------------------ + +externC int +mq_getattr( mqd_t mqdes, struct mq_attr *mqstat ) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + CYG_REPORT_FUNCARG2( "mqdes=%08x, mqstat=%08x", mqdes, mqstat ); + CYG_CHECK_DATA_PTRC( mqstat ); + + struct mquser *user = (struct mquser *)mqdes; + struct mqtabent *tabent = user->tabent; + +#ifdef CYGIMP_POSIX_MQUEUE_VALIDATE_DESCRIPTOR + if ( user->magic != MQ_VALID_MAGIC ) { + errno = EBADF; + CYG_REPORT_RETVAL( -1 ); + return -1; + } +#endif + + mqstat->mq_flags = user->flags; + mqstat->mq_maxmsg = tabent->maxmsg; + mqstat->mq_msgsize = tabent->msgsize; + mqstat->mq_curmsgs = tabent->mq->count(); + + CYG_REPORT_RETVAL( 0 ); + return 0; +} // mq_getattr() + + +//------------------------------------------------------------------------ + +#endif // ifdef CYGPKG_POSIX_MQUEUES + +/* EOF mqueue.cxx */ diff --git a/packages/compat/posix/v2_0/src/mutex.cxx b/packages/compat/posix/v2_0/src/mutex.cxx new file mode 100644 index 00000000..66dbf451 --- /dev/null +++ b/packages/compat/posix/v2_0/src/mutex.cxx @@ -0,0 +1,551 @@ +//========================================================================== +// +// pthread.cxx +// +// POSIX pthreads implementation +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg, jlarmour, Wade Jensen +// Date: 2000-03-27 +// Purpose: POSIX pthread implementation +// Description: This file contains the implementation of the POSIX pthread +// functions. +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +#include // tracing macros +#include // assertion macros + +#include "pprivate.h" // POSIX private header + +#include // thread definitions +#include // mutex definitions +#include // clock definitions +#include // scheduler primitives +#include + +#include // thread inlines +#include // scheduler inlines + +//----------------------------------------------------------------------------- +// new operator to allow us to construct mutex objects + +inline void *operator new(size_t size, cyg_uint8 *ptr) { return (void *)ptr; }; + +//============================================================================= +// Mutexes + +//----------------------------------------------------------------------------- +// Mutex attributes manipulation functions + +//----------------------------------------------------------------------------- +// Initialize attribute object + +externC int pthread_mutexattr_init ( pthread_mutexattr_t *attr) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + attr->protocol = PTHREAD_PRIO_NONE; +#ifdef _POSIX_THREAD_PRIO_PROTECT + attr->prioceiling = 0; +#endif + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Destroy attribute object + +externC int pthread_mutexattr_destroy ( pthread_mutexattr_t *attr) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + // Nothing to do here... + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Optional functions depending on priority inversion protection options. + +#if defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT) + +// Set priority inversion protection protocol +externC int pthread_mutexattr_setprotocol ( pthread_mutexattr_t *attr, + int protocol) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + switch( protocol ) + { + case PTHREAD_PRIO_NONE: +#if defined(_POSIX_THREAD_PRIO_INHERIT) + case PTHREAD_PRIO_INHERIT: +#endif +#if defined(_POSIX_THREAD_PRIO_PROTECT) + case PTHREAD_PRIO_PROTECT: +#endif + attr->protocol = protocol; + PTHREAD_RETURN(0); + + default: + PTHREAD_RETURN(EINVAL); + } + + PTHREAD_RETURN(0); +} + +// Get priority inversion protection protocol +externC int pthread_mutexattr_getprotocol ( pthread_mutexattr_t *attr, + int *protocol) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( protocol != NULL ) + *protocol = attr->protocol; + + PTHREAD_RETURN(0); +} + +#if defined(_POSIX_THREAD_PRIO_PROTECT) + +// Set priority for priority ceiling protocol +externC int pthread_mutexattr_setprioceiling ( pthread_mutexattr_t *attr, + int prioceiling) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + + attr->prioceiling = prioceiling; + + PTHREAD_RETURN(0); +} + +// Get priority for priority ceiling protocol +externC int pthread_mutexattr_getprioceiling ( pthread_mutexattr_t *attr, + int *prioceiling) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( prioceiling != NULL ) + *prioceiling = attr->prioceiling; + + PTHREAD_RETURN(0); +} + +// Set priority ceiling of given mutex, returning old ceiling. +externC int pthread_mutex_setprioceiling( pthread_mutex_t *mutex, + int prioceiling, + int *old_ceiling) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(mutex); + + pthread_mutex_lock( mutex ); + + Cyg_Mutex *mx = (Cyg_Mutex *)mutex; + + if( old_ceiling != NULL ) + *old_ceiling = mx->get_ceiling(); + + mx->set_ceiling( prioceiling ); + + pthread_mutex_unlock( mutex ); + + PTHREAD_RETURN(0); +} + +// Get priority ceiling of given mutex +externC int pthread_mutex_getprioceiling( pthread_mutex_t *mutex, + int *prioceiling) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(mutex); + + Cyg_Mutex *mx = (Cyg_Mutex *)mutex; + + if( prioceiling != NULL ) + *prioceiling = mx->get_ceiling(); + + PTHREAD_RETURN(0); +} + +#endif // defined(_POSIX_THREAD_PRIO_PROTECT) + +#endif // defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT) + +//----------------------------------------------------------------------------- +// Mutex functions + +//----------------------------------------------------------------------------- +// Initialize mutex. If mutex_attr is NULL, use default attributes. + +externC int pthread_mutex_init (pthread_mutex_t *mutex, + const pthread_mutexattr_t *mutex_attr) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK( mutex ); + + pthread_mutexattr_t use_attr; + + // Set up the attributes we are going to use + if( mutex_attr == NULL ) + pthread_mutexattr_init( &use_attr ); + else use_attr = *mutex_attr; + + // Now translate the POSIX protocol identifier into the eCos one. + Cyg_Mutex::cyg_protcol protocol; + + switch( use_attr.protocol ) + { +#if defined(_POSIX_THREAD_PRIO_PROTECT) + case PTHREAD_PRIO_PROTECT: + protocol = Cyg_Mutex::CEILING; + break; +#endif +#if defined(_POSIX_THREAD_PRIO_INHERIT) + case PTHREAD_PRIO_INHERIT: + protocol = Cyg_Mutex::INHERIT; + break; +#endif + case PTHREAD_PRIO_NONE: + protocol = Cyg_Mutex::NONE; + break; + + default: + PTHREAD_RETURN(EINVAL); + } + + Cyg_Mutex *mx = new((cyg_uint8 *)mutex) Cyg_Mutex( protocol ); + + mx = mx; // silence compiler warning +#if defined(_POSIX_THREAD_PRIO_PROTECT) + if ( protocol == Cyg_Mutex::CEILING ) + mx->set_ceiling( use_attr.prioceiling ); +#endif + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Destroy mutex. + +externC int pthread_mutex_destroy (pthread_mutex_t *mutex) +{ + PTHREAD_ENTRY(); + + int err = ENOERR; + + PTHREAD_CHECK( mutex ); + + Cyg_Mutex *mx = (Cyg_Mutex *)mutex; + + if( mx->get_owner() != NULL ) + err = EBUSY; + else mx->~Cyg_Mutex(); + + PTHREAD_RETURN(err); +} + +//----------------------------------------------------------------------------- +// Lock mutex, waiting for it if necessary. + +externC int pthread_mutex_lock (pthread_mutex_t *mutex) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK( mutex ); + + Cyg_Mutex *mx = (Cyg_Mutex *)mutex; + + if( mx->get_owner() == Cyg_Thread::self() ) + PTHREAD_RETURN(EDEADLK); + + // Loop here until we acquire the mutex. Even if we are kicked out + // of the wait by a signal or release we must retry. + while( !mx->lock() ) + continue; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Try to lock mutex. + +externC int pthread_mutex_trylock (pthread_mutex_t *mutex) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK( mutex ); + + Cyg_Mutex *mx = (Cyg_Mutex *)mutex; + + if( mx->get_owner() == Cyg_Thread::self() ) + PTHREAD_RETURN(EDEADLK); + + if( mx->trylock() ) + PTHREAD_RETURN(0); + + PTHREAD_RETURN(EBUSY); +} + + +//----------------------------------------------------------------------------- +// Unlock mutex. + +externC int pthread_mutex_unlock (pthread_mutex_t *mutex) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK( mutex ); + + Cyg_Mutex *mx = (Cyg_Mutex *)mutex; + + mx->unlock(); + + PTHREAD_RETURN(0); +} + + +//============================================================================= +// Condition Variables + +//----------------------------------------------------------------------------- +// Attribute manipulation functions +// We do not actually support any attributes at present, so these do nothing. + +//----------------------------------------------------------------------------- +// Initialize condition variable attributes + +externC int pthread_condattr_init (pthread_condattr_t *attr) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + // There are no condition variable attributes at present + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Destroy condition variable attributes + +externC int pthread_condattr_destroy (pthread_condattr_t *attr) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + // nothing to do here... + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Condition variable functions + +//----------------------------------------------------------------------------- +// Initialize condition variable. + +externC int pthread_cond_init (pthread_cond_t *cond, + const pthread_condattr_t *attr) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK( cond ); + + Cyg_Condition_Variable *cv = + new((cyg_uint8 *)cond) Cyg_Condition_Variable(); + + cv = cv; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Destroy condition variable. + +externC int pthread_cond_destroy (pthread_cond_t *cond) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK( cond ); + + ((Cyg_Condition_Variable *)cond)->~Cyg_Condition_Variable(); + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Wake up one thread waiting for condition variable + +externC int pthread_cond_signal (pthread_cond_t *cond) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK( cond ); + + ((Cyg_Condition_Variable *)cond)->signal(); + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Wake up all threads waiting for condition variable + +externC int pthread_cond_broadcast (pthread_cond_t *cond) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK( cond ); + + ((Cyg_Condition_Variable *)cond)->broadcast(); + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Block on condition variable until signalled. The mutex is +// assumed to be locked before this call, will be unlocked +// during the wait, and will be re-locked on wakeup. + +externC int pthread_cond_wait (pthread_cond_t *cond, + pthread_mutex_t *mutex) +{ + PTHREAD_ENTRY(); + + // check for cancellation first. + PTHREAD_TESTCANCEL(); + + PTHREAD_CHECK( cond ); + PTHREAD_CHECK( mutex ); + + ((Cyg_Condition_Variable *)cond)->wait( *(Cyg_Mutex *)mutex ); + + // check if we were woken because we were being cancelled + PTHREAD_TESTCANCEL(); + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Block on condition variable until signalled, or the timeout expires. + +externC int pthread_cond_timedwait (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + PTHREAD_ENTRY(); + + // check for cancellation first. + PTHREAD_TESTCANCEL(); + + PTHREAD_CHECK( cond ); + PTHREAD_CHECK( mutex ); + PTHREAD_CHECK( abstime ); + + // Only initialize the converters once or they will consume a huge + // amount or runtime. + + static struct Cyg_Clock::converter ns_converter; + static struct Cyg_Clock::converter sec_converter; + static volatile cyg_atomic conv_init; + if (!conv_init) + { + + // Try to avoid unnecessarily locking the scheduler when we are not + // initializing the converters. Check the conv_init flag again to + // avoid race conditions. + + struct Cyg_Clock::converter temp_ns_converter, temp_sec_converter; + + Cyg_Clock::real_time_clock + ->get_other_to_clock_converter( 1, &temp_ns_converter ); + Cyg_Clock::real_time_clock + ->get_other_to_clock_converter( 1000000000, &temp_sec_converter ); + + Cyg_Scheduler::lock(); + if (!conv_init) + { + ns_converter = temp_ns_converter; + sec_converter = temp_sec_converter; + conv_init=1; + } + Cyg_Scheduler::unlock(); + } + + cyg_tick_count ticks; + ticks = Cyg_Clock::convert( abstime->tv_sec, &sec_converter ); + ticks += Cyg_Clock::convert( abstime->tv_nsec, &ns_converter ); + + ((Cyg_Condition_Variable *)cond)->wait( *(Cyg_Mutex *)mutex, ticks ); + + // check if we were woken because we were being cancelled + PTHREAD_TESTCANCEL(); + + if ( Cyg_Thread::self()->get_wake_reason() == Cyg_Thread::TIMEOUT ) + PTHREAD_RETURN(ETIMEDOUT); + else + PTHREAD_RETURN(0); +} + +// ------------------------------------------------------------------------- +// EOF mutex.cxx diff --git a/packages/compat/posix/v2_0/src/pprivate.h b/packages/compat/posix/v2_0/src/pprivate.h new file mode 100644 index 00000000..e76cdb0f --- /dev/null +++ b/packages/compat/posix/v2_0/src/pprivate.h @@ -0,0 +1,271 @@ +#ifndef CYGONCE_PPRIVATE_H +#define CYGONCE_PPRIVATE_H +//============================================================================= +// +// pprivate.h +// +// POSIX types header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-03-17 +// Purpose: POSIX private header +// Description: This header contains various POSIX type definitions that are +// shared between the various parts of the POSIX package. +// +// Usage: #include +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include + +#include // NULL, size_t + +#include +#include +#include +#include // error codes +#include // sigset_t +#include // PTHREAD_KEYS_MAX + +#include // POSIX exports header + +#include // thread definitions +#include // mutex definitions + +//============================================================================= +// Constructor prioritization + +// Prioritization for POSIX library support objects +#define CYGBLD_POSIX_INIT CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_COMPAT) + +// Prioritization for POSIX library startup initialization. This must +// come after CYGBLD_POSIX_INIT constructors. +#define CYGBLD_POSIX_START CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_COMPAT+5) + +//============================================================================= +// Thread control data structure + +// Per-thread information needed by POSIX +// This is pointed to by the CYGNUM_KERNEL_THREADS_DATA_POSIX entry of the +// per-thread data. + +#ifdef CYGPKG_POSIX_PTHREAD +typedef struct +{ + unsigned int state:4, // Thread state + cancelstate:2, // Cancel state of thread + canceltype:2, // Cancel type of thread + cancelpending:1, // pending cancel flag + freestack:1; // stack malloced, must be freed + + pthread_t id; // My thread ID + Cyg_Thread *thread; // pointer to eCos thread object + pthread_attr_t attr; // Current thread attributes + void *retval; // return value + void *(*start_routine)(void *); // start routine + void *start_arg; // argument to start routine + char name[20]; // name string for debugging + Cyg_Condition_Variable *joiner; // joining threads wait here + CYG_ADDRWORD stackmem; // base of stack memory area + // only valid if freestack == true + + struct pthread_cleanup_buffer *cancelbuffer; // stack of cleanup buffers + +#ifdef CYGPKG_POSIX_SIGNALS + sigset_t sigpending; // Set of pending signals + sigset_t sigmask; // Thread's signal mask +#endif + + // The following is space for the eCos thread object that underlies + // this POSIX thread. It is allocated like this to avoid constructing + // it on startup. + cyg_uint8 thread_obj[sizeof(Cyg_Thread)]; + + // And the same for the joiner condition variable. + cyg_uint8 joiner_obj[sizeof(Cyg_Condition_Variable)]; + + // Per-thread data table pointer + void **thread_data; + +} pthread_info; + + +// Values for the state field. These are solely concerned with the +// states visible to POSIX. The thread's run state is stored in the +// eCos thread object. +// Note: numerical order here is important, do not rearrange. + +#define PTHREAD_STATE_FREE 0 // This structure is free for reuse +#define PTHREAD_STATE_DETACHED 1 // The thread is running but detached +#define PTHREAD_STATE_RUNNING 2 // The thread is running and will wait + // to join when it exits +#define PTHREAD_STATE_JOIN 3 // The thread has exited and is waiting + // to be joined +#define PTHREAD_STATE_EXITED 4 // The thread has exited and is ready to + // be reaped +#endif // ifdef CYGPKG_POSIX_PTHREAD +//----------------------------------------------------------------------------- +// Internal definitions + +// Handle entry to a pthread package function. +#define PTHREAD_ENTRY() CYG_REPORT_FUNCTYPE( "returning %d" ) + +// Handle entry to a pthread package function with no args. +#define PTHREAD_ENTRY_VOID() CYG_REPORT_FUNCTION() + +// Do a pthread package defined return. This requires the error code to be +// returned as the result of the function. This also gives us a place to +// put any generic tidyup handling needed for things like signal delivery +// and cancellation. +#define PTHREAD_RETURN(err) \ +CYG_MACRO_START \ + CYG_REPORT_RETVAL( err ); \ + return err; \ +CYG_MACRO_END + +// A void variant of the above. +#define PTHREAD_RETURN_VOID \ +CYG_MACRO_START \ + CYG_REPORT_RETURN(); \ + return; \ +CYG_MACRO_END + +// Check that a pointer passed in as an argument is valid and return +// EINVAL if it is not. This should be used to check pointers that are +// required to be valid. Pointers that may optionally be NULL should +// be checked within the function. +#define PTHREAD_CHECK(ptr) if( (ptr) == NULL ) PTHREAD_RETURN(EINVAL); + +#ifdef CYGPKG_POSIX_PTHREAD +# define PTHREAD_TESTCANCEL() pthread_testcancel() +#else +# define PTHREAD_TESTCANCEL() +#endif + +//----------------------------------------------------------------------------- +// Priority translation. +// eCos priorities run from 0 as the highest to 31 as the lowest. POSIX priorities +// run in the opposite direction. The following macros translate between the two +// priority ranges. + +#define PTHREAD_ECOS_PRIORITY(pri) (CYG_THREAD_MIN_PRIORITY-(pri)) + +#define PTHREAD_POSIX_PRIORITY(pri) (CYG_THREAD_MIN_PRIORITY-(pri)) + +//----------------------------------------------------------------------------- +// Global data structures + +// Mutex for locking access to pthread_info structures +extern Cyg_Mutex pthread_mutex; + +//----------------------------------------------------------------------------- +// Functions exported by pthread.cxx to the other parts of the POSIX subsystem. + +#ifdef CYGPKG_POSIX_PTHREAD +externC void cyg_posix_pthread_start( void ); + +externC pthread_info *pthread_self_info(void); + +externC pthread_info *pthread_info_id( pthread_t id ); + +# ifdef CYGPKG_POSIX_SIGNALS +externC void cyg_posix_pthread_release_thread( sigset_t *mask ); +# endif +#endif + +//----------------------------------------------------------------------------- +// Functions exported by signal.cxx to the other parts of the POSIX subsystem. + +#ifdef CYGPKG_POSIX_SIGNALS +externC void cyg_posix_signal_start(); + +externC void cyg_posix_signal_asr(pthread_info *self); + +externC cyg_bool cyg_sigqueue( const struct sigevent *sev, int code, + pthread_info *thread = NULL ); + +externC cyg_bool cyg_deliver_signals(); + +externC void cyg_posix_signal_sigwait(); + +externC void cyg_posix_thread_siginit( pthread_info *thread, + pthread_info *parentthread ); + +externC void cyg_posix_thread_sigdestroy( pthread_info *thread ); +#endif + +//----------------------------------------------------------------------------- +// Functions exported by time.cxx to other parts of the POSIX subsystem. + +#ifdef CYGPKG_POSIX_CLOCKS +externC void cyg_posix_clock_start(); + +externC cyg_tick_count cyg_timespec_to_ticks( const struct timespec *tp, + cyg_bool roundup = false); + +externC void cyg_ticks_to_timespec( cyg_tick_count ticks, struct timespec *tp ); + +#endif + +#ifdef CYGPKG_POSIX_TIMERS + +externC void cyg_posix_timer_asr( pthread_info *self ); + +#endif + +//----------------------------------------------------------------------------- +// Functions exported by except.cxx + +#ifdef CYGPKG_POSIX_SIGNALS +externC void cyg_posix_exception_start(); + +externC void cyg_pthread_exception_init(pthread_info *thread); + +externC void cyg_pthread_exception_destroy(pthread_info *thread); +#endif + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_PPRIVATE_H +// End of pprivate.h diff --git a/packages/compat/posix/v2_0/src/pthread.cxx b/packages/compat/posix/v2_0/src/pthread.cxx new file mode 100644 index 00000000..068cdf0a --- /dev/null +++ b/packages/compat/posix/v2_0/src/pthread.cxx @@ -0,0 +1,1679 @@ +//========================================================================== +// +// pthread.cxx +// +// POSIX pthreads implementation +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg, jlarmour +// Date: 2000-03-27 +// Purpose: POSIX pthread implementation +// Description: This file contains the implementation of the POSIX pthread +// functions. +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include +#include +#include + +#include // base kernel types +#include // tracing macros +#include // assertion macros + +#include "pprivate.h" // POSIX private header + +#include // malloc(), free() + +#include // scheduler definitions +#include // thread definitions +#include // clock definitions + +#include // scheduler inlines + +//----------------------------------------------------------------------------- +// First check that the configuration contains the elements we need + +#ifndef CYGPKG_KERNEL +#error POSIX pthread need eCos kernel +#endif + +#ifndef CYGSEM_KERNEL_SCHED_MLQUEUE +#error POSIX pthreads need MLQ scheduler +#endif + +#ifndef CYGSEM_KERNEL_SCHED_TIMESLICE +#error POSIX pthreads need timeslicing +#endif + +#ifndef CYGVAR_KERNEL_THREADS_DATA +#error POSIX pthreads need per-thread data +#endif + +//============================================================================= +// Internal data structures + +// Mutex for controlling access to shared data structures +Cyg_Mutex pthread_mutex CYGBLD_POSIX_INIT; + +// Array of pthread control structures. A pthread_t object is +// "just" an index into this array. +static pthread_info *thread_table[CYGNUM_POSIX_PTHREAD_THREADS_MAX]; + +// Count of number of threads in table. +static int pthread_count = 0; + +// Count of number of threads that have exited and not been reaped. +static int pthreads_exited; + +// Count of number of threads that are waiting to be joined +static int pthreads_tobejoined; + +// Per-thread key allocation. This key map has a 1 bit set for each +// key that is free, zero if it is allocated. +#define KEY_MAP_TYPE cyg_uint32 +#define KEY_MAP_TYPE_SIZE (sizeof(KEY_MAP_TYPE)*8) // in BITS! +static KEY_MAP_TYPE thread_key[PTHREAD_KEYS_MAX/KEY_MAP_TYPE_SIZE]; +static void (*key_destructor[PTHREAD_KEYS_MAX]) (void *); + +// Index of next pthread_info to allocate from thread_table array. +static int thread_info_next = 0; + +// This is used to make pthread_t values unique even when reusing +// a table slot. This allows CYGNUM_POSIX_PTHREAD_THREADS_MAX to range +// up to 1024. +#define THREAD_ID_COOKIE_INC 0x00000400 +#define THREAD_ID_COOKIE_MASK (THREAD_ID_COOKIE_INC-1) +static pthread_t thread_id_cookie = THREAD_ID_COOKIE_INC; + +//----------------------------------------------------------------------------- +// Main thread. + +#define MAIN_DEFAULT_STACK_SIZE \ + (CYGNUM_LIBC_MAIN_DEFAULT_STACK_SIZE < PTHREAD_STACK_MIN \ + ? PTHREAD_STACK_MIN : CYGNUM_LIBC_MAIN_DEFAULT_STACK_SIZE) + +static char main_stack[MAIN_DEFAULT_STACK_SIZE]; + +// Thread ID of main thread. +static pthread_t main_thread; + +//============================================================================= +// Exported variables + +int pthread_canceled_dummy_var; // pointed to by PTHREAD_CANCELED + +//============================================================================= +// Internal functions + +//----------------------------------------------------------------------------- +// Private version of pthread_self() that returns a pointer to our internal +// control structure. + +pthread_info *pthread_self_info(void) +{ + Cyg_Thread *thread = Cyg_Thread::self(); + + CYG_CHECK_DATA_PTR(thread, "Illegal current thread"); + + pthread_info *info = (pthread_info *)thread->get_data(CYGNUM_KERNEL_THREADS_DATA_POSIX); + + // This assertion mustn't be enabled because sometimes we can legitimately + // carefully call this as long as we realise the value can be NULL. + // e.g. consider the use of this when inheriting sigmasks when in the + // context of creating the main() thread. +// CYG_CHECK_DATA_PTR(info, "Not a POSIX thread!!!"); + + return info; +} + +externC pthread_info *pthread_info_id( pthread_t id ) +{ + pthread_t index = id & THREAD_ID_COOKIE_MASK; + + pthread_info *info = thread_table[index]; + + // Check for a valid entry + if( info == NULL ) + return NULL; + + // Check that this is a valid entry + if ( info->state == PTHREAD_STATE_FREE || + info->state == PTHREAD_STATE_EXITED ) + return NULL; + + // Check that the entry matches the id + if( info->id != id ) return NULL; + + // Return the pointer + return info; +} + +//----------------------------------------------------------------------------- +// new operator to allow us to invoke the Cyg_Thread constructor on the +// pthread_info.thread_obj array. + +inline void *operator new(size_t size, cyg_uint8 *ptr) { return (void *)ptr; }; + +//----------------------------------------------------------------------------- +// Optional memory allocation functions for pthread stacks. +// If there is an implementation of malloc() available, define pthread_malloc() +// and pthread_free() to use it. Otherwise define them to do nothing. +// In the future we may want to add configuration here to permit thread stacks +// to be allocated in a nominated memory pool separate from the standard malloc() +// pool. Hence the (currently redundant) encapsulation of these functions. + +#if CYGINT_ISO_MALLOC + +static __inline__ CYG_ADDRWORD pthread_malloc( CYG_ADDRWORD size ) +{ + return (CYG_ADDRWORD)malloc( size ); +} + +static __inline__ void pthread_free( CYG_ADDRWORD m ) +{ + free( (void *)m ); +} + +#define PTHREAD_MALLOC + +#else + +#define pthread_malloc(_x_) (0) + +#define pthread_free(_x_) + +#endif + +//----------------------------------------------------------------------------- +// pthread entry function. +// does some housekeeping and then calls the user's start routine. + +static void pthread_entry(CYG_ADDRWORD data) +{ + pthread_info *self = (pthread_info *)data; + + void *retval = self->start_routine(self->start_arg); + + pthread_exit( retval ); +} + +//----------------------------------------------------------------------------- +// Main entry function. +// This is set as the start_routine of the main thread. It invokes main() +// and if it returns, shuts down the system. + +externC void cyg_libc_invoke_main( void ); + +static void *call_main( void * ) +{ + cyg_libc_invoke_main(); + return NULL; // placate compiler +} + +//----------------------------------------------------------------------------- +// Check whether there is a cancel pending and if so, whether +// cancellations are enabled. We do it in this order to reduce the +// number of tests in the common case - when no cancellations are +// pending. +// We make this inline so it can be called directly below for speed + +static __inline__ int +checkforcancel( void ) +{ + pthread_info *self = pthread_self_info(); + + if( self != NULL && + self->cancelpending && + self->cancelstate == PTHREAD_CANCEL_ENABLE ) + return 1; + else + return 0; +} + + +//----------------------------------------------------------------------------- +// POSIX ASR +// This is installed as the ASR for all POSIX threads. + +static void posix_asr( CYG_ADDRWORD data ) +{ + pthread_info *self = (pthread_info *)data; + +#ifdef CYGPKG_POSIX_TIMERS + // Call into timer subsystem to deliver any pending + // timer expirations. + cyg_posix_timer_asr(self); +#endif + +#ifdef CYGPKG_POSIX_SIGNALS + // Call signal subsystem to deliver any signals + cyg_posix_signal_asr(self); +#endif + + // Check for cancellation + if( self->cancelpending && + self->cancelstate == PTHREAD_CANCEL_ENABLE && + self->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS ) + { + // If we have a pending cancellation, cancellations are + // enabled and we are in asynchronous mode, then we can do the + // cancellation processing. Since pthread_exit() does + // everything we need to do, we just call that here. + + pthread_exit(PTHREAD_CANCELED); + } +} + +//----------------------------------------------------------------------------- +// The (Grim) Reaper. +// This function is called to tidy up and dispose of any threads that have +// exited. This work must be done from a thread other than the one exiting. +// Note: this function _must_ be called with pthread_mutex locked. + +static void pthread_reap() +{ + int i; + + // Loop over the thread table looking for exited threads. The + // pthreads_exited counter springs us out of this once we have + // found them all (and keeps us out if there are none to do). + + for( i = 0; pthreads_exited && i < CYGNUM_POSIX_PTHREAD_THREADS_MAX ; i++ ) + { + pthread_info *thread = thread_table[i]; + + if( thread != NULL && thread->state == PTHREAD_STATE_EXITED ) + { + // The thread has exited, so it is a candidate for being + // reaped. We have to make sure that the eCos thread has + // also reached EXITED state before we can tidy it up. + + while( thread->thread->get_state() != Cyg_Thread::EXITED ) + { + // The eCos thread has not yet exited. This is + // probably because its priority is too low to allow + // it to complete. We fix this here by raising its + // priority to equal ours and then yielding. This + // should eventually get it into exited state. + + Cyg_Thread *self = Cyg_Thread::self(); + + // Set thread's priority to our current dispatching priority. + thread->thread->set_priority( self->get_current_priority() ); + + // Yield, yield + self->yield(); + + // and keep looping until he exits. + } + + // At this point we have a thread that we can reap. + + // destroy the eCos thread + thread->thread->~Cyg_Thread(); + + // destroy the joiner condvar + thread->joiner->~Cyg_Condition_Variable(); + +#ifdef CYGPKG_POSIX_SIGNALS + // Destroy signal handling fields + cyg_posix_thread_sigdestroy( thread ); +#endif + + // Free the stack if we allocated it + if( thread->freestack ) + pthread_free( thread->stackmem ); + + // Finally, set the thread table entry to NULL so that it + // may be reused. + thread_table[i] = NULL; + + pthread_count--; + pthreads_exited--; + } + } +} + +//============================================================================= +// Functions exported to rest of POSIX subsystem. + +//----------------------------------------------------------------------------- +// Create the main() thread. + +externC void cyg_posix_pthread_start( void ) +{ + + // Initialize the per-thread data key map. + + for( cyg_ucount32 i = 0; i < (PTHREAD_KEYS_MAX/KEY_MAP_TYPE_SIZE); i++ ) + { + thread_key[i] = ~0; + } + + // Create the main thread + pthread_attr_t attr; + struct sched_param schedparam; + + schedparam.sched_priority = CYGNUM_POSIX_MAIN_DEFAULT_PRIORITY; + + pthread_attr_init( &attr ); + pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); + pthread_attr_setstackaddr( &attr, &main_stack[sizeof(main_stack)] ); + pthread_attr_setstacksize( &attr, sizeof(main_stack) ); + pthread_attr_setschedpolicy( &attr, SCHED_RR ); + pthread_attr_setschedparam( &attr, &schedparam ); + + pthread_create( &main_thread, &attr, call_main, NULL ); +} + +#ifdef CYGPKG_POSIX_SIGNALS +//----------------------------------------------------------------------------- +// Look for a thread that can accept delivery of any of the signals in +// the mask and release it from any wait it is in. Since this may be +// called from a DSR, it cannot use any locks internally - any locking +// should be done before the call. + +externC void cyg_posix_pthread_release_thread( sigset_t *mask ) +{ + int i; + int count = pthread_count; + + // Loop over the thread table looking for a thread that has a + // signal mask that does not mask all the signals in mask. + // FIXME: find a more efficient way of doing this. + + for( i = 0; count > 0 && i < CYGNUM_POSIX_PTHREAD_THREADS_MAX ; i++ ) + { + pthread_info *thread = thread_table[i]; + + if( (thread != NULL) && + (thread->state <= PTHREAD_STATE_RUNNING) && + ((*mask & ~thread->sigmask) != 0) ) + { + // This thread can service at least one of the signals in + // *mask. Knock it out of its wait and make its ASR pending. + + thread->thread->set_asr_pending(); + thread->thread->release(); + break; + } + + // Decrement count for each valid thread we find. + if( thread != NULL && thread->state != PTHREAD_STATE_FREE ) + count--; + } +} +#endif + +//============================================================================= +// General thread operations + +//----------------------------------------------------------------------------- +// Thread creation and management. + +// Create a thread. +externC int pthread_create ( pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine) (void *), + void *arg) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(thread); + PTHREAD_CHECK(start_routine); + + pthread_info *self = pthread_self_info(); + + pthread_attr_t use_attr; + + // Set use_attr to the set of attributes we are going to + // actually use. Either those passed in, or the default set. + + if( attr == NULL ) + pthread_attr_init( &use_attr ); + else use_attr = *attr; + + // Adjust the attributes to cope with the setting of inheritsched. + + if( use_attr.inheritsched == PTHREAD_INHERIT_SCHED ) + { + CYG_ASSERT( NULL != self, + "Attempt to inherit sched policy from non-POSIX thread" ); +#ifdef CYGDBG_USE_ASSERTS + // paranoia check + int i; + for (i=(sizeof(thread_table)/sizeof(*thread_table))-1; i>=0; i--) { + if (thread_table[i] == self) + break; + } + CYG_ASSERT( i>=0, "Current pthread not found in table" ); +#endif + use_attr.schedpolicy = self->attr.schedpolicy; + use_attr.schedparam = self->attr.schedparam; + } + + CYG_ADDRWORD stackbase, stacksize; + cyg_bool freestack = false; + CYG_ADDRWORD stackmem = 0; + + // If the stack size is not valid, we can assume that it is at + // least PTHREAD_STACK_MIN bytes. + + if( use_attr.stacksize_valid ) + stacksize = use_attr.stacksize; + else stacksize = PTHREAD_STACK_MIN; + + if( use_attr.stackaddr_valid ) + { + // Set up stack base and size from supplied arguments. + + // Calculate stack base from address and size. + // FIXME: Falling stack assumed in pthread_create(). + stackmem = stackbase = (CYG_ADDRWORD)use_attr.stackaddr-stacksize; + } + else + { +#ifdef PTHREAD_MALLOC + + stackmem = stackbase = pthread_malloc( stacksize ); + + if( stackmem == 0 ) + PTHREAD_RETURN( EAGAIN ); + + freestack = true; +#else + PTHREAD_RETURN(EINVAL); +#endif + + } + + // Get sole access to data structures + + pthread_mutex.lock(); + + // Dispose of any dead threads + pthread_reap(); + + // Find a free slot in the thread table + + pthread_info *nthread; + int thread_next = thread_info_next; + + while( thread_table[thread_next] != NULL ) + { + thread_next++; + if( thread_next >= CYGNUM_POSIX_PTHREAD_THREADS_MAX ) + thread_next = 0; + + // check for wrap, and return error if no slots left + if( thread_next == thread_info_next ) + { + pthread_mutex.unlock(); + if( freestack ) + pthread_free( stackmem ); + PTHREAD_RETURN(ENOMEM); + } + } + + nthread = (pthread_info *)stackbase; + + stackbase += sizeof(pthread_info); + stacksize -= sizeof(pthread_info); + + thread_table[thread_next] = nthread; + + // Set new next index + thread_info_next = thread_next; + + // step the cookie + thread_id_cookie += THREAD_ID_COOKIE_INC; + + // Initialize the table entry + nthread->state = use_attr.detachstate == PTHREAD_CREATE_JOINABLE ? + PTHREAD_STATE_RUNNING : PTHREAD_STATE_DETACHED; + nthread->id = thread_next+thread_id_cookie; + nthread->attr = use_attr; + nthread->retval = 0; + nthread->start_routine = start_routine; + nthread->start_arg = arg; + + nthread->freestack = freestack; + nthread->stackmem = stackmem; + + nthread->cancelstate = PTHREAD_CANCEL_ENABLE; + nthread->canceltype = PTHREAD_CANCEL_DEFERRED; + nthread->cancelbuffer = NULL; + nthread->cancelpending = false; + + nthread->thread_data = NULL; + +#ifdef CYGVAR_KERNEL_THREADS_NAME + // generate a name for this thread + + char *name = nthread->name; + static char *name_template = "pthread.00000000"; + pthread_t id = nthread->id; + + for( int i = 0; name_template[i]; i++ ) name[i] = name_template[i]; + + // dump the id, in hex into the name. + for( int i = 15; i >= 8; i-- ) + { + name[i] = "0123456789ABCDEF"[id&0xF]; + id >>= 4; + } + +#endif + + // Initialize the joiner condition variable + + nthread->joiner = new(nthread->joiner_obj) Cyg_Condition_Variable( pthread_mutex ); + +#ifdef CYGPKG_POSIX_SIGNALS + // Initialize signal specific fields. + if (NULL != self) { + CYG_CHECK_DATA_PTR( self, + "Attempt to inherit signal mask from bogus pthread" ); +#ifdef CYGDBG_USE_ASSERTS + // paranoia check + int i; + for (i=(sizeof(thread_table)/sizeof(*thread_table))-1; i>=0; i--) { + if (thread_table[i] == self) + break; + } + CYG_ASSERT( i>=0, "Current pthread not found in table" ); +#endif + } + cyg_posix_thread_siginit( nthread, self ); +#endif + + // create the underlying eCos thread + + nthread->thread = new(&nthread->thread_obj[0]) + Cyg_Thread ( PTHREAD_ECOS_PRIORITY(use_attr.schedparam.sched_priority), + pthread_entry, + (CYG_ADDRWORD)nthread, + name, + stackbase, + stacksize); + + // Put pointer to pthread_info into eCos thread's per-thread data. + nthread->thread->set_data( CYGNUM_KERNEL_THREADS_DATA_POSIX, (CYG_ADDRWORD)nthread ); + + // Set timeslice enable according to scheduling policy. + if( use_attr.schedpolicy == SCHED_FIFO ) + nthread->thread->timeslice_disable(); + else nthread->thread->timeslice_enable(); + + // set up ASR and data + nthread->thread->set_asr( posix_asr, (CYG_ADDRWORD)nthread, NULL, NULL ); + + // return thread ID + *thread = nthread->id; + + pthread_count++; + + pthread_mutex.unlock(); + + // finally, set the thread going + nthread->thread->resume(); + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Get current thread id. + +externC pthread_t pthread_self ( void ) +{ + PTHREAD_ENTRY(); + + pthread_info *info = pthread_self_info(); + + CYG_CHECK_DATA_PTR(info, "Not a POSIX thread!!!"); + + return info->id; +} + +//----------------------------------------------------------------------------- +// Compare two thread identifiers. + +externC int pthread_equal (pthread_t thread1, pthread_t thread2) +{ + PTHREAD_ENTRY(); + + return thread1 == thread2; +} + +//----------------------------------------------------------------------------- +// Terminate current thread. + +externC void exit(int) CYGBLD_ATTRIB_NORET; + +externC void pthread_exit (void *retval) +{ + PTHREAD_ENTRY(); + + pthread_info *self = pthread_self_info(); + + // Disable cancellation requests for this thread. If cleanup + // handlers exist, they will generally be issuing system calls + // to clean up resources. We want these system calls to run + // without cancelling, and we also want to prevent being + // re-cancelled. + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + // Call cancellation handlers. We eat up the buffers as we go in + // case any of the routines calls pthread_exit() itself. + while( self->cancelbuffer != NULL ) + { + struct pthread_cleanup_buffer *buffer = self->cancelbuffer; + + self->cancelbuffer = buffer->prev; + + buffer->routine(buffer->arg); + } + + if( self->thread_data != NULL ) + { + // Call per-thread key destructors. + // The specification of this is that we must continue to call the + // destructor functions until all the per-thread data values are NULL or + // we have done it PTHREAD_DESTRUCTOR_ITERATIONS times. + + cyg_bool destructors_called; + int destructor_iterations = 0; + + do + { + destructors_called = false; + + for( cyg_ucount32 key = 0; key < PTHREAD_KEYS_MAX; key++ ) + { + // Skip unallocated keys + if( thread_key[key/KEY_MAP_TYPE_SIZE] & 1<<(key%KEY_MAP_TYPE_SIZE) ) + continue; + + // Skip NULL destructors + if( key_destructor[key] == NULL ) continue; + + // Skip NULL data values + if( self->thread_data[key] == NULL ) continue; + + // If it passes all that, call the destructor. + // Note that NULLing the data value here is new + // behaviour in the 2001 POSIX standard. + { + void* value = self->thread_data[key]; + self->thread_data[key] = NULL; + key_destructor[key](value); + } + + // Record that we called a destructor + destructors_called = true; + } + + // Count the iteration + destructor_iterations++; + + } while( destructors_called && + (destructor_iterations <= PTHREAD_DESTRUCTOR_ITERATIONS)); + + } + + pthread_mutex.lock(); + + // Set the retval for any joiner + self->retval = retval; + + // If we are already detached, go to EXITED state, otherwise + // go into JOIN state. + + if ( PTHREAD_STATE_DETACHED == self->state ) { + self->state = PTHREAD_STATE_EXITED; + pthreads_exited++; + } else { + self->state = PTHREAD_STATE_JOIN; + pthreads_tobejoined++; + } + + // Kick any waiting joiners + self->joiner->broadcast(); + + cyg_bool call_exit=false; + + // if this is the last thread (other than threads waiting to be joined) + // then we need to call exit() later + if ( pthreads_exited + pthreads_tobejoined == pthread_count ) + call_exit=true; + + pthread_mutex.unlock(); + + // Finally, call the exit function; this will not return. + if ( call_exit ) + ::exit(0); + else + self->thread->exit(); + + // This loop keeps some compilers happy. pthread_exit() is marked + // with the noreturn attribute, and without this they generate a + // call to abort() here in case Cyg_Thread::exit() returns. + + for(;;) continue; +} + +//----------------------------------------------------------------------------- +// Wait for the thread to terminate. If thread_return is not NULL then +// the retval from the thread's call to pthread_exit() is stored at +// *thread_return. + +externC int pthread_join (pthread_t thread, void **thread_return) +{ + int err = 0; + + PTHREAD_ENTRY(); + + // check for cancellation first. + pthread_testcancel(); + + pthread_mutex.lock(); + + // Dispose of any dead threads + pthread_reap(); + + pthread_info *self = pthread_self_info(); + pthread_info *joinee = pthread_info_id( thread ); + + if( joinee == NULL ) + { + err = ESRCH; + } + + if( !err && joinee == self ) + { + err = EDEADLK; + } + + if ( !err ) { + switch ( joinee->state ) + { + case PTHREAD_STATE_RUNNING: + // The thread is still running, we must wait for it. + while( joinee->state == PTHREAD_STATE_RUNNING ) { + if ( !joinee->joiner->wait() ) + // check if we were woken because we were being cancelled + if ( checkforcancel() ) { + err = EAGAIN; // value unimportant, just some error + break; + } + } + + // check that the thread is still joinable + if( joinee->state == PTHREAD_STATE_JOIN ) + break; + + // The thread has become unjoinable while we waited, so we + // fall through to complain. + + case PTHREAD_STATE_FREE: + case PTHREAD_STATE_DETACHED: + case PTHREAD_STATE_EXITED: + // None of these may be joined. + err = EINVAL; + break; + + case PTHREAD_STATE_JOIN: + break; + } + } + + if ( !err ) { + + // here, we know that joinee is a thread that has exited and is + // ready to be joined. + + // Get the retval + if( thread_return != NULL ) + *thread_return = joinee->retval; + + // set state to exited. + joinee->state = PTHREAD_STATE_EXITED; + pthreads_exited++; + pthreads_tobejoined--; + + // Dispose of any dead threads + pthread_reap(); + } + + pthread_mutex.unlock(); + + // check for cancellation before returning + pthread_testcancel(); + + PTHREAD_RETURN(err); +} + +//----------------------------------------------------------------------------- +// Set the detachstate of the thread to "detached". The thread then does not +// need to be joined and its resources will be freed when it exits. + +externC int pthread_detach (pthread_t thread) +{ + PTHREAD_ENTRY(); + + int ret = 0; + + pthread_mutex.lock(); + + pthread_info *detachee = pthread_info_id( thread ); + + if( detachee == NULL ) + ret = ESRCH; // No such thread + else if( detachee->state == PTHREAD_STATE_DETACHED ) + ret = EINVAL; // Already detached! + else + { + // Set state to detached and kick any joinees to + // make them return. + detachee->state = PTHREAD_STATE_DETACHED; + detachee->joiner->broadcast(); + } + + // Dispose of any dead threads + pthread_reap(); + + pthread_mutex.unlock(); + + PTHREAD_RETURN(ret); +} + + +//----------------------------------------------------------------------------- +// Thread attribute handling. + +//----------------------------------------------------------------------------- +// Initialize attributes object with default attributes: +// detachstate == PTHREAD_CREATE_JOINABLE +// scope == PTHREAD_SCOPE_SYSTEM +// inheritsched == PTHREAD_INHERIT_SCHED +// schedpolicy == SCHED_OTHER +// schedparam == unset +// stackaddr == unset +// stacksize == 0 +// + +externC int pthread_attr_init (pthread_attr_t *attr) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + attr->detachstate = PTHREAD_CREATE_JOINABLE; + attr->scope = PTHREAD_SCOPE_SYSTEM; + attr->inheritsched = PTHREAD_INHERIT_SCHED; + attr->schedpolicy = SCHED_OTHER; + attr->schedparam.sched_priority = 0; + attr->stackaddr_valid = 0; + attr->stackaddr = NULL; + attr->stacksize_valid = 0; + attr->stacksize = 0; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Destroy thread attributes object + +externC int pthread_attr_destroy (pthread_attr_t *attr) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + // Nothing to do here... + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Set the detachstate attribute + +externC int pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( detachstate == PTHREAD_CREATE_JOINABLE || + detachstate == PTHREAD_CREATE_DETACHED ) + { + attr->detachstate = detachstate; + PTHREAD_RETURN(0); + } + + PTHREAD_RETURN(EINVAL); +} + +//----------------------------------------------------------------------------- +// Get the detachstate attribute +externC int pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( detachstate != NULL ) + *detachstate = attr->detachstate; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Set scheduling contention scope + +externC int pthread_attr_setscope (pthread_attr_t *attr, int scope) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( scope == PTHREAD_SCOPE_SYSTEM || + scope == PTHREAD_SCOPE_PROCESS ) + { + if( scope == PTHREAD_SCOPE_PROCESS ) + PTHREAD_RETURN(ENOTSUP); + + attr->scope = scope; + + PTHREAD_RETURN(0); + } + + PTHREAD_RETURN(EINVAL); +} + +//----------------------------------------------------------------------------- +// Get scheduling contention scope + +externC int pthread_attr_getscope (const pthread_attr_t *attr, int *scope) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( scope != NULL ) + *scope = attr->scope; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Set scheduling inheritance attribute + +externC int pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( inherit == PTHREAD_INHERIT_SCHED || + inherit == PTHREAD_EXPLICIT_SCHED ) + { + attr->inheritsched = inherit; + + PTHREAD_RETURN(0); + } + + PTHREAD_RETURN(EINVAL); +} + +//----------------------------------------------------------------------------- +// Get scheduling inheritance attribute + +externC int pthread_attr_getinheritsched (const pthread_attr_t *attr, + int *inherit) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( inherit != NULL ) + *inherit = attr->inheritsched; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Set scheduling policy + +externC int pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( policy == SCHED_OTHER || + policy == SCHED_FIFO || + policy == SCHED_RR ) + { + attr->schedpolicy = policy; + + PTHREAD_RETURN(0); + } + + PTHREAD_RETURN(EINVAL); +} + +//----------------------------------------------------------------------------- +// Get scheduling policy + +externC int pthread_attr_getschedpolicy (const pthread_attr_t *attr, + int *policy) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( policy != NULL ) + *policy = attr->schedpolicy; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Set scheduling parameters +externC int pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + PTHREAD_CHECK(param); + + attr->schedparam = *param; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Get scheduling parameters + +externC int pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( param != NULL ) + *param = attr->schedparam; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Set starting address of stack. Whether this is at the start or end of +// the memory block allocated for the stack depends on whether the stack +// grows up or down. + +externC int pthread_attr_setstackaddr (pthread_attr_t *attr, void *stackaddr) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + attr->stackaddr = stackaddr; + attr->stackaddr_valid = 1; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Get any previously set stack address. + +externC int pthread_attr_getstackaddr (const pthread_attr_t *attr, + void **stackaddr) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + if( stackaddr != NULL ) + { + if( attr->stackaddr_valid ) + { + *stackaddr = attr->stackaddr; + PTHREAD_RETURN(0); + } + // Stack address not set, return EINVAL. + else PTHREAD_RETURN(EINVAL); + } + + PTHREAD_RETURN(0); +} + + +//----------------------------------------------------------------------------- +// Set minimum creation stack size. + +externC int pthread_attr_setstacksize (pthread_attr_t *attr, + size_t stacksize) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + CYG_ASSERT( stacksize >= PTHREAD_STACK_MIN, "Inadequate stack size supplied"); + + // Reject inadequate stack sizes + if( stacksize < PTHREAD_STACK_MIN ) + PTHREAD_RETURN(EINVAL); + + attr->stacksize_valid = 1; + attr->stacksize = stacksize; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Get current minimal stack size. + +externC int pthread_attr_getstacksize (const pthread_attr_t *attr, + size_t *stacksize) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK(attr); + + // Reject attempts to get a stack size when one has not been set. + if( !attr->stacksize_valid ) + PTHREAD_RETURN(EINVAL); + + if( stacksize != NULL ) + *stacksize = attr->stacksize; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Thread scheduling controls + +//----------------------------------------------------------------------------- +// Set scheduling policy and parameters for the thread + +externC int pthread_setschedparam (pthread_t thread_id, + int policy, + const struct sched_param *param) +{ + PTHREAD_ENTRY(); + + if( policy != SCHED_OTHER && + policy != SCHED_FIFO && + policy != SCHED_RR ) + PTHREAD_RETURN(EINVAL); + + PTHREAD_CHECK(param); + + // The parameters seem OK, change the thread... + + pthread_mutex.lock(); + + pthread_info *thread = pthread_info_id( thread_id ); + + if( thread == NULL ) + { + pthread_mutex.unlock(); + PTHREAD_RETURN(ESRCH); + } + + thread->attr.schedpolicy = policy; + thread->attr.schedparam = *param; + + if ( policy == SCHED_FIFO ) + thread->thread->timeslice_disable(); + else thread->thread->timeslice_enable(); + + thread->thread->set_priority( PTHREAD_ECOS_PRIORITY( param->sched_priority )); + + pthread_mutex.unlock(); + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Get scheduling policy and parameters for the thread + +externC int pthread_getschedparam (pthread_t thread_id, + int *policy, + struct sched_param *param) +{ + PTHREAD_ENTRY(); + + pthread_mutex.lock(); + + pthread_info *thread = pthread_info_id( thread_id ); + + if( thread == NULL ) + { + pthread_mutex.unlock(); + PTHREAD_RETURN(ESRCH); + } + + if( policy != NULL ) + *policy = thread->attr.schedpolicy; + + if( param != NULL ) + *param = thread->attr.schedparam; + + pthread_mutex.unlock(); + + PTHREAD_RETURN(0); +} + + +//============================================================================= +// Dynamic package initialization +// Call init_routine just the once per control variable. + +externC int pthread_once (pthread_once_t *once_control, + void (*init_routine) (void)) +{ + PTHREAD_ENTRY(); + + PTHREAD_CHECK( once_control ); + PTHREAD_CHECK( init_routine ); + + pthread_once_t old; + + // Do a test and set on the once_control object. + pthread_mutex.lock(); + + old = *once_control; + *once_control = 1; + + pthread_mutex.unlock(); + + // If the once_control was zero, call the init_routine(). + if( !old ) init_routine(); + + PTHREAD_RETURN(0); +} + + +//============================================================================= +//Thread specific data + +//----------------------------------------------------------------------------- +// Create a key to identify a location in the thread specific data area. +// Each thread has its own distinct thread-specific data area but all are +// addressed by the same keys. The destructor function is called whenever a +// thread exits and the value associated with the key is non-NULL. + +externC int pthread_key_create (pthread_key_t *key, + void (*destructor) (void *)) +{ + PTHREAD_ENTRY(); + + pthread_key_t k = -1; + + pthread_mutex.lock(); + + // Find a key to allocate + for( cyg_ucount32 i = 0; i < (PTHREAD_KEYS_MAX/KEY_MAP_TYPE_SIZE); i++ ) + { + if( thread_key[i] != 0 ) + { + // We have a table slot with space available + + // Get index of ls set bit. + HAL_LSBIT_INDEX( k, thread_key[i] ); + + // clear it + thread_key[i] &= ~(1<thread_data != NULL ) + thread->thread_data[k] = NULL; + } + } + + pthread_mutex.unlock(); + + if( k == -1 ) PTHREAD_RETURN(EAGAIN); + + *key = k; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Delete key. + +externC int pthread_key_delete (pthread_key_t key) +{ + PTHREAD_ENTRY(); + + pthread_mutex.lock(); + + // Set the key bit to 1 to indicate it is free. + thread_key[key/KEY_MAP_TYPE_SIZE] |= 1<<(key%(KEY_MAP_TYPE_SIZE)); + + pthread_mutex.unlock(); + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Store the pointer value in the thread-specific data slot addressed +// by the key. + +externC int pthread_setspecific (pthread_key_t key, const void *pointer) +{ + PTHREAD_ENTRY(); + + if( thread_key[key/KEY_MAP_TYPE_SIZE] & 1<<(key%KEY_MAP_TYPE_SIZE) ) + PTHREAD_RETURN(EINVAL); + + pthread_info *self = pthread_self_info(); + + if( self->thread_data == NULL ) + { + // Allocate the per-thread data table + self->thread_data = + (void **)self->thread->increment_stack_limit( + PTHREAD_KEYS_MAX * sizeof(void *) ); + + // Clear out all entries + for( int i = 0; i < PTHREAD_KEYS_MAX; i++ ) + self->thread_data[i] = NULL; + } + + self->thread_data[key] = (void *)pointer; + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Retrieve the pointer value in the thread-specific data slot addressed +// by the key. + +externC void *pthread_getspecific (pthread_key_t key) +{ + void *val; + PTHREAD_ENTRY(); + + if( thread_key[key/KEY_MAP_TYPE_SIZE] & 1<<(key%KEY_MAP_TYPE_SIZE) ) + PTHREAD_RETURN(NULL); + + pthread_info *self = pthread_self_info(); + + if( self->thread_data == NULL ) + val = NULL; + else val = self->thread_data[key]; + + PTHREAD_RETURN(val); +} + +//============================================================================= +// Thread Cancellation Functions + +//----------------------------------------------------------------------------- +// Set cancel state of current thread to ENABLE or DISABLE. +// Returns old state in *oldstate. + +externC int pthread_setcancelstate (int state, int *oldstate) +{ + PTHREAD_ENTRY(); + + if( state != PTHREAD_CANCEL_ENABLE && + state != PTHREAD_CANCEL_DISABLE ) + PTHREAD_RETURN(EINVAL); + + pthread_mutex.lock(); + + pthread_info *self = pthread_self_info(); + + if( oldstate != NULL ) *oldstate = self->cancelstate; + + self->cancelstate = state; + + pthread_mutex.unlock(); + + // Note: This function may have made it possible for a pending + // cancellation to now be delivered. However the standard does not + // list this function as a cancellation point, so for now we do + // nothing. In future we might call pthread_testcancel() here. + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Set cancel type of current thread to ASYNCHRONOUS or DEFERRED. +// Returns old type in *oldtype. + +externC int pthread_setcanceltype (int type, int *oldtype) +{ + PTHREAD_ENTRY(); + + if( type != PTHREAD_CANCEL_ASYNCHRONOUS && + type != PTHREAD_CANCEL_DEFERRED ) + PTHREAD_RETURN(EINVAL); + + pthread_mutex.lock(); + + pthread_info *self = pthread_self_info(); + + if( oldtype != NULL ) *oldtype = self->canceltype; + + self->canceltype = type; + + pthread_mutex.unlock(); + + // Note: This function may have made it possible for a pending + // cancellation to now be delivered. However the standard does not + // list this function as a cancellation point, so for now we do + // nothing. In future we might call pthread_testcancel() here. + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Cancel the thread. + +externC int pthread_cancel (pthread_t thread) +{ + PTHREAD_ENTRY(); + + pthread_mutex.lock(); + + pthread_info *th = pthread_info_id(thread); + + if( th == NULL ) + { + pthread_mutex.unlock(); + PTHREAD_RETURN(ESRCH); + } + + th->cancelpending = true; + + if ( th->cancelstate == PTHREAD_CANCEL_ENABLE ) + { + if ( th->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS ) + { + // If the thread has cancellation enabled, and it is in + // asynchronous mode, set the eCos thread's ASR pending to + // deal with it when the thread wakes up. We also release the + // thread out of any current wait to make it wake up. + + th->thread->set_asr_pending(); + th->thread->release(); + } + else if ( th->canceltype == PTHREAD_CANCEL_DEFERRED ) + { + // If the thread has cancellation enabled, and it is in + // deferred mode, wake the thread up so that cancellation + // points can test for cancellation. + th->thread->release(); + } + else + CYG_FAIL("Unknown cancellation type"); + } + + // Otherwise the thread has cancellation disabled, in which case + // it is up to the thread to enable cancellation + + pthread_mutex.unlock(); + + + PTHREAD_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Test for a pending cancellation for the current thread and terminate +// the thread if there is one. + +externC void pthread_testcancel (void) +{ + PTHREAD_ENTRY_VOID(); + + if( checkforcancel() ) + { + // If we have cancellation enabled, and there is a cancellation + // pending, then go ahead and do the deed. + + // Exit now with special retval. pthread_exit() calls the + // cancellation handlers implicitly. + pthread_exit(PTHREAD_CANCELED); + } + + PTHREAD_RETURN_VOID; +} + +//----------------------------------------------------------------------------- +// These two functions actually implement the cleanup push and pop functionality. + +externC void pthread_cleanup_push_inner (struct pthread_cleanup_buffer *buffer, + void (*routine) (void *), + void *arg) +{ + PTHREAD_ENTRY(); + + pthread_info *self = pthread_self_info(); + + buffer->routine = routine; + buffer->arg = arg; + + buffer->prev = self->cancelbuffer; + + self->cancelbuffer = buffer; + + return; +} + +externC void pthread_cleanup_pop_inner (struct pthread_cleanup_buffer *buffer, + int execute) +{ + PTHREAD_ENTRY(); + + pthread_info *self = pthread_self_info(); + + CYG_ASSERT( self->cancelbuffer == buffer, "Stacking error in cleanup buffers"); + + if( self->cancelbuffer == buffer ) + { + // Remove the buffer from the stack + self->cancelbuffer = buffer->prev; + } + else + { + // If the top of the stack is not the buffer we expect, do not + // execute it. + execute = 0; + } + + if( execute ) buffer->routine(buffer->arg); + + return; +} + + +// ------------------------------------------------------------------------- +// eCos-specific function to measure stack usage of the supplied thread + +#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT +externC size_t pthread_measure_stack_usage (pthread_t thread) +{ + pthread_info *th = pthread_info_id(thread); + + if ( NULL == th ) + return (size_t)-1; + + return (size_t)th->thread->measure_stack_usage(); +} +#endif + +// ------------------------------------------------------------------------- +// EOF pthread.cxx diff --git a/packages/compat/posix/v2_0/src/sched.cxx b/packages/compat/posix/v2_0/src/sched.cxx new file mode 100644 index 00000000..6ca47a36 --- /dev/null +++ b/packages/compat/posix/v2_0/src/sched.cxx @@ -0,0 +1,242 @@ +//========================================================================== +// +// sched.cxx +// +// POSIX scheduler API implementation +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-03-27 +// Purpose: POSIX scheduler API implementation +// Description: This file contains the implementation of the POSIX scheduler +// functions. +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include + +#include // base kernel types +#include // tracing macros +#include // assertion macros + +#include "pprivate.h" // POSIX private header + +#include // scheduler definitions +#include // thread definitions + +#include // scheduler inlines +#include // thread inlines + +//========================================================================== +// Process scheduling functions. + +//-------------------------------------------------------------------------- +// Set scheduling parameters for given process. + +int sched_setparam (pid_t pid, const struct sched_param *param) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + + if( pid != 0 ) + { + errno = ESRCH; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + errno = ENOSYS; + CYG_REPORT_RETVAL( -1 ); + return -1; +} + +//-------------------------------------------------------------------------- +// Get scheduling parameters for given process. + +int sched_getparam (pid_t pid, struct sched_param *param) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + + if( pid != 0 ) + { + errno = ESRCH; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + errno = ENOSYS; + CYG_REPORT_RETVAL( -1 ); + return -1; +} + +//-------------------------------------------------------------------------- +// Set scheduling policy and/or parameters for given process. +int sched_setscheduler (pid_t pid, + int policy, + const struct sched_param *param) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + + if( pid != 0 ) + { + errno = ESRCH; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + errno = ENOSYS; + CYG_REPORT_RETVAL( -1 ); + return -1; +} + + +//-------------------------------------------------------------------------- +// Get scheduling policy for given process. + +int sched_getscheduler (pid_t pid) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + + if( pid != 0 ) + { + errno = ESRCH; + CYG_REPORT_RETVAL( 0 ); + return -1; + } + + errno = ENOSYS; + CYG_REPORT_RETVAL( -1 ); + return -1; +} + +//-------------------------------------------------------------------------- +// Force current thread to relinquish the processor. + +int sched_yield (void) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + + Cyg_Thread::yield(); + + CYG_REPORT_RETVAL( 0 ); + return 0; +} + + +//========================================================================== +// Scheduler parameter limits. + +//-------------------------------------------------------------------------- +// Get maximum priority value for a policy. + +int sched_get_priority_max (int policy) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + + if( policy != SCHED_FIFO && + policy != SCHED_RR && + policy != SCHED_OTHER ) + { + errno = EINVAL; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + int pri = PTHREAD_POSIX_PRIORITY( CYG_THREAD_MAX_PRIORITY ); + + CYG_REPORT_RETVAL( pri ); + return pri; +} + +//-------------------------------------------------------------------------- +// Get minimum priority value for a policy. + +int sched_get_priority_min (int policy) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + + if( policy != SCHED_FIFO && + policy != SCHED_RR && + policy != SCHED_OTHER ) + { + errno = EINVAL; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + // idle thread priority isn't valid for general use, so subtract 1 + int pri = PTHREAD_POSIX_PRIORITY( CYG_THREAD_MIN_PRIORITY-1 ); + + CYG_REPORT_RETVAL( pri ); + return pri; +} + +//-------------------------------------------------------------------------- +// Get the SCHED_RR interval for the given process. + +int sched_rr_get_interval (pid_t pid, struct timespec *t) +{ + CYG_REPORT_FUNCTYPE( "returning %d" ); + +#ifdef CYGPKG_POSIX_CLOCKS + if( pid != 0 ) + { + errno = ESRCH; + CYG_REPORT_RETVAL( -1 ); + return -1; + } + + cyg_ticks_to_timespec( CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS, t ); + + CYG_REPORT_RETVAL( 0 ); + return 0; +#else + errno = ENOSYS; + CYG_REPORT_RETVAL( -1 ); + return -1; +#endif +} + +// ------------------------------------------------------------------------- +// EOF sched.cxx diff --git a/packages/compat/posix/v2_0/src/sem.cxx b/packages/compat/posix/v2_0/src/sem.cxx new file mode 100644 index 00000000..298dc668 --- /dev/null +++ b/packages/compat/posix/v2_0/src/sem.cxx @@ -0,0 +1,244 @@ +//========================================================================== +// +// sem.cxx +// +// POSIX semaphore implementation +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-03-27 +// Purpose: POSIX semaphore implementation +// Description: This file contains the implementation of the POSIX semaphore +// functions. +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include + +#include // base kernel types +#include // tracing macros +#include // assertion macros + +#include // our header + +#include "pprivate.h" // POSIX private header + +#include // Kernel threads + +#include // Cyg_ThreadQueue::empty() + +#include // Kernel semaphores + +// ------------------------------------------------------------------------- +// Internal definitions + +// Handle entry to a pthread package function. +#define SEMA_ENTRY() CYG_REPORT_FUNCTYPE( "returning %d" ); + +// Do a semaphore package defined return. This requires the error code +// to be placed in errno, and if it is non-zero, -1 returned as the +// result of the function. This also gives us a place to put any +// generic tidyup handling needed for things like signal delivery and +// cancellation. +#define SEMA_RETURN(err) \ +CYG_MACRO_START \ + int __retval = 0; \ + if( err != 0 ) __retval = -1, errno = err; \ + CYG_REPORT_RETVAL( __retval ); \ + return __retval; \ +CYG_MACRO_END + +//----------------------------------------------------------------------------- +// new operator to allow us to invoke the Cyg_Thread constructor on the +// user's semaphore object. + +inline void *operator new(size_t size, void *ptr) { return (void *)ptr; }; + +// ------------------------------------------------------------------------- +// Initialize semaphore to value. +// pshared is not supported under eCos. + +externC int sem_init (sem_t *sem, int pshared, unsigned int value) +{ + SEMA_ENTRY(); + + if( value > SEM_VALUE_MAX ) + SEMA_RETURN(EINVAL); + + Cyg_Counting_Semaphore *sema; + + sema = new((void *)sem) Cyg_Counting_Semaphore(value); + + sema=sema; + + SEMA_RETURN(0); +} + +// ------------------------------------------------------------------------- +// Destroy the semaphore. + +externC int sem_destroy (sem_t *sem) +{ + SEMA_ENTRY(); + + Cyg_Counting_Semaphore *sema = (Cyg_Counting_Semaphore *)sem; + + // Check that the semaphore has no waiters + if( sema->waiting() ) + SEMA_RETURN(EBUSY); + + // Call the destructor + sema->~Cyg_Counting_Semaphore(); + + SEMA_RETURN(0); +} + +// ------------------------------------------------------------------------- +// Decrement value if >0 or wait for a post. + +externC int sem_wait (sem_t *sem) +{ + int retval = 0; + + SEMA_ENTRY(); + +#ifdef CYGPKG_POSIX_PTHREAD + // check for cancellation first. + pthread_testcancel(); +#endif + + Cyg_Counting_Semaphore *sema = (Cyg_Counting_Semaphore *)sem; + + if( !sema->wait() ) retval = EINTR; + +#ifdef CYGPKG_POSIX_PTHREAD + // check if we were woken because we were being cancelled + pthread_testcancel(); +#endif + + SEMA_RETURN(retval); +} + +// ------------------------------------------------------------------------- +// Decrement value if >0, return -1 if not. + +externC int sem_trywait (sem_t *sem) +{ + int retval = 0; + + SEMA_ENTRY(); + + Cyg_Counting_Semaphore *sema = (Cyg_Counting_Semaphore *)sem; + + if( !sema->trywait() ) retval = EAGAIN; + + SEMA_RETURN(retval); +} + +// ------------------------------------------------------------------------- +// Increment value and wake a waiter if one is present. + +externC int sem_post (sem_t *sem) +{ + SEMA_ENTRY(); + + Cyg_Counting_Semaphore *sema = (Cyg_Counting_Semaphore *)sem; + + sema->post(); + + SEMA_RETURN(0); +} + + +// ------------------------------------------------------------------------- +// Get current value + +externC int sem_getvalue (sem_t *sem, int *sval) +{ + SEMA_ENTRY(); + + Cyg_Counting_Semaphore *sema = (Cyg_Counting_Semaphore *)sem; + + *sval = sema->peek(); + + CYG_REPORT_RETVAL( 0 ); + return 0; +} + +// ------------------------------------------------------------------------- +// Open an existing named semaphore, or create it. + +externC sem_t *sem_open (const char *name, int oflag, ...) +{ + SEMA_ENTRY(); + + errno = ENOSYS; + + CYG_REPORT_RETVAL( SEM_FAILED ); + return SEM_FAILED; +} + +// ------------------------------------------------------------------------- +// Close descriptor for semaphore. + +externC int sem_close (sem_t *sem) +{ + SEMA_ENTRY(); + + SEMA_RETURN(ENOSYS); +} + +// ------------------------------------------------------------------------- +// Remove named semaphore + +externC int sem_unlink (const char *name) +{ + SEMA_ENTRY(); + + SEMA_RETURN(ENOSYS); +} + +// ------------------------------------------------------------------------- +// EOF sem.cxx diff --git a/packages/compat/posix/v2_0/src/signal.cxx b/packages/compat/posix/v2_0/src/signal.cxx new file mode 100644 index 00000000..80bc9c39 --- /dev/null +++ b/packages/compat/posix/v2_0/src/signal.cxx @@ -0,0 +1,1236 @@ +//========================================================================== +// +// signal.cxx +// +// POSIX signal functions implementation +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2002 Nick Garnett +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-03-27 +// Purpose: POSIX signal functions implementation +// Description: This file contains the implementation of the POSIX signal +// functions. +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +#ifdef CYGPKG_POSIX_SIGNALS + +#include +#include +#include + +#include // base kernel types +#include // tracing macros +#include // assertion macros + +#include "pprivate.h" // POSIX private header + +#include // our header +#include +#include // _exit + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +// Internal definitions + +// Handle entry to a signal package function. +#define SIGNAL_ENTRY() CYG_REPORT_FUNCTYPE( "returning %d" ); + +// Do a signal package defined return. This requires the error code +// to be placed in errno, and if it is non-zero, -1 returned as the +// result of the function. This also gives us a place to put any +// generic tidyup handling needed for things like signal delivery and +// cancellation. +#define SIGNAL_RETURN(err) \ +CYG_MACRO_START \ + int __retval = 0; \ + if( err != 0 ) __retval = -1, errno = err; \ + CYG_REPORT_RETVAL( __retval ); \ + return __retval; \ +CYG_MACRO_END + +// Similarly for functions that have valid non-zero returns +#define SIGNAL_RETURN_VALUE(val) \ +CYG_MACRO_START \ + CYG_REPORT_RETVAL( val ); \ + return val; \ +CYG_MACRO_END + +// Range check on a signal value. +#define SIGNAL_VALID(_sig_) (((_sig_) > 0) && ((_sig_) < ((int)sizeof(sigset_t)*8))) + +//========================================================================== +// Signal management structures + +typedef struct signal_info +{ + struct signal_info *next; // link in list of pending signals + siginfo_t si; // siginfo to pass to handler +} signal_info; + +typedef struct +{ + struct sigaction sa; // Sigaction defining what to do + signal_info *pending; // List of pending signals - this is + // a circular list with pending pointing + // to the tail element (or NULL if empty). +} signal_state; + +//========================================================================== +// Signal management variables + +// Lock used to protect signal management structures +Cyg_Mutex signal_mutex CYGBLD_POSIX_INIT; + +// Condition variable for all threads in sigsuspend() and sigwait() +// to wait on. +Cyg_Condition_Variable CYGBLD_POSIX_INIT signal_sigwait( signal_mutex ) ; + +// Global pending signal set +sigset_t sig_pending; + +// Array controlling signal states +static signal_state sigstate[sizeof(sigset_t)*8]; + +// Array of available signal_info objects for queueing signals +static signal_info siginfo[SIGQUEUE_MAX]; + +// List of free signal_info objects +static signal_info *siginfo_next = NULL; + +//========================================================================== +// Variables used to support alarm() + +// Forward def of action function +static void sigalrm_action( Cyg_Alarm *alarm, CYG_ADDRWORD data ); + +// Kernel alarm object +static Cyg_Alarm CYGBLD_POSIX_INIT sigalrm_alarm( Cyg_Clock::real_time_clock, sigalrm_action, 0 ) ; + +// Set true when alarm is armed +volatile cyg_bool sigalrm_armed = false; + +// Set true when alarm has fired and is waiting to be delivered +volatile cyg_bool sigalrm_pending = false; + +//========================================================================== +// Implementation functions. +// These are where the real work of the signal mechanism gets done. + +externC void cyg_posix_signal_start() +{ + // Chain all free signal_info objects together + for( int i = 0; i < SIGQUEUE_MAX; i++ ) + { + siginfo[i].next = siginfo_next; + siginfo_next = &siginfo[i]; + } + + // initialize all signal actions to SIG_DFL + for ( unsigned int i=0; i<(sizeof(sigstate)/sizeof(signal_state)); i++ ) + { + sigstate[i].sa.sa_handler = SIG_DFL; + } + + // Clear the pending signal set + sigemptyset( &sig_pending ); +} + +// ------------------------------------------------------------------------- +// Generate a signal + +cyg_bool cyg_sigqueue( const struct sigevent *sev, int code, + pthread_info *thread ) +{ + if( sev->sigev_notify == SIGEV_NONE ) + { + // Do nothing + return true; + } + + if( sev->sigev_notify == SIGEV_THREAD ) + { + // create a thread to run the notification + // function. + // FIXME: implement SIGEV_THREAD + return true; + } + + // Otherwise we must have a SIGEV_SIGNAL notification + + // Find out whether the current thread already has the mutex + // locked. This is a distinct possibility if this function is + // called from the ASR while exiting the signal_sigwait condvar in + // pause() and sigtimedwait(). + + pthread_info *self = pthread_self_info(); + cyg_bool locked = (self != NULL) && (signal_mutex.get_owner() == self->thread); + + // Lock the mutex only if we do not already own it + if( !locked ) signal_mutex.lock(); + + int signo = sev->sigev_signo; + signal_state *ss = &sigstate[signo]; + + if( ss->sa.sa_flags & SA_SIGINFO ) + { + // We have a queuable signal, allocate a signal_info + // object and add it to the queue. + + if( siginfo_next == NULL ) + { + if( !locked ) signal_mutex.unlock(); + return false; + } + + signal_info *si = siginfo_next; + siginfo_next = si->next; + + si->si.si_signo = signo; + si->si.si_code = code; + si->si.si_value = sev->sigev_value; + + if( ss->pending == NULL ) + { + si->next = si; + } + else + { + si->next = ss->pending->next; + ss->pending->next = si; + } + + ss->pending = si; + } + // else A non-queuable signal, just set it pending + + if( thread != NULL ) + { + sigaddset( &thread->sigpending, signo ); + // just wake the thread up now if it's blocked somewhere + if ((thread->sigpending & ~thread->sigmask) != 0) + { + thread->thread->set_asr_pending(); + thread->thread->release(); + } + } + else + { + sigaddset( &sig_pending, signo ); + // Wake up any threads in sigsuspend() and sigwait(). + if (!signal_sigwait.get_queue()->empty()) + { + signal_sigwait.broadcast(); + } + else + { + cyg_posix_pthread_release_thread( &sig_pending ); + } + } + + if( !locked ) signal_mutex.unlock(); + + return true; +} + +// ------------------------------------------------------------------------- +// Deliver any pending unblocked signals to the current thread +// Returns true if a signal handler was called. + +cyg_bool cyg_deliver_signals() +{ + cyg_bool res = false; + + pthread_info *self = pthread_self_info(); + + // If there is no pthread_info pointer for this thread then + // it is not a POSIX thread and cannot have signals delivered + // to it. + + if( self == NULL ) return false; + + // If there are no pending signals our work is done + if( sig_pending == 0 && self->sigpending == 0 ) + return false; + + // If there are no unmasked pending signals our + // work is also done + if( ((sig_pending | self->sigpending) & ~self->sigmask) == 0 ) + return false; + + // As with cyg_sigqueue(), this function can get called from an + // ASR where the signal_mutex is already locked. Check here to + // avoid relocking... + + cyg_bool locked = signal_mutex.get_owner() == self->thread; + + if( !locked ) signal_mutex.lock(); + + sigset_t todo; + + // Since a signal handler may raise another signal, or unmask an existing + // signal, we loop here while there are no more unblocked signals pending. + while( (todo = ((sig_pending | self->sigpending) & ~self->sigmask)) != 0 ) + { + // Here todo is a mask of the signals available for delivery + + int signo = 0; + + // This prioritizes low numbered signals + HAL_LSBIT_INDEX( signo, todo ); + + signal_state *ss = &sigstate[signo]; + sigset_t sigbit = 1L<sa.sa_handler != SIG_IGN ) + { + sigset_t oldmask = self->sigmask; + siginfo_t lsi; + + if(ss->pending != NULL) + { + // There is a queued signal. Dequeue it and copy the + // siginfo object to a local copy. + + signal_info *si = ss->pending->next; + + // Make a local copy of the siginfo object + lsi = si->si; + + // Remove the head signal_info object from the + // circular list. + if( ss->pending == si ) + ss->pending = NULL; + else + ss->pending->next = si->next; + + // Return it to the free list + si->next = siginfo_next; + siginfo_next = si; + } + else + { + // There are no signals queued. Set up the local siginfo_t + // object with default values. + + lsi.si_signo = signo; + lsi.si_code = SI_USER; + lsi.si_value.sival_int = 0; + } + + // Clear the bit from the pending masks. If the pending + // queue is not empty, leave the bits set, otherwise clear + // them. Do this now so that if the signal handler longjumps + // out, the signal subsystem is clean. + + if( ss->pending == NULL ) + { + // Clear the bit in both masks regardless of which + // one it actually came from. This is cheaper than + // trying to find out. + sig_pending &= ~sigbit; + self->sigpending &= ~sigbit; + } + + // Add the mask set and the signal itself to the + // mask while we call the signal handler + self->sigmask = oldmask | ss->sa.sa_mask | sigbit; + + // Unlock now so that a longjmp out of the handler + // does the right thing. We do this even if we did not + // lock the mutex since it will only recently have been + // relocked and thus all data is still consistent. + + signal_mutex.unlock(); + + if( ss->sa.sa_flags & SA_SIGINFO ) + { + // A sigaction delivery + CYG_CHECK_FUNC_PTR( ss->sa.sa_sigaction, + "Bad sa_sigaction signal handler" ); + ss->sa.sa_sigaction( signo, &lsi, NULL ); + } + else if ( ss->sa.sa_handler == SIG_DFL ) + { + CYG_TRACE2( true, + "Unhandled POSIX signal: sig=%d, mask=%08x", + signo, oldmask ); + + // FIXME: should do something better here +#if CYGINT_ISO_EXIT + _exit( -signo ); +#endif + CYG_FAIL("Unhandled POSIX signal"); + } + else + { + // This is a standard signal delivery. + CYG_CHECK_FUNC_PTR( ss->sa.sa_handler, + "Bad sa_handler signal handler" ); + + ss->sa.sa_handler( signo ); + } + + // Relock the mutex + signal_mutex.lock(); + + // Restore original signal mask + self->sigmask = oldmask; + + // return that we have handled a signal + res = true; + } + } + + if( !locked ) signal_mutex.unlock(); + + return res; +} + +// ------------------------------------------------------------------------- +// Utility routine to signal any threads waiting in sigwait*(). + +void cyg_posix_signal_sigwait() +{ + signal_sigwait.broadcast(); +} + +// ------------------------------------------------------------------------- +// Action routine called from kernel alarm to deliver the SIGALRM signal. +// We cannot call any signal delivery functions directly here, so we simply +// set a flag and schedule an ASR to be called. + +static void sigalrm_action( Cyg_Alarm *alarm, CYG_ADDRWORD data ) +{ + sigset_t mask; + sigalrm_armed = false; + sigalrm_pending = true; + sigemptyset( &mask ); + sigaddset( &mask, SIGALRM ); + // Wake up any threads in sigsuspend() and sigwait() in case they + // are waiting for an alarm, and would have SIGALRM masked + signal_sigwait.broadcast(); + + cyg_posix_pthread_release_thread( &mask ); +} + +// ------------------------------------------------------------------------- +// Check for SIGALRMs. This is called from the ASR and sigtimedwait() +// as alarms need to be handled as a special case. + +static __inline__ void check_sigalarm(void) +{ + // If there is a pending SIGALRM, generate it + if( sigalrm_pending ) + { + sigalrm_pending = false; + + struct sigevent sev; + + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGALRM; + sev.sigev_value.sival_int = 0; + + // generate the signal + cyg_sigqueue( &sev, SI_USER ); + } +} + +// ------------------------------------------------------------------------- +// signal ASR function. This is called from the general POSIX ASR to +// deal with any signal related issues. + +externC void cyg_posix_signal_asr(pthread_info *self) +{ + check_sigalarm(); + + // Now call cyg_deliver_signals() to see if we can + // handle any signals now. + + cyg_deliver_signals(); +} + +//========================================================================== +// Per-thread initialization and destruction + +externC void cyg_posix_thread_siginit( pthread_info *thread, + pthread_info *parentthread ) +{ + // Clear out signal masks + sigemptyset( &thread->sigpending ); + // but threads inherit signal masks + if ( NULL == parentthread ) + sigemptyset( &thread->sigmask ); + else + thread->sigmask = parentthread->sigmask; + + cyg_pthread_exception_init( thread ); +} + +externC void cyg_posix_thread_sigdestroy( pthread_info *thread ) +{ + cyg_pthread_exception_destroy( thread ); +} + +//========================================================================== +// Functions to generate signals + +// ------------------------------------------------------------------------- +// Deliver sig to a process. +// eCos only supports the value 0 for pid. + +externC int kill (pid_t pid, int sig) +{ + SIGNAL_ENTRY(); + + if( !SIGNAL_VALID(sig) ) + SIGNAL_RETURN(EINVAL); + + if( pid != 0 ) + SIGNAL_RETURN(ESRCH); + + struct sigevent sev; + + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = sig; + sev.sigev_value.sival_int = 0; + + cyg_sigqueue( &sev, SI_USER ); + + cyg_deliver_signals(); + + SIGNAL_RETURN(0); +} + +// ------------------------------------------------------------------------- + +externC int pthread_kill (pthread_t threadid, int sig) +{ + SIGNAL_ENTRY(); + + if( !SIGNAL_VALID(sig) ) + SIGNAL_RETURN(EINVAL); + + struct sigevent sev; + + pthread_info *thread = pthread_info_id(threadid); + + if( thread == NULL ) + SIGNAL_RETURN(ESRCH); + + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = sig; + sev.sigev_value.sival_int = 0; + + cyg_sigqueue( &sev, SI_USER, thread ); + + cyg_deliver_signals(); + + SIGNAL_RETURN(0); +} + +//========================================================================== +// Functions to catch signals + +// ------------------------------------------------------------------------- +// Install signal handler for sig. + +externC int sigaction (int sig, const struct sigaction *act, + struct sigaction *oact) +{ + SIGNAL_ENTRY(); + + if( !SIGNAL_VALID(sig) ) + SIGNAL_RETURN(EINVAL); + + signal_state *ss = &sigstate[sig]; + + signal_mutex.lock(); + + if( oact != NULL ) + *oact = ss->sa; + + ss->sa = *act; + + if( ss->sa.sa_handler == SIG_IGN ) + { + // Setting the handler to SIG_IGN causes any pending + // signals to be discarded and any queued values to also + // be removed. + + pthread_info *self = pthread_self_info(); + sigset_t sigbit = 1<sigpending) & sigbit ) + { + // This signal is pending, clear it + + sig_pending &= ~sigbit; + self->sigpending &= ~sigbit; + + // Clean out any queued signal_info objects + while( ss->pending != NULL ) + { + signal_info *si = ss->pending->next; + + // Remove the head signal_info object from the + // circular list. + if( ss->pending == si ) + ss->pending = NULL; + else + ss->pending->next = si->next; + + // Return it to the free list + si->next = siginfo_next; + siginfo_next = si; + } + } + } + + cyg_deliver_signals(); + + signal_mutex.unlock(); + + SIGNAL_RETURN(0); +} + + +// ------------------------------------------------------------------------- +// Queue signal to process with value. + +externC int sigqueue (pid_t pid, int sig, const union sigval value) +{ + SIGNAL_ENTRY(); + + if( !SIGNAL_VALID(sig) ) + SIGNAL_RETURN(EINVAL); + + struct sigevent sev; + + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = sig; + sev.sigev_value = value; + + cyg_sigqueue( &sev, SI_QUEUE ); + + cyg_deliver_signals(); + + SIGNAL_RETURN(0); +} + +//========================================================================== +// Functions to deal with current blocked and pending masks + +// ------------------------------------------------------------------------- +// Set process blocked signal mask +// Map this onto pthread_sigmask(). + +externC int sigprocmask (int how, const sigset_t *set, sigset_t *oset) +{ + return pthread_sigmask( how, set, oset); +} + + +// ------------------------------------------------------------------------- +// Set calling thread's blocked signal mask + +externC int pthread_sigmask (int how, const sigset_t *set, sigset_t *oset) +{ + int err = 0; + + SIGNAL_ENTRY(); + + pthread_info *self = pthread_self_info(); + // Save old set + if( oset != NULL ) + *oset = self->sigmask; + + if( set != NULL ) + { + switch( how ) + { + case SIG_BLOCK: + self->sigmask |= *set; + break; + + case SIG_UNBLOCK: + self->sigmask &= ~*set; + break; + + case SIG_SETMASK: + self->sigmask = *set; + break; + + default: + err = EINVAL; + break; + } + } + + // Deliver any newly unblocked signals + cyg_deliver_signals(); + + SIGNAL_RETURN(err); +} + +// ------------------------------------------------------------------------- +// Exported routine to set calling thread's blocked signal mask +// +// Optionally set and return the current thread's signal mask. This is +// exported to other packages so that they can manipulate the signal +// mask without necessarily having them delivered (as calling +// pthread_sigmask() would). Signals can be delivered by calling +// cyg_posix_deliver_signals(). + +externC void cyg_pthread_sigmask_set (const sigset_t *set, sigset_t *oset) +{ + pthread_info *self = pthread_self_info(); + + if( self != NULL ) + { + if( oset != NULL ) + *oset = self->sigmask; + + if( set != NULL ) + self->sigmask = *set; + } +} + +// ------------------------------------------------------------------------- +// Exported routine to test for any pending signals. +// +// This routine tests for any pending undelivered, unmasked +// signals. If there are any it returns true. This is exported to +// other packages, such as FILEIO, so that they can detect whether to +// abort a current API call with an EINTR result. + +externC cyg_bool cyg_posix_sigpending(void) +{ + pthread_info *self = pthread_self_info(); + + if( self == NULL ) + return false; + + return ( ((sig_pending | self->sigpending) & ~self->sigmask) != 0 ); +} + +// ------------------------------------------------------------------------- +// Exported routine to deliver selected signals +// +// This routine optionally sets the given mask and then tries to +// deliver any pending signals that have been unmasked. This is +// exported to other packages so that they can cause signals to be +// delivered at controlled points during execution. + +externC void cyg_posix_deliver_signals( const sigset_t *mask ) +{ + sigset_t oldmask; + pthread_info *self = pthread_self_info(); + + if( self != NULL ) + { + if( mask != NULL ) + { + oldmask = self->sigmask; + self->sigmask = *mask; + } + else + oldmask = 0; // silence warning + + cyg_deliver_signals(); + + if( mask != NULL ) + self->sigmask = oldmask; + } +} + +// ------------------------------------------------------------------------- +// Get set of pending signals for this process + +externC int sigpending (sigset_t *set) +{ + SIGNAL_ENTRY(); + + if( set == NULL ) + SIGNAL_RETURN(EINVAL); + + pthread_info *self = pthread_self_info(); + + *set = self->sigpending | sig_pending; + + SIGNAL_RETURN(0); +} + + +//========================================================================== +// Wait for or accept signals + +// ------------------------------------------------------------------------- +// Block signals in set and wait for a signal + +externC int sigsuspend (const sigset_t *set) +{ + SIGNAL_ENTRY(); + + pthread_info *self = pthread_self_info(); + + signal_mutex.lock(); + + // Save the old mask and set the current mask to + // the one supplied. + sigset_t old = self->sigmask; + self->sigmask = *set; + + // Loop until a signal gets delivered + while( !cyg_deliver_signals() ) + signal_sigwait.wait(); + + self->sigmask = old; + + signal_mutex.unlock(); + + SIGNAL_RETURN(EINTR); +} + + +// ------------------------------------------------------------------------- +// Wait for a signal in set to arrive +// Implement this as a variant on sigtimedwait(). + +externC int sigwait (const sigset_t *set, int *sig) +{ + SIGNAL_ENTRY(); + + siginfo_t info; + + int ret = sigtimedwait( set, &info, NULL ); + + if( ret == -1 ) + SIGNAL_RETURN(errno); + + *sig = ret; + + SIGNAL_RETURN(0); +} + +// ------------------------------------------------------------------------- +// Do the same as sigwait() except return a siginfo_t object too. +// Implement this as a variant on sigtimedwait(). + +externC int sigwaitinfo (const sigset_t *set, siginfo_t *info) +{ + SIGNAL_ENTRY(); + + int ret = sigtimedwait( set, info, NULL ); + + SIGNAL_RETURN_VALUE(ret); +} + +// ------------------------------------------------------------------------- +// Wait either for a signal in the given set to become pending, or +// for the timeout to expire. If timeout is NULL, wait for ever. + +externC int sigtimedwait (const sigset_t *set, siginfo_t *info, + const struct timespec *timeout) +{ + SIGNAL_ENTRY(); + + // check for cancellation first. + pthread_testcancel(); + + int err = 0; + cyg_tick_count ticks; + + if( timeout == NULL ) ticks = 0; + else ticks = cyg_timespec_to_ticks( timeout ) + + Cyg_Clock::real_time_clock->current_value(); + + pthread_info *self = pthread_self_info(); + + signal_mutex.lock(); + + sigset_t todo; + + // Wait for a signal in the set to become pending + while( (todo = (*set & (sig_pending | self->sigpending))) == 0 ) + { + // If timeout is not NULL, do a timed wait on the + // sigwait condition variable. If it is NULL - wait + // until we are woken. + if( timeout ) + { + if( ticks == 0 || !signal_sigwait.wait(ticks) ) + { + // If the timeout is actually zero, or we have waited and + // timed out, then we must quit with an error. + err = EAGAIN; + break; + } + } + else { + if ( !signal_sigwait.wait() ) { + // check we weren't woken up forcibly (e.g. to be cancelled) + // if so, pretend it's an error + err = EAGAIN; + break; + } + } + + // Special case check for SIGALRM since the fact SIGALRM is masked + // would have prevented it being set pending in the alarm handler. + check_sigalarm(); + + cyg_posix_timer_asr(self); + } + + if( err == 0 ) + { + // There is a signal in the set that is pending: deliver + // it. todo contains a mask of all the signals that could be + // delivered now, but we only want to deliver one of them. + + int signo = 0; + + // Select the lowest numbered signal from the todo mask + HAL_LSBIT_INDEX( signo, todo ); + + signal_state *ss = &sigstate[signo]; + sigset_t sigbit = 1L<sa.sa_flags & SA_SIGINFO) && (ss->pending != NULL) ) + { + // If the SA_SIGINFO bit is set, then there + // will be a signal_info object queued on the + // pending field. + + signal_info *si = ss->pending->next; + *info = si->si; + + // Remove the head signal_info object from the + // circular list. + if( ss->pending == si ) + ss->pending = NULL; + else + ss->pending->next = si->next; + + si->next = siginfo_next; + siginfo_next = si; + + } + else + { + // Not a queued signal, or there is no signal_info object + // on the pending queue: fill in info structure with + // default values. + info->si_signo = signo; + info->si_code = SI_USER; + info->si_value.sival_int = 0; + } + + // Clear the bit from the pending masks. If the pending + // queue is not empty, leave the bits set, otherwise clear + // them. + + if( ss->pending == NULL ) + { + // Clear the bit in both masks regardless of which + // one it actually came from. This is cheaper than + // trying to find out. + sig_pending &= ~sigbit; + self->sigpending &= ~sigbit; + } + + // all done + } + + signal_mutex.unlock(); + + pthread_testcancel(); + + if (err) + SIGNAL_RETURN(err); + else + SIGNAL_RETURN_VALUE( info->si_signo ); +} + +//========================================================================== +// alarm, pause and sleep + +// ------------------------------------------------------------------------- +// Generate SIGALRM after some number of seconds + +externC unsigned int alarm( unsigned int seconds ) +{ + int res = 0; + struct timespec tv; + cyg_tick_count trigger, interval; + + SIGNAL_ENTRY(); + + signal_mutex.lock(); + + if( sigalrm_armed ) + { + sigalrm_alarm.disable(); + + sigalrm_alarm.get_times( &trigger, &interval ); + + // Convert trigger time back to interval + trigger -= Cyg_Clock::real_time_clock->current_value(); + + cyg_ticks_to_timespec( trigger, &tv ); + + res = tv.tv_sec; + + sigalrm_armed = false; + } + + if( seconds != 0 ) + { + // Here we know that the sigalrm_alarm is unarmed, set it up + // to trigger in the required number of seconds. + + tv.tv_sec = seconds; + tv.tv_nsec = 0; + + trigger = cyg_timespec_to_ticks( &tv ); + + // Convert trigger interval to absolute time + trigger += Cyg_Clock::real_time_clock->current_value(); + + sigalrm_alarm.initialize( trigger, 0 ); + + sigalrm_armed = true; + } + + signal_mutex.unlock(); + + CYG_REPORT_RETVAL(res); + + return res; +} + +// ------------------------------------------------------------------------- +// Wait for a signal to be delivered. + +externC int pause( void ) +{ + SIGNAL_ENTRY(); + + signal_mutex.lock(); + + // Check for any pending signals that can be delivered and + // if there are none, wait for a signal to be generated + if( !cyg_deliver_signals() ) + signal_sigwait.wait(); + + // Now check again for some signals to deliver + cyg_deliver_signals(); + + signal_mutex.unlock(); + + SIGNAL_RETURN(EINTR); +} + +//========================================================================== +// Signal sets + +// ------------------------------------------------------------------------- +// Clear all signals from set. + +externC int sigemptyset (sigset_t *set) +{ + SIGNAL_ENTRY(); + + *set = 0; + + SIGNAL_RETURN(0); +} + + +// ------------------------------------------------------------------------- +// Set all signals in set. + +externC int sigfillset (sigset_t *set) +{ + SIGNAL_ENTRY(); + + *set = ~0; + + SIGNAL_RETURN(0); +} + + +// ------------------------------------------------------------------------- +// Add signo to set. + +externC int sigaddset (sigset_t *set, int signo) +{ + SIGNAL_ENTRY(); + + int err = 0; + + if( !SIGNAL_VALID(signo) ) + err = EINVAL; + else *set |= 1< + +#include +#include "pprivate.h" // POSIX private header + +// ------------------------------------------------------------------------- + +// define an object that will automatically initialize the POSIX subsystem + +class cyg_posix_startup_dummy_constructor_class { +public: + cyg_posix_startup_dummy_constructor_class() { + +#ifdef CYGPKG_POSIX_PTHREAD + cyg_posix_pthread_start(); +#endif +#ifdef CYGPKG_POSIX_SIGNALS + cyg_posix_signal_start(); + cyg_posix_exception_start(); +#endif +#ifdef CYGPKG_POSIX_TIMERS + cyg_posix_clock_start(); +#endif + + } +}; + +static cyg_posix_startup_dummy_constructor_class cyg_posix_startup_obj + CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_COMPAT); + +// ------------------------------------------------------------------------- +// EOF startup.cxx diff --git a/packages/compat/posix/v2_0/src/time.cxx b/packages/compat/posix/v2_0/src/time.cxx new file mode 100644 index 00000000..c4f5d701 --- /dev/null +++ b/packages/compat/posix/v2_0/src/time.cxx @@ -0,0 +1,700 @@ +//========================================================================== +// +// time.cxx +// +// POSIX time functions implementation +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-03-27 +// Purpose: POSIX time functions implementation +// Description: This file contains the implementation of the POSIX time +// functions. +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +#ifdef CYGPKG_POSIX_CLOCKS + +#include +#include + +#include // base kernel types +#include // tracing macros +#include // assertion macros + +#include "pprivate.h" // POSIX private header + +#include // our header + +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +// Internal definitions + +// Handle entry to a pthread package function. +#define TIME_ENTRY() CYG_REPORT_FUNCTYPE( "returning %d" ); + +// Do a time package defined return. This requires the error code +// to be placed in errno, and if it is non-zero, -1 returned as the +// result of the function. This also gives us a place to put any +// generic tidyup handling needed for things like signal delivery and +// cancellation. +#define TIME_RETURN(err) \ +CYG_MACRO_START \ + int __retval = 0; \ + if( err != 0 ) __retval = -1, errno = err; \ + CYG_REPORT_RETVAL( __retval ); \ + return __retval; \ +CYG_MACRO_END + +//========================================================================== +// Timer control structures + +#ifdef CYGPKG_POSIX_TIMERS +typedef struct +{ + timer_t id; // id value for checking + Cyg_Alarm *alarm; // eCos alarm object + cyg_bool armed; // is alarm enabled? + cyg_bool pending; // is expiry pending? + int overrun; // Overrun count + struct sigevent sigev; // Sigevent to raise on expiry + + // Space for alarm object + cyg_uint8 alarm_obj[sizeof(Cyg_Alarm)]; + +} posix_timer; + +// Mutex for controlling access to shared data structures +static Cyg_Mutex timer_mutex CYGBLD_POSIX_INIT; + +// Array of timer objects +static posix_timer timer_table[_POSIX_TIMER_MAX]; + +// Index of next timer to allocate from array +static int timer_next = 0; + +// This is used to make timer_t values unique even when reusing +// a table slot. This allows _POSIX_TIMER_MAX to range +// up to 1024. +#define TIMER_ID_COOKIE_INC 0x00000400 +#define TIMER_ID_COOKIE_MASK (TIMER_ID_COOKIE_INC-1) +static timer_t timer_id_cookie = TIMER_ID_COOKIE_INC; + +#endif // ifdef CYGPKG_POSIX_TIMERS + +//----------------------------------------------------------------------------- +// new operator to allow us to invoke the constructor on +// posix_timer.alarm_obj. + +inline void *operator new(size_t size, cyg_uint8 *ptr) { return (void *)ptr; }; + +//========================================================================== +// Time conversion variables +// These are used to interconvert between ticks and POSIX timespecs. + +// Converters from sec and ns to ticks +static struct Cyg_Clock::converter ns_converter, sec_converter; + +// Converters from ticks to sec and ns +static struct Cyg_Clock::converter ns_inverter, sec_inverter; + +// tickns is the number of nanoseconds per tick. +static cyg_tick_count tickns; + +static cyg_bool converters_initialized = false; + +//========================================================================== +// Local functions + +static void init_converters() +{ + if( !converters_initialized ) + { + + // Create the converters we need. + Cyg_Clock::real_time_clock->get_other_to_clock_converter( 1, &ns_converter ); + Cyg_Clock::real_time_clock->get_other_to_clock_converter( 1000000000, &sec_converter ); + Cyg_Clock::real_time_clock->get_clock_to_other_converter( 1, &ns_inverter ); + Cyg_Clock::real_time_clock->get_clock_to_other_converter( 1000000000, &sec_inverter ); + + tickns = Cyg_Clock::convert( 1, &ns_inverter ); + + converters_initialized = true; + } +} + +static cyg_bool valid_timespec( const struct timespec *tp ) +{ + // Fail a NULL pointer + if( tp == NULL ) return false; + + // Fail illegal nanosecond values + if( tp->tv_nsec < 0 || tp->tv_nsec > 1000000000 ) + return false; + + return true; +} + +externC cyg_tick_count cyg_timespec_to_ticks( const struct timespec *tp, + cyg_bool roundup) +{ + init_converters(); + + // Short circuit zero timespecs + if( tp->tv_sec == 0 && tp->tv_nsec == 0 ) + { + return 0; + } + + // Convert the seconds field to ticks. + cyg_tick_count ticks = Cyg_Clock::convert( tp->tv_sec, &sec_converter ); + + if( roundup ) + { + // Convert the nanoseconds. We add (tickns-1) to round the value up + // to the next whole tick. + + ticks += Cyg_Clock::convert( (cyg_tick_count)tp->tv_nsec+tickns-1, &ns_converter ); + } + else + { + // Convert the nanoseconds. This will round down to nearest whole tick. + ticks += Cyg_Clock::convert( (cyg_tick_count)tp->tv_nsec, &ns_converter ); + } + + return ticks; +} + +externC void cyg_ticks_to_timespec( cyg_tick_count ticks, struct timespec *tp ) +{ + init_converters(); + + // short circuit zero ticks values + if( ticks == 0 ) + { + tp->tv_sec = 0; + tp->tv_nsec = 0; + return; + } + + // Convert everything to nanoseconds with a long long. For 64-bits, + // this is safe for 544 years. We'll think about it more closer to + // the time... + + unsigned long long nsecs = Cyg_Clock::convert( ticks, &ns_inverter ); + + tp->tv_sec = (long)(nsecs / 1000000000ll); + tp->tv_nsec = (long)(nsecs % 1000000000ll); + + CYG_POSTCONDITION(valid_timespec(tp), "Failed to make valid timespec!"); +} + +//========================================================================== +// Startup routine. + +externC void cyg_posix_clock_start() +{ + init_converters(); +} + +#ifdef CYGPKG_POSIX_TIMERS +//========================================================================== +// Alarm action routine +// This is called each time an alarm set up by a timer expires. + +static void alarm_action( Cyg_Alarm *alarm, CYG_ADDRWORD data ) +{ + posix_timer *timer = (posix_timer *)data; + + if( timer->pending ) + { + // If the pending flag is already set, count an overrun and + // do not bother to try and deliver the expiry. + + timer->overrun++; + } + else + { + if( timer->sigev.sigev_notify == SIGEV_SIGNAL ) + { + // Set the expiry pending and wake a thread to + // deliver the signal. + + timer->pending = true; + + sigset_t mask; + sigemptyset( &mask ); + sigaddset( &mask, timer->sigev.sigev_signo ); + cyg_posix_signal_sigwait(); + cyg_posix_pthread_release_thread( &mask ); + } + else if( timer->sigev.sigev_notify == SIGEV_THREAD ) + { + // Thread style notification + // FIXME: implement SIGEV_THREAD + } + // else do nothing + } +} + +//========================================================================== +// Timer ASR routine + +externC void cyg_posix_timer_asr( pthread_info *self ) +{ + + // Loop over the timers looking for any that have an + // expiry pending and call cyg_sigqueue() for each. + + for( int i = 0; i < _POSIX_TIMER_MAX; i++ ) + { + posix_timer *timer = &timer_table[i]; + + if( timer->id != 0 && timer->pending ) + { + timer->pending = false; + + // Call into signal subsystem... + cyg_sigqueue( &timer->sigev, SI_TIMER ); + + timer->overrun = 0; + } + } +} + +#endif // ifdef CYGPKG_POSIX_TIMERS + +//========================================================================== +// Clock functions + +//----------------------------------------------------------------------------- +// Set the clocks current time + +externC int clock_settime( clockid_t clock_id, const struct timespec *tp) +{ + TIME_ENTRY(); + + if( clock_id != CLOCK_REALTIME ) + TIME_RETURN(EINVAL); + + if( !valid_timespec( tp ) ) + TIME_RETURN(EINVAL); + + cyg_tick_count ticks = cyg_timespec_to_ticks( tp ); + + Cyg_Clock::real_time_clock->set_value( ticks ); + + TIME_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Get the clocks current time + +externC int clock_gettime( clockid_t clock_id, struct timespec *tp) +{ + TIME_ENTRY(); + + if( clock_id != CLOCK_REALTIME ) + TIME_RETURN(EINVAL); + + if( tp == NULL ) + TIME_RETURN(EINVAL); + + cyg_tick_count ticks = Cyg_Clock::real_time_clock->current_value(); + + cyg_ticks_to_timespec( ticks, tp ); + + TIME_RETURN(0); +} + + +//----------------------------------------------------------------------------- +// Get the clocks resolution + +externC int clock_getres( clockid_t clock_id, struct timespec *tp) +{ + TIME_ENTRY(); + + if( clock_id != CLOCK_REALTIME ) + TIME_RETURN(EINVAL); + + if( tp == NULL ) + TIME_RETURN(EINVAL); + + // Get the resolution of 1 tick + cyg_ticks_to_timespec( 1, tp ); + + TIME_RETURN(0); +} + + +//========================================================================== +// Timer functions + +#ifdef CYGPKG_POSIX_TIMERS + +//----------------------------------------------------------------------------- +// Create a timer based on the given clock. + +externC int timer_create( clockid_t clock_id, + struct sigevent *evp, + timer_t *timer_id) +{ + TIME_ENTRY(); + + if( clock_id != CLOCK_REALTIME ) + TIME_RETURN(EINVAL); + + timer_mutex.lock(); + + posix_timer *timer; + int next = timer_next; + + // Look for an unused slot in the table + while( timer_table[next].id != 0 ) + { + next++; + if( next >= _POSIX_TIMER_MAX ) + next = 0; + + if( next == timer_next ) + { + timer_mutex.unlock(); + TIME_RETURN(EAGAIN); + } + } + + timer = &timer_table[next]; + + timer_next = next; + + // Make sure we never allocate a zero timer id. + while( timer->id == 0 ) + { + timer_id_cookie += TIMER_ID_COOKIE_INC; + timer->id = next+timer_id_cookie; + } + + if( evp == NULL ) + { + // If no evp is supplied, set up the timer + // to use a default set. + timer->sigev.sigev_notify = SIGEV_SIGNAL; + timer->sigev.sigev_signo = SIGALRM; + timer->sigev.sigev_value.sival_int = timer->id; + } + else timer->sigev = *evp; + + timer->alarm = new( timer->alarm_obj ) + Cyg_Alarm( Cyg_Clock::real_time_clock, + alarm_action, + (CYG_ADDRWORD)timer ); + + timer->armed = false; + timer->overrun = 0; + + *timer_id = timer->id; + + timer_mutex.unlock(); + + TIME_RETURN(0); +} + +//----------------------------------------------------------------------------- +// Delete the timer + +externC int timer_delete( timer_t timerid ) +{ + int err = EINVAL; + TIME_ENTRY(); + + posix_timer *timer = &timer_table[timerid & TIMER_ID_COOKIE_MASK]; + + timer_mutex.lock(); + + if( timer->id == timerid ) + { + // This is a valid timer, disable the kernel + // alarm and delete it. + + // disable alarm + timer->alarm->disable(); + + // destroy it + timer->alarm->~Cyg_Alarm(); + + // Mark POSIX timer free + timer->id = 0; + + err = 0; + } + + timer_mutex.unlock(); + + TIME_RETURN( err ); +} + +//----------------------------------------------------------------------------- +// Set the expiration time of the timer. + +externC int timer_settime( timer_t timerid, int flags, + const struct itimerspec *value, + struct itimerspec *ovalue ) +{ + int err = EINVAL; + TIME_ENTRY(); + + if( value == NULL ) + TIME_RETURN(EINVAL); + + // convert trigger and interval values to ticks. + cyg_tick_count trigger = cyg_timespec_to_ticks( &value->it_value, true ); + cyg_tick_count interval = cyg_timespec_to_ticks( &value->it_interval, true ); + + posix_timer *timer = &timer_table[timerid & TIMER_ID_COOKIE_MASK]; + + timer_mutex.lock(); + + if( timer->id == timerid ) + { + // disable the timer + timer->alarm->disable(); + + if( ovalue != NULL ) + { + cyg_tick_count otrigger, ointerval; + + timer->alarm->get_times( &otrigger, &ointerval ); + + if( timer->armed ) + { + // convert absolute trigger time to interval until next trigger + otrigger -= Cyg_Clock::real_time_clock->current_value(); + } + else otrigger = 0; + + // convert ticks to timespecs + cyg_ticks_to_timespec( otrigger, &ovalue->it_value ); + cyg_ticks_to_timespec( ointerval, &ovalue->it_interval ); + } + + if( trigger == 0 ) + { + // Mark timer disarmed + timer->armed = false; + } + else + { + // If the ABSTIME flag is not set, add the current time + if( (flags & TIMER_ABSTIME) == 0 ) + trigger += Cyg_Clock::real_time_clock->current_value(); + + // Set the alarm running. + timer->alarm->initialize( trigger, interval ); + + // Mark timer armed + timer->armed = true; + + } + + err = 0; + } + + timer_mutex.unlock(); + + TIME_RETURN(err); +} + +//----------------------------------------------------------------------------- +// Get current timer values + +externC int timer_gettime( timer_t timerid, struct itimerspec *value ) +{ + int err = EINVAL; + + TIME_ENTRY(); + + if( value == NULL ) + TIME_RETURN(EINVAL); + + posix_timer *timer = &timer_table[timerid & TIMER_ID_COOKIE_MASK]; + + timer_mutex.lock(); + + if( timer->id == timerid ) + { + cyg_tick_count trigger, interval; + + timer->alarm->get_times( &trigger, &interval ); + + if( timer->armed ) + { + // convert absolute trigger time to interval until next trigger + trigger -= Cyg_Clock::real_time_clock->current_value(); + } + else trigger = 0; + + // convert ticks to timespecs + cyg_ticks_to_timespec( trigger, &value->it_value ); + cyg_ticks_to_timespec( interval, &value->it_interval ); + err = 0; + } + + timer_mutex.unlock(); + + TIME_RETURN(err); +} + +//----------------------------------------------------------------------------- +// Get number of missed triggers + +externC int timer_getoverrun( timer_t timerid ) +{ + int overrun = 0; + + TIME_ENTRY(); + + posix_timer *timer = &timer_table[timerid & TIMER_ID_COOKIE_MASK]; + + timer_mutex.lock(); + + if( timer->id == timerid ) + { + overrun = timer->overrun; + } + + timer_mutex.unlock(); + + CYG_REPORT_RETVAL(overrun); + return overrun; +} + +#endif // ifdef CYGPKG_POSIX_TIMERS + +//========================================================================== +// Nanosleep +// Sleep for the given time. + +externC int nanosleep( const struct timespec *rqtp, + struct timespec *rmtp) +{ + cyg_tick_count ticks, now, then; + + TIME_ENTRY(); + + // check for cancellation first. + PTHREAD_TESTCANCEL(); + + // Fail an invalid timespec + if( !valid_timespec( rqtp ) ) + TIME_RETURN(EINVAL); + + // Return immediately for a zero delay. + if( rqtp->tv_sec == 0 && rqtp->tv_nsec == 0 ) + TIME_RETURN(0); + + // Convert timespec to ticks + ticks = cyg_timespec_to_ticks( rqtp, true ); + + CYG_ASSERT( ticks != 0, "Zero tick count"); + + Cyg_Thread *self = Cyg_Thread::self(); + + // Do the delay, keeping track of how long we actually slept for. + then = Cyg_Clock::real_time_clock->current_value(); + + self->delay( ticks ); + + now = Cyg_Clock::real_time_clock->current_value(); + + + if( rmtp != NULL && (then+ticks) > now ) + { + // We woke up early, return the time left. + // FIXME: strictly we only need to do this if we were woken + // by a signal. + + // Calculate remaining number of ticks. + ticks -= (now-then); + + cyg_ticks_to_timespec( ticks, rmtp ); + } + + // check if we were woken up because we were cancelled. + PTHREAD_TESTCANCEL(); + + TIME_RETURN(0); +} + +// ------------------------------------------------------------------------- +// Wait for a signal, or the given number of seconds + +externC unsigned int sleep( unsigned int seconds ) +{ + TIME_ENTRY(); + + struct timespec timeout; + + timeout.tv_sec = seconds; + timeout.tv_nsec = 0; + + if( nanosleep( &timeout, &timeout ) != 0 ) + { + CYG_REPORT_RETVAL(timeout.tv_sec); + return timeout.tv_sec; + } + + TIME_RETURN(0); +} + +#endif // ifdef CYGPKG_POSIX_CLOCKS + +// ------------------------------------------------------------------------- +// EOF time.cxx diff --git a/packages/compat/posix/v2_0/tests/mqueue1.c b/packages/compat/posix/v2_0/tests/mqueue1.c new file mode 100644 index 00000000..0c66284d --- /dev/null +++ b/packages/compat/posix/v2_0/tests/mqueue1.c @@ -0,0 +1,359 @@ +/*======================================================================== +// +// mqueue1.c +// +// POSIX Message queues tests +// +//======================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jlarmour +// Contributors: +// Date: 2000-05-18 +// Purpose: This file provides tests for POSIX mqueues +// Description: +// Usage: +// +//####DESCRIPTIONEND#### +// +//====================================================================== +*/ + +/* CONFIGURATION */ + +#include + +#ifndef CYGPKG_POSIX_MQUEUES +# define NA_MSG "Message queues not configured" +#endif + +#ifdef NA_MSG +#include // test API +void +cyg_user_start(void) +{ + CYG_TEST_NA( NA_MSG ); +} + +#else + +/* INCLUDES */ + +#include // O_* +#include // errno +#include // file modes +#include // Mqueue Header +#include // test API + +/* FUNCTIONS */ + +static int +my_memcmp(const void *m1, const void *m2, size_t n) +{ + char *s1 = (char *)m1; + char *s2 = (char *)m2; + + while (n--) { + if (*s1 != *s2) + return *s1 - *s2; + s1++; + s2++; + } + return 0; +} // my_memcmp() + +//************************************************************************ + +int +main(void) +{ + mqd_t q1, q2; + char buf[20]; + ssize_t recvlen; + unsigned int prio; + struct mq_attr attr, oattr; + mode_t mode; + int err; + + CYG_TEST_INIT(); + CYG_TEST_INFO( "Starting POSIX message test 1" ); + + q1 = mq_open( "/mq1", O_RDWR ); + CYG_TEST_PASS_FAIL( q1 == (mqd_t)-1, "error for non-existent queue" ); + CYG_TEST_PASS_FAIL( ENOENT == errno, + "errno correct for non-existent queue" ); + + attr.mq_flags = 0; + attr.mq_maxmsg = 4; + attr.mq_msgsize = 20; + mode = S_IRWXU|S_IRWXG|S_IRWXO; // rwx for all + + q1 = mq_open( "/mq1", O_CREAT|O_NONBLOCK|O_WRONLY, mode, &attr ); + CYG_TEST_PASS_FAIL( q1 != (mqd_t)-1, "simple mq_open (write only)" ); + + err = mq_getattr( q1, &attr ); + CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr" ); + CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && + (20 == attr.mq_msgsize) && + (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && + (O_RDONLY != (attr.mq_flags & O_RDONLY)) && + (O_WRONLY == (attr.mq_flags & O_WRONLY)) && + (O_RDWR != (attr.mq_flags & O_RDWR)) && + (0 == attr.mq_curmsgs ), "getattr attributes correct" ); + + err = mq_send( q1, "Vik is brill", sizeof("Vik is brill"), 10 ); + + CYG_TEST_PASS_FAIL( 0 == err, "simple mq_send" ); + + err = mq_getattr( q1, &attr ); + CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr after send" ); + CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && + (20 == attr.mq_msgsize) && + (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && + (O_RDONLY != (attr.mq_flags & O_RDONLY)) && + (O_WRONLY == (attr.mq_flags & O_WRONLY)) && + (O_RDWR != (attr.mq_flags & O_RDWR)) && + (1 == attr.mq_curmsgs ), + "getattr attributes correct #2" ); + + q2 = mq_open( "/mq1", O_RDONLY|O_CREAT|O_EXCL ); + CYG_TEST_PASS_FAIL( q2 == (mqd_t)-1, + "error for exclusive open of existing queue" ); + CYG_TEST_PASS_FAIL( EEXIST == errno, + "errno correct for exclusive open of existing queue" ); + + q2 = mq_open( "/mq1", O_RDONLY ); + CYG_TEST_PASS_FAIL( q2 != (mqd_t)-1, "simple mq_open (read only)" ); + + err = mq_getattr( q2, &attr ); + CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr, different mqd_t" ); + CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && + (20 == attr.mq_msgsize) && + (O_NONBLOCK != (attr.mq_flags & O_NONBLOCK)) && + (O_RDONLY == (attr.mq_flags & O_RDONLY)) && + (O_WRONLY != (attr.mq_flags & O_WRONLY)) && + (O_RDWR != (attr.mq_flags & O_RDWR)) && + (1 == attr.mq_curmsgs ), + "getattr attributes correct #3" ); + + err = mq_close( q2 ); + CYG_TEST_PASS_FAIL( 0 == err, "simple mq_close" ); + + q2 = mq_open( "/mq1", O_RDONLY ); + CYG_TEST_PASS_FAIL( q2 != (mqd_t)-1, "mq_open reopen (read only)" ); + + err = mq_getattr( q2, &attr ); + CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr, different mqd_t" ); + CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && + (20 == attr.mq_msgsize) && + (O_NONBLOCK != (attr.mq_flags & O_NONBLOCK)) && + (O_RDONLY == (attr.mq_flags & O_RDONLY)) && + (O_WRONLY != (attr.mq_flags & O_WRONLY)) && + (O_RDWR != (attr.mq_flags & O_RDWR)) && + (1 == attr.mq_curmsgs ), + "getattr attributes correct #4" ); + + recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); + CYG_TEST_PASS_FAIL( recvlen == sizeof("Vik is brill"), + "receive message length" ); + CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "Vik is brill", + sizeof("Vik is brill")), + "received message data intact" ); + CYG_TEST_PASS_FAIL( 10 == prio, "received at correct priority" ); + + err = mq_getattr( q1, &attr ); + CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr after send" ); + CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && + (20 == attr.mq_msgsize) && + (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && + (O_RDONLY != (attr.mq_flags & O_RDONLY)) && + (O_WRONLY == (attr.mq_flags & O_WRONLY)) && + (O_RDWR != (attr.mq_flags & O_RDWR)) && + (0 == attr.mq_curmsgs ), + "getattr attributes correct #5" ); + + attr.mq_flags |= O_NONBLOCK; + err = mq_setattr( q2, &attr, &oattr ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_setattr O_NONBLOCK" ); + CYG_TEST_PASS_FAIL( (4 == oattr.mq_maxmsg) && + (20 == oattr.mq_msgsize) && + (O_NONBLOCK != (oattr.mq_flags & O_NONBLOCK)) && + (O_RDONLY == (oattr.mq_flags & O_RDONLY)) && + (O_WRONLY != (oattr.mq_flags & O_WRONLY)) && + (O_RDWR != (oattr.mq_flags & O_RDWR)) && + (0 == oattr.mq_curmsgs ), + "old attribute correct" ); + err = mq_getattr( q2, &attr ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_getattr after O_NONBLOCK" ); + CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && + (20 == attr.mq_msgsize) && + (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && + (O_RDONLY == (attr.mq_flags & O_RDONLY)) && + (O_WRONLY != (attr.mq_flags & O_WRONLY)) && + (O_RDWR != (attr.mq_flags & O_RDWR)) && + (0 == attr.mq_curmsgs ), + "new attribute correct" ); + + recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); + CYG_TEST_PASS_FAIL( recvlen == (ssize_t)-1, + "mq_receive, empty buffer, non-blocking" ); + CYG_TEST_PASS_FAIL( EAGAIN == errno, + "errno correct for non-blocking" ); + + err = mq_send( q2, "foo", sizeof("foo"), 1 ); + CYG_TEST_PASS_FAIL( -1 == err, "error on mq_send on read-only descriptor" ); + CYG_TEST_PASS_FAIL( EBADF == errno, + "errno correct for mq_send on r/o descriptor" ); + + err = mq_send( q2, "supercalifragilisticexpealidocious", 21, 2 ); + CYG_TEST_PASS_FAIL( -1 == err, "error on mq_send (message too long)" ); + CYG_TEST_PASS_FAIL( EMSGSIZE == errno, + "errno correct for mq_send (message too long)" ); + + err = mq_send( q1, "", sizeof(""), 5 ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_send \"\"" ); + + err = mq_send( q1, "I love Vik", sizeof("I love Vik"), 7 ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_send (different priority)" ); + + err = mq_send( q1, "a lot!", sizeof("a lot!"), 7 ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_send (same priority)" ); + + err = mq_send( q1, "Vik is a babe", sizeof("Vik is a babe"), 6 ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_send (middle priority)" ); + + err = mq_send( q1, "wibble", sizeof("wibble"), 6 ); + CYG_TEST_PASS_FAIL( -1 == err, "error on mq_send with full queue" ); + CYG_TEST_PASS_FAIL( EAGAIN == errno, + "errno correct for mq_send full queue" ); + + err = mq_getattr( q2, &attr ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_getattr after sends" ); + CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && + (20 == attr.mq_msgsize) && + (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && + (O_RDONLY == (attr.mq_flags & O_RDONLY)) && + (O_WRONLY != (attr.mq_flags & O_WRONLY)) && + (O_RDWR != (attr.mq_flags & O_RDWR)) && + (4 == attr.mq_curmsgs ), + "getattr attributes correct #5" ); + + recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); + CYG_TEST_PASS_FAIL( recvlen == sizeof("I love Vik"), + "receive message length (prioritized) #1" ); + CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "I love Vik", + sizeof("I love Vik")), + "received message data intact (prioritized) #1" ); + CYG_TEST_PASS_FAIL( 7 == prio, + "received at correct priority (prioritized) #1" ); + + recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); + CYG_TEST_PASS_FAIL( recvlen == sizeof("a lot!"), + "receive message length (prioritized) #2" ); + CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "a lot!", + sizeof("a lot!")), + "received message data intact (prioritized) #2" ); + CYG_TEST_PASS_FAIL( 7 == prio, + "received at correct priority (prioritized) #2" ); + + recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); + CYG_TEST_PASS_FAIL( recvlen == sizeof("Vik is a babe"), + "receive message length (prioritized) #3" ); + CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "Vik is a babe", + sizeof("Vik is a babe")), + "received message data intact (prioritized) #3" ); + CYG_TEST_PASS_FAIL( 6 == prio, + "received at correct priority (prioritized) #3" ); + + recvlen = mq_receive( q2, buf, 0, &prio ); + CYG_TEST_PASS_FAIL( recvlen == (ssize_t)-1, + "mq_receive, zero-sized buffer" ); + + recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); + CYG_TEST_PASS_FAIL( recvlen == sizeof(""), + "receive message length (prioritized) #4" ); + CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "", + sizeof("")), + "received message data intact (prioritized) #4" ); + CYG_TEST_PASS_FAIL( 5 == prio, + "received at correct priority (prioritzed) #4" ); + + recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); + CYG_TEST_PASS_FAIL( recvlen == (ssize_t)-1, + "mq_receive, empty buffer, non-blocking #2" ); + CYG_TEST_PASS_FAIL( EAGAIN == errno, + "errno correct for non-blocking #2" ); + + err = mq_send( q1, "12345678901234567890", 20, 15 ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_send (before closing)" ); + + err = mq_unlink( "/foo" ); + CYG_TEST_PASS_FAIL( -1 == err, "mq_unlink (wrong name)" ); + CYG_TEST_PASS_FAIL( ENOENT == errno, + "errno correct for mq_unlink (wrong name)" ); + + err = mq_unlink( "/mq1" ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_unlink (before closing)" ); + + err = mq_close( q1 ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_close (send descriptor)" ); + + recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); + CYG_TEST_PASS_FAIL( recvlen == 20, + "receive message length (mid close)" ); + CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "12345678901234567890", 20 ), + "received message data intact (mid close)" ); + CYG_TEST_PASS_FAIL( 15 == prio, + "received at correct priority (mid close)" ); + + err = mq_close( q2 ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_close (receive descriptor)" ); + + q1 = mq_open( "/mq1", O_RDONLY ); + CYG_TEST_PASS_FAIL( q1 == (mqd_t)-1, "error for non-existent queue" ); + CYG_TEST_PASS_FAIL( ENOENT == errno, + "errno correct for non-existent queue" ); + + CYG_TEST_EXIT("POSIX message test 1"); + + return 0; +} // main() + +//------------------------------------------------------------------------ + +#endif + +/* EOF mqueue1.c */ diff --git a/packages/compat/posix/v2_0/tests/mqueue2.c b/packages/compat/posix/v2_0/tests/mqueue2.c new file mode 100644 index 00000000..f1405504 --- /dev/null +++ b/packages/compat/posix/v2_0/tests/mqueue2.c @@ -0,0 +1,276 @@ +/*======================================================================== +// +// mqueue2.c +// +// POSIX Message queues tests - mq_notify +// +//======================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jlarmour +// Contributors: +// Date: 2000-05-18 +// Purpose: This file provides tests for POSIX mqueue mq_notify +// Description: +// Usage: +// +//####DESCRIPTIONEND#### +// +//====================================================================== +*/ + +/* CONFIGURATION */ + +#include + +#ifndef CYGPKG_POSIX_MQUEUES +# define NA_MSG "Message queues not configured" +#elif !defined(CYGPKG_POSIX_SIGNALS) +# define NA_MSG "No POSIX signals configured" +#endif + +#ifdef NA_MSG +#include // test API +void +cyg_user_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( NA_MSG ); +} + +#else + +/* INCLUDES */ + +#include // O_* +#include // errno +#include // file modes +#include // Mqueue Header +#include // test API +#include // signals + +/* GLOBALS */ +sig_atomic_t signals=0; +char buf[20]; +unsigned int prio; + + +/* FUNCTIONS */ + +static int +my_memcmp(const void *m1, const void *m2, size_t n) +{ + char *s1 = (char *)m1; + char *s2 = (char *)m2; + + while (n--) { + if (*s1 != *s2) + return *s1 - *s2; + s1++; + s2++; + } + return 0; +} // my_memcmp() + +static char * +my_strcpy(char *s1, const char *s2) +{ + char *s = s1; + while (*s2) { + *s1++ = *s2++; + } + return s; +} // my_strcpy() + +static size_t +my_strlen(const char *s) +{ + const char *start = s; + while (*s) + s++; + return (s - start); +} // my_strcpy() + + + +//************************************************************************ + +static void +sigusr1_handler( int signo, siginfo_t *info, void *context ) +{ + ssize_t recvlen; + char mybuf[20]; + unsigned int myprio; + mqd_t *q = (mqd_t *)info->si_value.sival_ptr; + + CYG_TEST_PASS_FAIL( SIGUSR1 == signo, "correct signal number #1" ); + CYG_TEST_PASS_FAIL( SIGUSR1 == info->si_signo, "correct signal number #2" ); + CYG_TEST_PASS_FAIL( SI_MESGQ == info->si_code, "correct signal code" ); + + signals++; + + // retrieve message and compare with buf + recvlen = mq_receive( *q, mybuf, sizeof(mybuf), &myprio ); + CYG_TEST_PASS_FAIL( recvlen == my_strlen(buf), + "receive message length" ); + CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, mybuf, my_strlen(buf)), + "received message data intact" ); + CYG_TEST_PASS_FAIL( prio == myprio, + "received at correct priority" ); +} + +//************************************************************************ + +int +main(void) +{ + mqd_t q1; + struct mq_attr attr; + mode_t mode; + int err; + ssize_t recvlen; + char mybuf[20]; + unsigned int myprio; + struct sigevent ev; + struct sigaction act; + + CYG_TEST_INIT(); + CYG_TEST_INFO( "Starting POSIX message test 2" ); + +#if 0 + if ( 0 != pthread_create( &thr, NULL, &thread, NULL ) ) { + CYG_TEST_FAIL_FINISH( "Couldn't create a helper thread" ); + } +#endif + + attr.mq_flags = 0; + attr.mq_maxmsg = 4; + attr.mq_msgsize = 20; + mode = S_IRWXU|S_IRWXG|S_IRWXO; // rwx for all + + q1 = mq_open( "/mq1", O_CREAT|O_NONBLOCK|O_RDWR, mode, &attr ); + CYG_TEST_PASS_FAIL( q1 != (mqd_t)-1, "simple mq_open (write only)" ); + + err = mq_getattr( q1, &attr ); + CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr" ); + CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && + (20 == attr.mq_msgsize) && + (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && + (O_RDWR == (attr.mq_flags & O_RDWR)) && + (0 == attr.mq_curmsgs ), "getattr attributes correct" ); + + + act.sa_sigaction = &sigusr1_handler; + sigfillset( &act.sa_mask ); // enable all signals + act.sa_flags = SA_SIGINFO; + + if ( 0 != sigaction( SIGUSR1, &act, NULL ) ) { + CYG_TEST_FAIL_FINISH( "Couldn't register signal handler" ); + } + + ev.sigev_notify = SIGEV_SIGNAL; + ev.sigev_signo = SIGUSR1; + ev.sigev_value.sival_ptr = (void *)&q1; + + err = mq_notify( q1, &ev ); + CYG_TEST_PASS_FAIL( 0 == err, "simple mq_notify" ); + + my_strcpy( buf, "Vik is the best" ); + prio = 7; + err = mq_send( q1, buf, my_strlen(buf), prio ); + + CYG_TEST_PASS_FAIL( 0 == err, "mq_send #1" ); + + CYG_TEST_PASS_FAIL( 1 == signals, "got notification" ); + + my_strcpy( buf, "Scrummy Vik" ); + prio = 6; + err = mq_send( q1, buf, my_strlen(buf), prio ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_send #2" ); + + CYG_TEST_PASS_FAIL( 1 == signals, "correctly didn't get notification" ); + + recvlen = mq_receive( q1, mybuf, sizeof(mybuf), &myprio ); + CYG_TEST_PASS_FAIL( recvlen == my_strlen(buf), + "receive message length" ); + CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, mybuf, my_strlen(buf)), + "received message data intact" ); + CYG_TEST_PASS_FAIL( prio == myprio, + "received at correct priority" ); + + err = mq_notify( q1, &ev ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_notify #2" ); + + err = mq_notify( q1, &ev ); + CYG_TEST_PASS_FAIL( -1 == err, "second mq_notify returns error" ); + CYG_TEST_PASS_FAIL( EBUSY == errno, + "errno correct for second mq_notify error" ); + + err = mq_notify( q1, NULL ); + CYG_TEST_PASS_FAIL( 0 == err, "clear notification" ); + + my_strcpy( buf, "Vik is k3wl" ); + prio = 8; + err = mq_send( q1, buf, my_strlen(buf), prio ); + + CYG_TEST_PASS_FAIL( 0 == err, "mq_send #2" ); + + CYG_TEST_PASS_FAIL( 1 == signals, "correctly didn't get notification #2" ); + + recvlen = mq_receive( q1, mybuf, sizeof(mybuf), &myprio ); + CYG_TEST_PASS_FAIL( recvlen == my_strlen(buf), + "receive message length" ); + CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, mybuf, my_strlen(buf)), + "received message data intact" ); + CYG_TEST_PASS_FAIL( prio == myprio, + "received at correct priority" ); + + err = mq_close( q1 ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_close" ); + + err = mq_unlink( "/mq1" ); + CYG_TEST_PASS_FAIL( 0 == err, "mq_unlink" ); + + CYG_TEST_EXIT("POSIX message test 2"); + + return 0; +} // main() + +//------------------------------------------------------------------------ + +#endif + +/* EOF mqueue2.c */ diff --git a/packages/compat/posix/v2_0/tests/mutex3.c b/packages/compat/posix/v2_0/tests/mutex3.c new file mode 100644 index 00000000..c35d9ef9 --- /dev/null +++ b/packages/compat/posix/v2_0/tests/mutex3.c @@ -0,0 +1,672 @@ +//========================================================================== +// +// mutex3.cxx +// +// Mutex test 3 - priority inheritance +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt, nickg, jlarmour +// Date: 2000-01-06 +// Description: Tests mutex priority inheritance. This is simply a translation +// of the similarly named kernel test to the POSIX API +//####DESCRIPTIONEND#### + +// ------------------------------------------------------------------------ + +#include +#include +#include +#ifdef CYGPKG_KERNEL +#include +#endif + +#ifdef CYGPKG_ISOINFRA +# include +# include +# include +# include +# include +#endif + +#if !defined(CYGPKG_POSIX_PTHREAD) +#define NA_MSG "POSIX threads not enabled" + +// ------------------------------------------------------------------------ +// +// These checks should be enough; any other scheduler which has priorities +// should manifest as having no priority inheritance, but otherwise fine, +// so the test should work correctly. + +#elif !defined(_POSIX_THREAD_PRIORITY_SCHEDULING) +#define NA_MSG "No POSIX thread priority scheduling enabled" +#elif !defined(_POSIX_THREAD_PRIO_INHERIT) +#define NA_MSG "No POSIX thread priority inheritance enabled" +#elif !defined(_POSIX_SEMAPHORES) +#define NA_MSG "No POSIX sempaphore support enabled enabled" +#elif !defined(CYGFUN_KERNEL_API_C) +#define NA_MSG "Kernel C API not enabled" +#elif defined(CYGPKG_KERNEL_SMP_SUPPORT) +#define NA_MSG "Test cannot run with SMP support" +#endif + +#ifdef NA_MSG +void +cyg_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(NA_MSG); +} +#else + +#include +#include +#include // diag_printf + +#include // Some extras + +// ------------------------------------------------------------------------ +// Management functions +// +// Stolen from testaux.hxx and copied in here because I want to be able to +// reset the world also. +// ... and subsequently POSIXized out of all similarly with its progenitors. + +#define NTHREADS 7 + +#define STACKSIZE (PTHREAD_STACK_MIN*2) + +static pthread_t thread[NTHREADS] = { 0 }; + +typedef CYG_WORD64 CYG_ALIGNMENT_TYPE; + +static CYG_ALIGNMENT_TYPE stack[NTHREADS] [ + (STACKSIZE+sizeof(CYG_ALIGNMENT_TYPE)-1) + / sizeof(CYG_ALIGNMENT_TYPE) ]; + +// Semaphores to halt execution of threads +static sem_t hold[NTHREADS]; + +// Flag to tell all threads to exit +static int all_exit; + +// Application thread data is passed here, the thread +// argument is +static CYG_ADDRWORD thread_data[NTHREADS]; + +static volatile int nthreads = 0; + +// Sleep for 1 tick... +static struct timespec sleeptime; + + +static pthread_t new_thread( void *(*entry)(void *), + CYG_ADDRWORD data, + int priority, + int do_resume) +{ + pthread_attr_t attr; + int _nthreads = nthreads++; + + struct sched_param schedparam; + schedparam.sched_priority = priority; + + pthread_attr_init( &attr ); + pthread_attr_setstackaddr( &attr, (void *)((char *)(&stack[_nthreads])+STACKSIZE) ); + pthread_attr_setstacksize( &attr, STACKSIZE ); + pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); + pthread_attr_setschedpolicy( &attr, SCHED_RR ); + pthread_attr_setschedparam( &attr, &schedparam ); + + CYG_ASSERT(_nthreads < NTHREADS, + "Attempt to create more than NTHREADS threads"); + + thread_data[_nthreads] = data; + + sem_init( &hold[_nthreads], 0, do_resume ? 1 : 0 ); + all_exit = 0; + + pthread_create( &thread[_nthreads], + &attr, + entry, + (void *)_nthreads); + + return thread[_nthreads]; +} + + +static void kill_threads( void ) +{ + CYG_ASSERT(nthreads <= NTHREADS, + "More than NTHREADS threads"); + CYG_ASSERT( pthread_equal(pthread_self(),thread[0]), + "kill_threads() not called from thread 0"); + all_exit = 1; + while ( nthreads > 1 ) { + nthreads--; + if ( 0 != thread[nthreads] ) { + sem_post( &hold[nthreads] ); + pthread_cancel( thread[nthreads] ); + pthread_join( thread[nthreads], NULL ); + thread[nthreads] = 0; + sem_destroy( &hold[nthreads] ); + } + } + CYG_ASSERT(nthreads == 1, + "No threads left"); +} + +// ------------------------------------------------------------------------ + +#define DELAYFACTOR 1 // for debugging + +// ------------------------------------------------------------------------ + +pthread_mutex_t mutex; + +// These are for reporting back to the master thread +volatile int got_it = 0; +volatile int t3ran = 0; +volatile int t3ended = 0; +volatile int extras[4] = {0,0,0,0}; + +volatile int go_flag = 0; // but this one controls thread 3 from thread 2 + +// ------------------------------------------------------------------------ +// 0 to 3 of these run generally to interfere with the other processing, +// to cause multiple prio inheritances, and clashes in any orders. + +static void *extra_thread( void *arg ) +{ +#define XINFO( z ) \ + do { z[13] = '0' + data; CYG_TEST_INFO( z ); } while ( 0 ) + + static char running[] = "Extra thread Xa running"; + static char exiting[] = "Extra thread Xa exiting"; + static char resumed[] = "Extra thread Xa resumed"; + static char locked[] = "Extra thread Xa locked"; + static char unlocked[] = "Extra thread Xa unlocked"; + + int id = (int)arg; + CYG_ADDRWORD data = thread_data[id]; + + CYG_ASSERT( (id >= 4 && id <= 6), "extra_thread invalid id" ); + + // Emulate resume behaviour + sem_wait( &hold[id] ); + if( all_exit ) return 0; + + XINFO( running ); + + sem_wait( &hold[id] ); + + XINFO( resumed ); + + pthread_mutex_lock( &mutex ); + + XINFO( locked ); + + pthread_mutex_unlock( &mutex ); + + XINFO( unlocked ); + + extras[ data ] ++; + + XINFO( exiting ); + + return NULL; +} + +// ------------------------------------------------------------------------ + +static void *t1( void *arg ) +{ + int id = (int)arg; + //CYG_ADDRWORD data = thread_data[id]; + + // Emulate resume behaviour + sem_wait( &hold[id] ); + if( all_exit ) return 0; + + CYG_TEST_INFO( "Thread 1 running" ); + + sem_wait( &hold[id] ); + + pthread_mutex_lock( &mutex ); + + got_it++; + + CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,1]" ); + + pthread_mutex_unlock( &mutex ); + + CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,2]" ); + + // That's all. + + CYG_TEST_INFO( "Thread 1 exit" ); + + return 0; +} + +// ------------------------------------------------------------------------ + +static void *t2( void *arg ) +{ + int i; + int id = (int)arg; + CYG_ADDRWORD data = thread_data[id]; + cyg_tick_count_t now, then; + + // Emulate resume behaviour + sem_wait( &hold[id] ); + if( all_exit ) return 0; + + CYG_TEST_INFO( "Thread 2 running" ); + + CYG_TEST_CHECK( 0 == (data & ~0x77), "Bad T2 arg: extra bits" ); + CYG_TEST_CHECK( 0 == (data & (data >> 4)), "Bad T2 arg: overlap" ); + + sem_wait( &hold[id] ); + + // depending on our config argument, optionally restart some of the + // extra threads to throw noise into the scheduler: + for ( i = 0; i < 3; i++ ) + if ( (1 << i) & data ) // bits 0-2 control + sem_post( &hold[i+4] ); // made sure extras are thread[4-6] + + // let those threads run + for( i = 0; i < DELAYFACTOR * 10; i++ ) + nanosleep( &sleeptime, NULL ); + + cyg_scheduler_lock(); // do this next lot atomically + + go_flag = 1; // unleash thread 3 + sem_post( &hold[1] ); // resume thread 1 + + // depending on our config argument, optionally restart some of the + // extra threads to throw noise into the scheduler at this later point: + for ( i = 4; i < 7; i++ ) + if ( (1 << i) & data ) // bits 4-6 control + sem_post( &hold[i] ); // made sure extras are thread[4-6] + + cyg_scheduler_unlock(); // let scheduling proceed + + // Need a delay (but not a CPU yield) to allow t3 to awaken and act on + // the go_flag, otherwise we check these details below too soon. + // Actually, waiting for the clock to tick a couple of times would be + // better, so that is what we will do. Must be a busy-wait. + then = cyg_current_time(); + do { + now = cyg_current_time(); + // Wait longer than the delay in t3 waiting on go_flag + } while ( now < (then + 3) ); + +#ifdef _POSIX_THREAD_PRIO_INHERIT + CYG_TEST_INFO( "Checking for mutex priority inheritance" ); + CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" ); + CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" ); +#else + CYG_TEST_INFO( "Checking for NO mutex priority inheritance" ); + CYG_TEST_CHECK( 0 == t3ran, "Thread 3 DID run" ); + CYG_TEST_CHECK( 0 == got_it, "Thread 1 DID get the mutex" ); +#endif + + CYG_TEST_CHECK( 0 == t3ended, "Thread 3 ended prematurely [T2,1]" ); + + for( i = 0; i < DELAYFACTOR * 20; i++ ) + nanosleep( &sleeptime, NULL ); // let those threads run + + CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" ); + CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" ); + CYG_TEST_CHECK( 1 == t3ended, "Thread 3 has not ended" ); + + for ( i = 0; i < 3; i++ ) + if ( (1 << i) & (data | data >> 4) ) // bits 0-2 and 4-6 control + CYG_TEST_CHECK( 1 == extras[i+1], "Extra thread did not run" ); + else + CYG_TEST_CHECK( 0 == extras[i+1], "Extra thread ran" ); + + CYG_TEST_PASS( "Thread 2 exiting, AOK" ); + // That's all: restart the control thread. + sem_post( &hold[0] ); + + return 0; +} + +// ------------------------------------------------------------------------ + +static void *t3( void *arg ) +{ + int i; + int id = (int)arg; + //CYG_ADDRWORD data = thread_data[id]; + + // Emulate resume behaviour + sem_wait( &hold[id] ); + if( all_exit ) return 0; + + CYG_TEST_INFO( "Thread 3 running" ); + + pthread_mutex_lock( &mutex ); + + for( i = 0; i < DELAYFACTOR * 5; i++ ) + nanosleep( &sleeptime, NULL ); // let thread 3a run + + sem_post( &hold[2] ); // resume thread 2 + + while ( 0 == go_flag ) + nanosleep( &sleeptime, NULL ); // wait until we are told to go + + t3ran ++; // record the fact + + CYG_TEST_CHECK( 0 == got_it, "Thread 1 claims to have got my mutex" ); + + pthread_mutex_unlock( &mutex ); + + t3ended ++; // record that we came back + + CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" ); + + CYG_TEST_INFO( "Thread 3 exit" ); + + return 0; +} + +// ------------------------------------------------------------------------ + +static void *control_thread( void *arg ) +{ + int i,z; + int id = (int)arg; + //CYG_ADDRWORD data = thread_data[id]; + + // Emulate resume behaviour + sem_wait( &hold[id] ); + if( all_exit ) return 0; + + // one tick sleep time + sleeptime.tv_nsec = 10000000; + sleeptime.tv_sec = 0; + + CYG_TEST_INIT(); + CYG_TEST_INFO( "Control Thread running" ); + + // Go through the 27 possibilitied of resuming the extra threads + // 0: not at all + // 1: early in the process + // 2: later on + // which are represented by bits 0-3 and 4-6 resp in the argument to + // thread 2 (none set means no resume at all). + for ( i = 0; i < 27; i++ ) { + static int xx[] = { 0, 1, 16 }; + int j = i % 3; + int k = (i / 3) % 3; + int l = (i / 9) % 3; + + int d = xx[j] | (xx[k]<<1) | (xx[l]<<2) ; + + if ( cyg_test_is_simulator && (0 != i && 13 != i && 26 != i) ) + continue; // 13 is 111 base 3, 26 is 222 base 3 + +#ifdef _POSIX_THREAD_PRIO_INHERIT + // If the simple scheme plus relay enhancement, or any other + // *complete* scheme, we can run all three ancillary threads no + // problem, so no special action here. + +#else + // If no priority inheritance at all, running threads 1a and 2a is + // OK, but not thread 3a; it blocks the world. + if ( l ) // Cannot run thread 3a if no + break; // priority inheritance at all. +#endif + + // Reinitialize mutex to provide priority inheritance + { + pthread_mutexattr_t attr; + pthread_mutexattr_init( &attr ); + pthread_mutexattr_setprotocol( &attr, PTHREAD_PRIO_INHERIT ); + pthread_mutex_init( &mutex, &attr ); + } + + got_it = 0; + t3ran = 0; + t3ended = 0; + for ( z = 0; z < 4; z++ ) extras[z] = 0; + go_flag = 0; + + new_thread( t1, 0, 15, 1 ); // Slot 1 + new_thread( t2, d, 10, 1 ); // Slot 2 + new_thread( t3, 0, 5, 1 ); // Slot 3 + + new_thread( extra_thread, 1, 17, j ); // Slot 4 + new_thread( extra_thread, 2, 12, k ); // Slot 5 + new_thread( extra_thread, 3, 8, l ); // Slot 6 + + { + static char *a[] = { "inactive", "run early", "run late" }; + diag_printf( "\n----- [%2d] New Cycle: 0x%02x, Threads 1a %s, 2a %s, 3a %s -----\n", + i, d, a[j], a[k], a[l] ); + } + + sem_wait( &hold[0] ); + + kill_threads(); + pthread_mutex_destroy( &mutex ); + } + CYG_TEST_EXIT( "Control Thread exit" ); + + return 0; +} + +// ------------------------------------------------------------------------ + +static sem_t main_sem; + +externC int +main( int argc, char **argv ) +{ + new_thread( control_thread, 0, 20, 1 ); + + // We have nothing for main to do here, so put it to sleep on + // its own semaphore. We cannot let it just exit since that + // will end the whole program. + + sem_init( &main_sem, 0, 0 ); + + for(;;) sem_wait( &main_sem ); +} + +// ------------------------------------------------------------------------ +// Documentation: enclosed is the design of this test. +// +// It has been carefully constructed so that it does NOT use other kernel +// facilities (aside from delay-task) to test that priority inheritance is +// working, or not, as intended by the configuration. +// +// These notes describe the flow of control in one run of the test with the +// ancillary tasks optionally interspersed. The details of how those extra +// tasks are or are not allowed to run are not described. +// +// +// +// The only change in the test that depends on whether there is inheritance or +// not is the check in thread 2 on "3-ran" and "got it" flags marked **** +// +// +// volatile &c booleans: +// "got it" = FALSE +// "3-ran" = FALSE +// "3-ended" = FALSE +// "extras"[3] = FALSE +// +// thread 1. prio 5, self-suspend. +// +// thread 1a, prio 8, self-suspend. +// +// thread 2. prio 10, self-suspend. +// +// thread 2a, prio 12, self-suspend. +// +// thread 3. prio 15, runs, lock mutex, resume(2) +// +// thread 3a, prio 17, self-suspend. +// +// 2. runs, +// 2. resume(3a) +++OPTIONAL +// 2. resume(2a) +++OPTIONAL +// 2. resume(1a) +++OPTIONAL +// [1a lock-fail] thread 3->prio := 8 +// +// [3. runs maybe, does the looping thing] +// +// 2. sleep a while... +// +// [2a lock-fail] thread 3->prio := 12 +// +// [3. runs maybe, does the looping thing] +// +// [3a lock-fail] thread 3->prio unchanged +// +// [3. runs maybe, does the looping thing] +// +// 2. lock scheduler +// 2. set "go-flag" +// 2. resume(1) +// 2. resume(1a) +++OPTIONAL +// 2. resume(2a) +++OPTIONAL +// 2. resume(3a) +++OPTIONAL +// 2. unlock scheduler +// +// 1. runs, lock mutex - thread 3 has it locked +// +// 2. busy-waits a bit for thread 3 to come out of its delay() loop. +// This must be a *busy*wait so that 3 can only run via the +// inherited raised priority. +// +// [xa. all do the same: lock mutex, ] +// [xa. unlock mutex ] +// [xa. set a flag "extras"[x] to say we are done. ] +// [xa. exit ] +// +// +// +// INHERIT +// ------- +// +// thread 3->prio := 5 +// +// 3. runs, +// 3. set a flag to say "3-ran", +// 3. loop with a sleep(1) until "go-flag" is set. +// 3. check "got it" is false, +// 3. then unlock mutex, +// +// thread 3->prio := 15 +// +// 1. runs, set a flag to say "got it", +// 1. check "3-ended" flag is false +// 1. unlock mutex, +// 1. check "3-ended" flag is still false +// 1. exit. +// +// [1a locks, unlocks, exits] +// +// 2. runs, check "3-ran" and "got it" flags are TRUE **** +// 2. check "3-ended" flag is false +// 2. sleeps for a while so that... +// +// [2a locks, unlocks, exits] +// +// 3. runs, set "3-ended" flag, +// 3. check "3-ran" and "got it" flags +// 3. exit +// +// [3a locks, unlocks, exits] +// +// 2. awakens, checks all flags true, +// 2. check that all "extra" threads that we started have indeed run +// 2. end of test. +// +// +// +// +// NO-INHERIT +// ---------- +// thread 1 is waiting on the mutex +// +// [1a lock-fail] +// +// 2. runs, checks that "3-ran" and "got it" flags are FALSE **** +// 2. check "3-ended" flag is false +// 2. sleeps for a while so that... +// +// [2a. lock-fail] +// +// 3. runs, set a flag to say "3-ran", +// 3. check "got it" is false, +// 3. then unlock mutex, +// +// 1. runs, set a flag to say "got it", +// 1. check "3-ended" flag is false +// 1. unlock mutex, +// 1. check "3-ended" flag is still false +// 1. exit. +// +// [1a locks, unlocks, exits] +// [2a locks, unlocks, exits] +// +// 3. runs, set "3-ended" flag, +// 3. check "3-ran" and "got it" flags +// 3. exit +// +// [3a locks, unlocks, exits] +// +// 2. awakens, checks all flags true, +// 2. check that all "extra" threads that we started have indeed run +// 2. end of test. +// +// +// (the end) +// +// +// ------------------------------------------------------------------------ + +#endif + +// EOF mutex3.cxx diff --git a/packages/compat/posix/v2_0/tests/pthread1.c b/packages/compat/posix/v2_0/tests/pthread1.c new file mode 100644 index 00000000..116bfdf5 --- /dev/null +++ b/packages/compat/posix/v2_0/tests/pthread1.c @@ -0,0 +1,119 @@ +//========================================================================== +// +// pthread1.cxx +// +// POSIX pthread test 1 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-04-10 +// Description: Tests POSIX join functionality. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#ifndef CYGPKG_POSIX_PTHREAD +#define NA_MSG "POSIX threads not enabled" +#endif + +#ifdef NA_MSG +void +cyg_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(NA_MSG); +} +#else + +#include +#include + +//-------------------------------------------------------------------------- +// Thread stack. + +char thread_stack[PTHREAD_STACK_MIN*2]; + +//-------------------------------------------------------------------------- + +void *pthread_entry1( void *arg) +{ + CYG_TEST_INFO( "Thread 1 running" ); + + pthread_exit( (void *)((int)arg+1) ); +} + +//-------------------------------------------------------------------------- + +int main(int argc, char **argv) +{ + pthread_t thread; + pthread_attr_t attr; + void *retval; + + CYG_TEST_INIT(); + + // Create test thread + pthread_attr_init( &attr ); + + pthread_attr_setstackaddr( &attr, (void *)&thread_stack[sizeof(thread_stack)] ); + pthread_attr_setstacksize( &attr, sizeof(thread_stack) ); + + pthread_create( &thread, + &attr, + pthread_entry1, + (void *)0x12345678); + + // Now join with it + pthread_join( thread, &retval ); + + // check retval + + if( (long)retval == 0x12345679 ) + CYG_TEST_PASS_FINISH( "pthread1" ); + else + CYG_TEST_FAIL_FINISH( "pthread1" ); +} + +#endif + +//-------------------------------------------------------------------------- +// end of pthread1.c diff --git a/packages/compat/posix/v2_0/tests/pthread2.c b/packages/compat/posix/v2_0/tests/pthread2.c new file mode 100644 index 00000000..a501fe65 --- /dev/null +++ b/packages/compat/posix/v2_0/tests/pthread2.c @@ -0,0 +1,176 @@ +//========================================================================== +// +// pthread2.cxx +// +// POSIX pthread test 2 - per-thread data +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-04-10 +// Description: Tests POSIX per-thread data. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#ifndef CYGPKG_POSIX_PTHREAD +#define NA_MSG "POSIX threads not enabled" +#endif + +#ifdef NA_MSG +void +cyg_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(NA_MSG); +} +#else + +#include +#include + +//-------------------------------------------------------------------------- +// Thread stack. + +char thread_stack[2][PTHREAD_STACK_MIN*2]; + +pthread_t thread[2]; + +pthread_key_t key; + +//-------------------------------------------------------------------------- + +void key_destructor( void *val ) +{ + int ret; + + CYG_TEST_INFO( "key destructor called" ); + + if( (long)val == 0xAAAAAAAA ) + { + ret = pthread_setspecific( key, NULL ); + CYG_TEST_CHECK( ret == 0, "pthread_setspecific() returned error"); + } + else + { + ret = pthread_setspecific( key, (void *)0xAAAAAAAA ); + CYG_TEST_CHECK( ret == 0, "pthread_setspecific() returned error"); + } +} + +//-------------------------------------------------------------------------- + +void *pthread_entry( void *arg) +{ + int ret; + int retval = 1; + void *val; + + CYG_TEST_INFO( "Thread running" ); + + ret = pthread_setspecific( key, arg ); + CYG_TEST_CHECK( ret == 0, "pthread_setspecific() returned error"); + + val = pthread_getspecific( key ); + CYG_TEST_CHECK( val == arg, "pthread_getspecific() did not return expected value"); + if( val != arg ) retval = 0; + + sched_yield(); + + val = pthread_getspecific( key ); + CYG_TEST_CHECK( val == arg, "pthread_getspecific() did not return expected value"); + if( val != arg ) retval = 0; + + pthread_exit( (void *)retval ); +} + +//-------------------------------------------------------------------------- + +int main(int argc, char **argv) +{ + int i; + int ret; + void *retval[2]; + + CYG_TEST_INIT(); + + // allocate data key + ret = pthread_key_create( &key, key_destructor ); + CYG_TEST_CHECK( ret == 0, "pthread_key_create() returned error"); + + // Create test threads + for( i = 0; i < 2; i++ ) + { + pthread_attr_t attr; + pthread_attr_init( &attr ); + + pthread_attr_setstackaddr( &attr, (void *)&thread_stack[i][sizeof(thread_stack[i])] ); + pthread_attr_setstacksize( &attr, sizeof(thread_stack[i]) ); + + ret = pthread_create( &thread[i], + &attr, + pthread_entry, + (void *)(0x12340000+i)); + CYG_TEST_CHECK( ret == 0, "pthread_create() returned error"); + } + + // Now join with threads + for( i = 0; i < 2; i++ ) + pthread_join( thread[i], &retval[i] ); + + + ret = pthread_key_delete( key ); + CYG_TEST_CHECK( ret == 0, "pthread_key_delete() returned error"); + + // check retvals + + for( i = 0; i < 2; i++ ) + if( !(long)retval[0] ) + CYG_TEST_FAIL_FINISH( "pthread2" ); + + CYG_TEST_PASS_FINISH( "pthread2" ); + +} + +#endif + +//-------------------------------------------------------------------------- +// end of pthread2.c diff --git a/packages/compat/posix/v2_0/tests/pthread3.c b/packages/compat/posix/v2_0/tests/pthread3.c new file mode 100644 index 00000000..1f61960c --- /dev/null +++ b/packages/compat/posix/v2_0/tests/pthread3.c @@ -0,0 +1,269 @@ +//========================================================================== +// +// pthread3.cxx +// +// POSIX pthread test 2 - cancellation +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg, jlarmour +// Date: 2000-04-10 +// Description: Tests POSIX cancellation. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#ifndef CYGPKG_POSIX_PTHREAD +#define NA_MSG "POSIX threads not enabled" +#endif + +#ifdef NA_MSG +void +cyg_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(NA_MSG); +} +#else + +#include +#include +#include // sleep() + +//-------------------------------------------------------------------------- +// Thread info + +#define NTHREADS 3 + +char thread_stack[NTHREADS][PTHREAD_STACK_MIN*2]; + +pthread_t thread[NTHREADS]; + +void *pthread_entry1( void *arg); +void *pthread_entry2( void *arg); +void *pthread_entry3( void *arg); + +void *(*pthread_entry[NTHREADS])(void *) = +{ + pthread_entry1, + pthread_entry2, + pthread_entry3 +}; + +//-------------------------------------------------------------------------- + +volatile cyg_bool cancel_handler1_called = false; +volatile cyg_bool cancel_handler2_called = false; +volatile cyg_bool cancel_handler3_called = false; +volatile cyg_bool thread_ready[NTHREADS]; + +//-------------------------------------------------------------------------- + +void cancel_handler1( void * arg ) +{ + CYG_TEST_INFO( "cancel_handler1 called" ); + + CYG_TEST_CHECK( (long)arg == 0x12340000, "cancel_handler1: bad arg value"); + + cancel_handler1_called = true; +} + +//-------------------------------------------------------------------------- + +void cancel_handler2( void * arg ) +{ + CYG_TEST_INFO( "cancel_handler2 called" ); + + CYG_TEST_CHECK( (long)arg == 0xFFFF1111, "cancel_handler2: bad arg value"); + + cancel_handler2_called = true; +} + +//-------------------------------------------------------------------------- + +void cancel_handler3( void * arg ) +{ + CYG_TEST_INFO( "cancel_handler3 called" ); + + CYG_TEST_CHECK( (long)arg == 0x12340001, "cancel_handler3: bad arg value"); + + cancel_handler3_called = true; +} + +//-------------------------------------------------------------------------- + +void function1(void) +{ + + pthread_cleanup_push( cancel_handler2, (void *)0xFFFF1111 ); + + for(;;) + { + sched_yield(); + pthread_testcancel(); + } + + pthread_cleanup_pop( 0 ); +} + +//-------------------------------------------------------------------------- + +void *pthread_entry1( void *arg) +{ + int retval = 1; + + CYG_TEST_INFO( "pthread_entry1 entered"); + + pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, NULL ); + + pthread_cleanup_push( cancel_handler1, arg ); + + thread_ready[0] = true; + + function1(); + + pthread_cleanup_pop( 0 ); + + pthread_exit( (void *)retval ); +} + +//-------------------------------------------------------------------------- + +void *pthread_entry2( void *arg) +{ + int retval = 1; + + CYG_TEST_INFO( "pthread_entry2 entered"); + + pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL ); + + pthread_cleanup_push( cancel_handler3, arg ); + + thread_ready[1] = true; + + for(;;) sched_yield(); + + pthread_cleanup_pop( 0 ); + + pthread_exit( (void *)retval ); +} + +//-------------------------------------------------------------------------- + +void *pthread_entry3( void *arg) +{ + int retval = 1; + + CYG_TEST_INFO( "pthread_entry3 entered"); + + pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, NULL ); + + thread_ready[2] = true; + + // stop in a cancellation point + sleep( 99999 ); + + pthread_exit( (void *)retval ); +} + +//-------------------------------------------------------------------------- + +int main(int argc, char **argv) +{ + int i, j; + int ret; + void *retval[NTHREADS]; + + CYG_TEST_INIT(); + + // Create test threads + for( i = 0; i < NTHREADS; i++ ) + { + pthread_attr_t attr; + pthread_attr_init( &attr ); + + pthread_attr_setstackaddr( &attr, (void *)&thread_stack[i][sizeof(thread_stack[i])] ); + pthread_attr_setstacksize( &attr, sizeof(thread_stack[i]) ); + + ret = pthread_create( &thread[i], + &attr, + pthread_entry[i], + (void *)(0x12340000+i)); + CYG_TEST_CHECK( ret == 0, "pthread_create() returned error"); + } + + // Let the threads get going + for ( i = 0; i < NTHREADS ; i++ ) { + while ( thread_ready[i] == false ) + sched_yield(); + } + + // Now wait a bit to be sure that the other threads have reached + // their cancellation points. + for ( j = 0; j < 20 ; j++ ) + sched_yield(); + + // Now cancel them + for( i = 0; i < NTHREADS; i++ ) + pthread_cancel( thread[i] ); + + // Now join with threads + for( i = 0; i < NTHREADS; i++ ) + pthread_join( thread[i], &retval[i] ); + + + // check retvals + for( i = 0; i < NTHREADS; i++ ) + CYG_TEST_CHECK( retval[i] == PTHREAD_CANCELED, + "thread didn't exit with PTHREAD_CANCELED" ); + + CYG_TEST_CHECK( cancel_handler1_called, "cancel_handler1 not called" ); + CYG_TEST_CHECK( cancel_handler2_called, "cancel_handler2 not called" ); + CYG_TEST_CHECK( cancel_handler3_called, "cancel_handler3 not called" ); + + CYG_TEST_PASS_FINISH( "pthread3" ); + +} + +#endif + +//-------------------------------------------------------------------------- +// end of pthread3.c diff --git a/packages/compat/posix/v2_0/tests/signal1.c b/packages/compat/posix/v2_0/tests/signal1.c new file mode 100644 index 00000000..f414c28a --- /dev/null +++ b/packages/compat/posix/v2_0/tests/signal1.c @@ -0,0 +1,302 @@ +//========================================================================== +// +// signal1.cxx +// +// POSIX signal test 1 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-04-10 +// Description: Tests POSIX signal functionality. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#if !defined(CYGPKG_POSIX_SIGNALS) +#define NA_MSG "POSIX signals not enabled" +#elif !defined(CYGPKG_POSIX_PTHREAD) +#define NA_MSG "POSIX threads not enabled" +#endif + +#ifdef NA_MSG +void +cyg_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(NA_MSG); +} +#else + +#include +#include +#include +#include +#include + +//-------------------------------------------------------------------------- +// Thread stack. + +char thread_stack[PTHREAD_STACK_MIN*2]; + +//-------------------------------------------------------------------------- +// Local variables + +// Sync semaphore +sem_t sem; + +// Thread ID +pthread_t thread1; + +volatile int sigusr2_called = 0; +volatile int sigalrm_called = 0; + +//-------------------------------------------------------------------------- +// Signal handler functions + +static void sigusr2( int signo ) +{ + CYG_TEST_INFO( "sigusr2() handler called" ); + CYG_TEST_CHECK( signo == SIGUSR2, "Signal not SIGUSR2"); + CYG_TEST_CHECK( pthread_equal(pthread_self(), thread1), "Not called in thread1"); + + sigusr2_called++; +} + +static void sigalrm( int signo ) +{ + CYG_TEST_INFO( "sigalrm() handler called" ); + CYG_TEST_CHECK( signo == SIGALRM, "Signal not SIGALRM"); + CYG_TEST_CHECK( pthread_equal(pthread_self(), thread1), "Not called in thread1"); + + sigalrm_called++; +} + +//-------------------------------------------------------------------------- + +void *pthread_entry1( void *arg) +{ + sigset_t mask; + siginfo_t info; + struct timespec timeout; + int sig, sig2, err; + + CYG_TEST_INFO( "Thread 1 running" ); + + // Should have inherited parent's signal mask + pthread_sigmask( 0, NULL, &mask ); + CYG_TEST_CHECK( sigismember( &mask, SIGALRM), + "SIGALRM mask inherited"); + CYG_TEST_CHECK( sigismember( &mask, SIGUSR1), + "SIGUSR1 mask inherited"); + CYG_TEST_CHECK( sigismember( &mask, SIGUSR2), + "SIGUSR2 mask inherited"); + CYG_TEST_CHECK( sigismember( &mask, SIGSEGV), + "SIGSEGV mask inherited"); + + // Make a full set + sigfillset( &mask ); + + // remove USR2 and ALRM signals + sigdelset( &mask, SIGUSR2 ); + sigdelset( &mask, SIGALRM ); + + // Set signal mask + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + + // Get main thread going again + sem_post( &sem ); + + // set up timeout + timeout.tv_sec = 10; + timeout.tv_nsec = 0; + + CYG_TEST_INFO( "Thread1: calling sigtimedwait()"); + + // Wait for a signal to be delivered + sig = sigtimedwait( &mask, &info, &timeout ); + + sig2 = info.si_signo; + + CYG_TEST_CHECK( sig == sig2, "sigtimedwait return value not equal"); + CYG_TEST_CHECK( sig == SIGUSR1, "Signal not delivered"); + + while( sigusr2_called != 2 ) + { + CYG_TEST_INFO( "Thread1: calling pause()"); + pause(); + } + + errno = 0; // strictly correct to reset errno first + + // now wait for SIGALRM to be delivered + CYG_TEST_INFO( "Thread1: calling pause()"); + err = pause(); + CYG_TEST_CHECK( -1==err, "pause returned -1"); + CYG_TEST_CHECK( EINTR==errno, "errno set to EINTR"); + + // generate another SIGALRM and wait for it to be delivered too + // we need to mask it first though + + // Make a full set + sigfillset( &mask ); + + // Set signal mask + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + + alarm(1); + CYG_TEST_INFO( "Thread1: calling sigwait()"); + err = sigwait( &mask, &sig); + CYG_TEST_CHECK( 0==err, "sigwait returned -1"); + CYG_TEST_CHECK( sig==SIGALRM, "sigwait caught alarm"); + + CYG_TEST_INFO( "Thread1: calling pthread_exit()"); + pthread_exit( (void *)((int)arg+sig2) ); +} + +//-------------------------------------------------------------------------- + +int main(int argc, char **argv) +{ + int ret; + sigset_t mask; + pthread_attr_t attr; + void *retval; + union sigval value; + + CYG_TEST_INIT(); + + // Make a full signal set + sigfillset( &mask ); + + + // Install signal handlers + { + struct sigaction sa; + + sa.sa_handler = sigusr2; + sa.sa_mask = mask; + sa.sa_flags = 0; + + ret = sigaction( SIGUSR2, &sa, NULL ); + + CYG_TEST_CHECK( ret == 0 , "sigaction returned error"); + } + + { + struct sigaction sa; + + sa.sa_handler = sigalrm; + sa.sa_mask = mask; + sa.sa_flags = 0; + + ret = sigaction( SIGALRM, &sa, NULL ); + + CYG_TEST_CHECK( ret == 0 , "sigaction returned error"); + } + + + // Mask all signals + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + + sem_init( &sem, 0, 0 ); + + // Create test thread + pthread_attr_init( &attr ); + + pthread_attr_setstackaddr( &attr, (void *)&thread_stack[sizeof(thread_stack)] ); + pthread_attr_setstacksize( &attr, sizeof(thread_stack) ); + + pthread_create( &thread1, + &attr, + pthread_entry1, + (void *)0x12345678); + + // Wait for other thread to get started + CYG_TEST_INFO( "Main: calling sem_wait()"); + sem_wait( &sem ); + + value.sival_int = 0; + + // send a signal to the other thread + CYG_TEST_INFO( "Main: calling sigqueue(SIGUSR1)"); + sigqueue( 0, SIGUSR1, value ); + + // Send the signal via kill + CYG_TEST_INFO( "Main: calling kill(0, SIGUSR2)"); + kill( 0, SIGUSR2 ); + + // Wait for thread1 to call pause() + CYG_TEST_INFO( "Main: calling sleep(1)"); + sleep(1); + + // And again + CYG_TEST_INFO( "Main: calling kill(0, SIGUSR2)"); + kill( 0, SIGUSR2 ); + + // Set up an alarm for 1 second hence + CYG_TEST_INFO( "Main: calling alarm(1)"); + alarm(1); + + // Wait for alarm signal to be delivered to thread1 + CYG_TEST_INFO( "Main: calling sleep(2)"); + sleep(2); + + // Now join with thread1 + CYG_TEST_INFO( "Main: calling pthread_join()"); + pthread_join( thread1, &retval ); + + CYG_TEST_CHECK( sigusr2_called == 2, "SIGUSR2 signal handler not called twice" ); + + CYG_TEST_CHECK( sigalrm_called == 1, "SIGALRM signal handler not called" ); + + // check retval + + if( (long)retval == 0x12345678+SIGUSR1 ) + CYG_TEST_PASS_FINISH( "signal1" ); + else + CYG_TEST_FAIL_FINISH( "signal1" ); +} + +#endif + +//-------------------------------------------------------------------------- +// end of signal1.c diff --git a/packages/compat/posix/v2_0/tests/signal2.c b/packages/compat/posix/v2_0/tests/signal2.c new file mode 100644 index 00000000..358965dc --- /dev/null +++ b/packages/compat/posix/v2_0/tests/signal2.c @@ -0,0 +1,313 @@ +//========================================================================== +// +// signal2.cxx +// +// POSIX signal test 2 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: jlarmour +// Date: 2000-04-10 +// Description: Tests POSIX signal functionality. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include // For exception codes + +#include +#include +#include +#include + +#include + +#include + +#if CYGINT_ISO_SETJMP == 0 +# define NA_MSG "Requires setjmp/longjmp implementation" +#elif !defined(CYGPKG_POSIX_SIGNALS) +# define NA_MSG "POSIX signals not enabled" +#endif + +#ifdef NA_MSG +void +cyg_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( NA_MSG ); +} +#else + +//-------------------------------------------------------------------------- +// Local variables + +static jmp_buf jbuf; + +//-------------------------------------------------------------------------- + +// PowerPC is a special case as it has the alignment exception, but it +// doesn't trigger for this function unless in little-endian mode (although +// the exception exists for other instructions not used by this function so +// CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS will still be defined + +#if defined(CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS) && !(defined(CYGPKG_HAL_POWERPC) && (CYG_BYTEORDER==CYG_MSBFIRST)) + +static void +cause_unaligned_access(void) +{ + volatile int x; + volatile CYG_ADDRESS p=(CYG_ADDRESS) &jbuf; + + x = *(volatile int *)(p+1); + +} // cause_unaligned_access() + +#endif + +//-------------------------------------------------------------------------- + +#ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS + +static void +cause_illegal_access(void) +{ +#ifdef CYGPKG_HAL_I386 + + // In the x86 architecture, although we have the DATA_ACCESS + // exception available, it is not possible to provoke it using the + // normal code of this test. This is because the normal segments we + // have installed in the segment registers cover all of memory. Instead we + // set GS to a descriptor that does not cover 0xF0000000-0xFFFFFFFF and + // poke at that. + + __asm__ ( "movw $0x20,%%ax\n" + "movw %%ax,%%gs\n" + "movl %%gs:0xF0000000,%%eax\n" + : + : + : "eax" + ); + +#else + volatile int x; + volatile CYG_ADDRESS p=(CYG_ADDRESS) &jbuf; + + do + { + x = *(volatile int *)(p); + p += (CYG_ADDRESS)0x100000; + } while( p != (CYG_ADDRESS)&jbuf ); + +#endif +} // cause_illegal_access() + +#endif + +//-------------------------------------------------------------------------- + +#ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO + +// num must always be 0 - do it this way in case the optimizer tries to +// get smart + +static int +cause_fpe(int num) +{ + double a; + + a = 1.0/num; // Depending on FPU emulation and/or + // the FPU architecture, this may + // cause an exception. + // (float division by zero) + + return ((int)a)/num; // This may cause an exception if + // the architecture supports it. + // (integer division by zero). +} // cause_fpe() + +#endif + +//-------------------------------------------------------------------------- +// Signal handler functions + +static void sigsegv( int signo ) +{ + CYG_TEST_INFO( "sigsegv() handler called" ); + CYG_TEST_CHECK( signo == SIGSEGV, "Signal not SIGSEGV"); + + longjmp( jbuf, 1 ); +} + +static void sigbus( int signo ) +{ + CYG_TEST_INFO( "sigbus() handler called" ); + CYG_TEST_CHECK( signo == SIGBUS, "Signal not SIGBUS"); + + longjmp( jbuf, 1 ); +} + +static void sigfpe( int signo ) +{ + CYG_TEST_INFO( "sigfpe() handler called" ); + CYG_TEST_CHECK( signo == SIGFPE, "Signal not SIGFPE"); + + longjmp( jbuf, 1 ); +} + + +//-------------------------------------------------------------------------- + +int main(int argc, char **argv) +{ + int ret; + sigset_t mask; + struct sigaction sa; + + CYG_TEST_INIT(); + + // Make a full signal set + sigfillset( &mask ); + + + // Install signal handlers + + sa.sa_mask = mask; + sa.sa_flags = 0; + + sa.sa_handler = sigsegv; + ret = sigaction( SIGSEGV, &sa, NULL ); + CYG_TEST_CHECK( ret == 0 , "sigaction returned error"); + + sa.sa_handler = sigbus; + ret = sigaction( SIGBUS, &sa, NULL ); + CYG_TEST_CHECK( ret == 0 , "sigaction returned error"); + + sa.sa_handler = sigfpe; + ret = sigaction( SIGFPE, &sa, NULL ); + CYG_TEST_CHECK( ret == 0 , "sigaction returned error"); + + // now make an empty signal set + sigemptyset( &mask ); + +// Now reset the various exception handlers to eCos handlers so that we +// have control; this is the target side equivalent of the CYG_TEST_GDBCMD +// lines above: +#ifdef HAL_VSR_SET_TO_ECOS_HANDLER + // Reclaim the VSR off CygMon possibly +#ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS + HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_ACCESS, NULL ); +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS + HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS, NULL ); +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS + HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS, NULL ); +#endif +#ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION + HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, NULL ); +#endif +#ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO + HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO, NULL ); +#endif +#endif + + // PowerPC is a special case as it has the alignment exception, but it + // doesn't trigger for this function unless in little-endian mode (although + // the exception exists for other instructions not used by this function so + // CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS will still be defined + +#if defined(CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS) && !(defined(CYGPKG_HAL_POWERPC) && (CYG_BYTEORDER==CYG_MSBFIRST)) + + CYG_TEST_INFO("Test 1 - provoke unaligned access"); + + if( setjmp( jbuf ) == 0 ) + { + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + cause_unaligned_access(); + CYG_TEST_FAIL("Didn't cause exception"); + } + +#else + + CYG_TEST_INFO("Test 1 - provoke unaligned access - not supported"); + +#endif + +#ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS + + CYG_TEST_INFO("Test 2 - provoke illegal access"); + + if( setjmp( jbuf ) == 0 ) + { + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + cause_illegal_access(); + CYG_TEST_FAIL("Didn't cause exception"); + } + +#else + + CYG_TEST_INFO("Test 1 - provoke illegal access - not supported"); + +#endif + +#ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO + + CYG_TEST_INFO("Test 3 - provoke FP error"); + + if( setjmp( jbuf ) == 0 ) + { + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + cause_fpe(0); + CYG_TEST_FAIL("Didn't cause exception"); + } + +#else + + CYG_TEST_INFO("Test 3 - provoke FP error - not supported"); + +#endif + + CYG_TEST_PASS_FINISH( "signal2" ); +} + +#endif // ifndef NA_MSG + +//-------------------------------------------------------------------------- +// end of signal1.c diff --git a/packages/compat/posix/v2_0/tests/signal3.c b/packages/compat/posix/v2_0/tests/signal3.c new file mode 100644 index 00000000..58292892 --- /dev/null +++ b/packages/compat/posix/v2_0/tests/signal3.c @@ -0,0 +1,174 @@ +//========================================================================== +// +// signal3.cxx +// +// POSIX signal test 3 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2003-01-30 +// Description: Tests POSIX signal functionality. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#if !defined(CYGPKG_POSIX_SIGNALS) +#define NA_MSG "POSIX signals not enabled" +#elif !defined(CYGPKG_POSIX_PTHREAD) +#define NA_MSG "POSIX threads not enabled" +#endif + +#ifdef NA_MSG +void +cyg_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(NA_MSG); +} +#else + +#include +#include +#include +#include +#include + +volatile int sigusr1_called = 0; + +//-------------------------------------------------------------------------- +// Signal handler functions + +static void sigusr1( int signo ) +{ + CYG_TEST_INFO( "sigusr1() handler called" ); + CYG_TEST_CHECK( signo == SIGUSR1, "Signal not SIGUSR1"); + + sigusr1_called++; +} + +//-------------------------------------------------------------------------- + +int main (int argc, char **argv) +{ + int ret_val; + sigset_t set; + int sig; + struct itimerspec timerValue; // Timeout value on eCos + timer_t timer1; // Timer + struct sigevent sev; + + CYG_TEST_INIT(); + + { + struct sigaction sa; + + sa.sa_handler = sigusr1; + sigfillset( &sa.sa_mask ); + sa.sa_flags = 0; + + ret_val = sigaction( SIGUSR1, &sa, NULL ); + + CYG_TEST_CHECK( ret_val == 0 , "sigaction returned error"); + } + + // unblock all the signals + sigfillset (&set); + pthread_sigmask (SIG_UNBLOCK, &set, (sigset_t*)NULL); + + //-------------------------------------------------------------------- + // + //-------------------------------------------------------------------- + + // Notification type --- Deliver the signal + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGUSR1; + sev.sigev_value.sival_int = 0xABCDEF01; + + // Timer values --- 1 Second + timerValue.it_value.tv_sec = 1; + timerValue.it_value.tv_nsec = 0; + timerValue.it_interval.tv_sec = 1; + timerValue.it_interval.tv_nsec = 0; + + ret_val = timer_create (CLOCK_REALTIME, &sev, &timer1); + + CYG_TEST_CHECK( ret_val==0, "Error in creating the timer"); + + ret_val = timer_settime (timer1, 0, &timerValue, NULL ); + CYG_TEST_CHECK( ret_val==0,"Error in setting the time"); + + //-------------------------------------------------------------------- + // + //-------------------------------------------------------------------- + + CYG_TEST_INFO ("Timer initialisation is completed.."); + + CYG_TEST_INFO ("Calling pause()"); + ret_val = pause(); + CYG_TEST_CHECK( ret_val==-1, "pause() did not return -1"); + CYG_TEST_CHECK( EINTR==errno, "errno set to EINTR"); + CYG_TEST_CHECK( sigusr1_called==1, "Siguser1 handler not called"); + + // Block all the signals + sigfillset (&set); + pthread_sigmask (SIG_BLOCK, &set, (sigset_t*)NULL); + + CYG_TEST_INFO ("Calling sigwait()"); + // Wait for any signal to arrive + sigfillset (&set); + ret_val = sigwait (&set, &sig); + + CYG_TEST_CHECK( ret_val==0, "sigwait returned error"); + CYG_TEST_CHECK( sig==SIGUSR1, "sigwait returned wrong signo!"); + CYG_TEST_CHECK( sigusr1_called==1, "Siguser1 handler called!"); + + CYG_TEST_INFO ("Program terminating"); + + CYG_TEST_PASS_FINISH( "signal3" ); + return 0; +} + + +#endif + +//-------------------------------------------------------------------------- +// end of signal3.c diff --git a/packages/compat/posix/v2_0/tests/sigsetjmp.c b/packages/compat/posix/v2_0/tests/sigsetjmp.c new file mode 100644 index 00000000..6fd0f118 --- /dev/null +++ b/packages/compat/posix/v2_0/tests/sigsetjmp.c @@ -0,0 +1,383 @@ +//========================================================================== +// +// sigsetjmp.c +// +// POSIX sigsetjmp test +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-04-10 +// Description: Tests POSIX sigsetjmp functionality. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#if !defined(CYGPKG_POSIX_SIGNALS) +#define NA_MSG "POSIX signals not enabled" +#elif !defined(CYGPKG_POSIX_PTHREAD) +#define NA_MSG "POSIX threads not enabled" +#endif + +#ifdef NA_MSG +void +cyg_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(NA_MSG); +} +#else + +#include +#include +#include +#include +#include +#include + +#include + +//-------------------------------------------------------------------------- +// Thread stack. + +char thread1_stack[PTHREAD_STACK_MIN*2]; +char thread2_stack[PTHREAD_STACK_MIN*2]; + +//-------------------------------------------------------------------------- +// Local variables + +// Sync semaphore +sem_t sem; + +// Thread IDs +pthread_t thread1; +pthread_t thread2; + +timer_t timer1; +timer_t timer2; + +volatile int sigusr1_called = 0; +volatile int sigusr2_called = 0; + +sigjmp_buf jmpbuf1; +sigjmp_buf jmpbuf2; + +//-------------------------------------------------------------------------- +// Signal handler functions + +static void sigusr1( int signo, siginfo_t *info, void *context ) +{ + CYG_TEST_INFO( "sigusr1() handler called" ); + CYG_TEST_CHECK( signo == SIGUSR1, "Signal not SIGUSR1"); + CYG_TEST_CHECK( signo == info->si_signo, "Bad signal number in siginfo" ); + CYG_TEST_CHECK( info->si_code == SI_TIMER, "Siginfo code not SI_TIMER" ); + CYG_TEST_CHECK( info->si_value.sival_int == 0xABCDEF01, "Siginfo value wrong"); + CYG_TEST_CHECK( pthread_equal(pthread_self(), thread1), "Not called in thread1"); + + sigusr1_called++; + + CYG_TEST_INFO( "sigusr1() handler calling siglongjmp()" ); + + siglongjmp( jmpbuf1, sigusr1_called ); +} + +static void sigusr2( int signo, siginfo_t *info, void *context ) +{ + CYG_TEST_INFO( "sigusr2() handler called" ); + CYG_TEST_CHECK( signo == SIGUSR2, "Signal not SIGUSR2"); + CYG_TEST_CHECK( signo == info->si_signo, "Bad signal number in siginfo" ); + CYG_TEST_CHECK( info->si_code == SI_TIMER, "Siginfo code not SI_TIMER" ); + CYG_TEST_CHECK( info->si_value.sival_int == 0xABCDEF02, "Siginfo value wrong"); + CYG_TEST_CHECK( pthread_equal(pthread_self(), thread2), "Not called in thread2"); + + sigusr2_called++; + + CYG_TEST_INFO( "sigusr2() handler calling siglongjmp()" ); + siglongjmp( jmpbuf2, sigusr2_called ); +} + +//-------------------------------------------------------------------------- + +void *pthread_entry1( void *arg) +{ + sigset_t mask; + + + CYG_TEST_INFO( "Thread 1 running" ); + + // Make a full set + sigfillset( &mask ); + + // remove USR1 signal + sigdelset( &mask, SIGUSR1 ); + + // Set signal mask + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + + // Get main thread going again + sem_post( &sem ); + + do + { + sigset_t curmask; + + CYG_TEST_INFO( "Thread1: calling sigsetjmp()"); + if( sigsetjmp( jmpbuf1, 1 ) != 0 ) + CYG_TEST_INFO( "Thread1: sigsetjmp() returned non-zero"); + + pthread_sigmask( SIG_SETMASK, NULL, &curmask ); + CYG_TEST_CHECK( curmask == mask, "Thread1: Signal masks not equal" ); + + if ( sigusr1_called >= 1 ) + break; + + CYG_TEST_INFO( "Thread1: calling pause()"); + pause(); + + CYG_TEST_INFO( "Thread1: pause() returned"); + } while(1); + + CYG_TEST_INFO( "Thread1: calling pthread_exit()"); + pthread_exit( arg ); +} + +//-------------------------------------------------------------------------- + +void *pthread_entry2( void *arg) +{ + sigset_t mask; + + CYG_TEST_INFO( "Thread 2 running" ); + + // Make a full set + sigfillset( &mask ); + + // remove USR2 signal + sigdelset( &mask, SIGUSR2 ); + + // Set signal mask + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + + // Get main thread going again + sem_post( &sem ); + + do + { + sigset_t curmask; + + CYG_TEST_INFO( "Thread2: calling sigsetjmp()"); + if( sigsetjmp( jmpbuf2, 1 ) != 0 ) + CYG_TEST_INFO( "Thread2: sigsetjmp() returned non-zero"); + + pthread_sigmask( SIG_SETMASK, NULL, &curmask ); + CYG_TEST_CHECK( curmask == mask, "Thread2: Signal masks not equal" ); + + if ( sigusr2_called >= 6 ) + break; + + CYG_TEST_INFO( "Thread2: calling pause()"); + pause(); + + CYG_TEST_INFO( "Thread2: pause() returned"); + } while(1); + + CYG_TEST_INFO( "Thread2: calling pthread_exit()"); + pthread_exit( arg ); +} + +//-------------------------------------------------------------------------- + +int main(int argc, char **argv) +{ + int ret; + sigset_t mask; + pthread_attr_t attr; + void *retval; + + CYG_TEST_INIT(); + + // Make a full signal set + sigfillset( &mask ); + + + // Install signal handlers + { + struct sigaction sa; + + sa.sa_sigaction = sigusr1; + sa.sa_mask = mask; + sa.sa_flags = SA_SIGINFO; + + ret = sigaction( SIGUSR1, &sa, NULL ); + + CYG_TEST_CHECK( ret == 0 , "sigaction returned error"); + } + { + struct sigaction sa; + + sa.sa_sigaction = sigusr2; + sa.sa_mask = mask; + sa.sa_flags = SA_SIGINFO; + + ret = sigaction( SIGUSR2, &sa, NULL ); + + CYG_TEST_CHECK( ret == 0 , "sigaction returned error"); + } + + + // Create the timers + + { + struct sigevent sev; + struct itimerspec value; + + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGUSR1; + sev.sigev_value.sival_int = 0xABCDEF01; + + value.it_value.tv_sec = 1; + value.it_value.tv_nsec = 0; + value.it_interval.tv_sec = 0; + value.it_interval.tv_nsec = 0; + + ret = timer_create( CLOCK_REALTIME, &sev, &timer1 ); + + CYG_TEST_CHECK( ret == 0 , "timer_create returned error"); + + ret = timer_settime( timer1, 0, &value, NULL ); + + CYG_TEST_CHECK( ret == 0 , "timer_settime returned error"); + } + + { + struct sigevent sev; + struct itimerspec value; + + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGUSR2; + sev.sigev_value.sival_int = 0xABCDEF02; + + value.it_value.tv_sec = 0; + value.it_value.tv_nsec = 500000000; + value.it_interval.tv_sec = 0; + value.it_interval.tv_nsec = 250000000; + + ret = timer_create( CLOCK_REALTIME, &sev, &timer2 ); + + CYG_TEST_CHECK( ret == 0 , "timer_create returned error"); + + ret = timer_settime( timer2, 0, &value, NULL ); + + CYG_TEST_CHECK( ret == 0 , "timer_settime returned error"); + } + + + // Mask all signals + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + + sem_init( &sem, 0, 0 ); + + // Create test threads + + { + pthread_attr_init( &attr ); + + pthread_attr_setstackaddr( &attr, (void *)&thread1_stack[sizeof(thread1_stack)] ); + pthread_attr_setstacksize( &attr, sizeof(thread1_stack) ); + + pthread_create( &thread1, + &attr, + pthread_entry1, + (void *)0x12345671); + } + + { + pthread_attr_init( &attr ); + + pthread_attr_setstackaddr( &attr, (void *)&thread2_stack[sizeof(thread2_stack)] ); + pthread_attr_setstacksize( &attr, sizeof(thread2_stack) ); + + pthread_create( &thread2, + &attr, + pthread_entry2, + (void *)0x12345672); + } + + // Wait for other thread to get started + CYG_TEST_INFO( "Main: calling sem_wait()"); + sem_wait( &sem ); + CYG_TEST_INFO( "Main: calling sem_wait() again"); + sem_wait( &sem ); + + // Now join with thread1 + CYG_TEST_INFO( "Main: calling pthread_join(thread1)"); + pthread_join( thread1, &retval ); + + CYG_TEST_CHECK( retval == (void *)0x12345671, "Thread 1 retval wrong"); + + // And thread 2 + CYG_TEST_INFO( "Main: calling pthread_join(thread2)"); + pthread_join( thread2, &retval ); + + // now delete the timers + CYG_TEST_INFO( "Main: calling timer_delete(timer1)"); + ret = timer_delete( timer1 ); + + CYG_TEST_CHECK( ret == 0 , "timer_delete(timer1) returned error"); + + CYG_TEST_INFO( "Main: calling timer_delete(timer2)"); + ret = timer_delete( timer2 ); + + CYG_TEST_CHECK( ret == 0 , "timer_delete(timer2) returned error"); + + + CYG_TEST_CHECK( retval == (void *)0x12345672, "Thread 2 retval wrong"); + + CYG_TEST_CHECK( sigusr1_called == 1, "SIGUSR1 signal handler not called once" ); + CYG_TEST_CHECK( sigusr2_called == 6, "SIGUSR2 signal handler not called six times" ); + + CYG_TEST_PASS_FINISH( "sigsetjmp" ); +} + +#endif + +//-------------------------------------------------------------------------- +// end of sigsetjmp.c diff --git a/packages/compat/posix/v2_0/tests/timer1.c b/packages/compat/posix/v2_0/tests/timer1.c new file mode 100644 index 00000000..38d22b5e --- /dev/null +++ b/packages/compat/posix/v2_0/tests/timer1.c @@ -0,0 +1,343 @@ +//========================================================================== +// +// timer1.cxx +// +// POSIX signal test 1 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-04-10 +// Description: Tests POSIX signal functionality. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#ifndef CYGPKG_POSIX_SIGNALS +#define NA_MSG "No POSIX signals" +#elif !defined(CYGPKG_POSIX_TIMERS) +#define NA_MSG "No POSIX timers" +#endif + +#ifdef NA_MSG +void +cyg_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(NA_MSG); +} +#else + +#include +#include +#include +#include +#include + +//-------------------------------------------------------------------------- +// Thread stack. + +char thread1_stack[PTHREAD_STACK_MIN*2]; +char thread2_stack[PTHREAD_STACK_MIN*2]; + +//-------------------------------------------------------------------------- +// Local variables + +// Sync semaphore +sem_t sem; + +// Thread IDs +pthread_t thread1; +pthread_t thread2; + +timer_t timer1; +timer_t timer2; + +volatile int sigusr1_called = 0; +volatile int sigusr2_called = 0; + +//-------------------------------------------------------------------------- +// Signal handler functions + +static void sigusr1( int signo, siginfo_t *info, void *context ) +{ + CYG_TEST_INFO( "sigusr1() handler called" ); + CYG_TEST_CHECK( signo == SIGUSR1, "Signal not SIGUSR1"); + CYG_TEST_CHECK( signo == info->si_signo, "Bad signal number in siginfo" ); + CYG_TEST_CHECK( info->si_code == SI_TIMER, "Siginfo code not SI_TIMER" ); + CYG_TEST_CHECK( info->si_value.sival_int == 0xABCDEF01, "Siginfo value wrong"); + CYG_TEST_CHECK( pthread_equal(pthread_self(), thread1), "Not called in thread1"); + + sigusr1_called++; +} + +static void sigusr2( int signo, siginfo_t *info, void *context ) +{ + CYG_TEST_INFO( "sigusr2() handler called" ); + CYG_TEST_CHECK( signo == SIGUSR2, "Signal not SIGUSR2"); + CYG_TEST_CHECK( signo == info->si_signo, "Bad signal number in siginfo" ); + CYG_TEST_CHECK( info->si_code == SI_TIMER, "Siginfo code not SI_TIMER" ); + CYG_TEST_CHECK( info->si_value.sival_int == 0xABCDEF02, "Siginfo value wrong"); + CYG_TEST_CHECK( pthread_equal(pthread_self(), thread2), "Not called in thread2"); + + sigusr2_called++; +} + +//-------------------------------------------------------------------------- + +void *pthread_entry1( void *arg) +{ + sigset_t mask; + + + CYG_TEST_INFO( "Thread 1 running" ); + + // Make a full set + sigfillset( &mask ); + + // remove USR1 signal + sigdelset( &mask, SIGUSR1 ); + + // Set signal mask + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + + // Get main thread going again + sem_post( &sem ); + + while( sigusr1_called < 1 ) + { + CYG_TEST_INFO( "Thread1: calling pause()"); + pause(); + } + + CYG_TEST_INFO( "Thread1: calling pthread_exit()"); + pthread_exit( arg ); +} + +//-------------------------------------------------------------------------- + +void *pthread_entry2( void *arg) +{ + sigset_t mask; + + CYG_TEST_INFO( "Thread 2 running" ); + + // Make a full set + sigfillset( &mask ); + + // remove USR2 signal + sigdelset( &mask, SIGUSR2 ); + + // Set signal mask + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + + // Get main thread going again + sem_post( &sem ); + + while( sigusr2_called < 6 ) + { + CYG_TEST_INFO( "Thread2: calling pause()"); + pause(); + } + + CYG_TEST_INFO( "Thread2: calling pthread_exit()"); + pthread_exit( arg ); +} + +//-------------------------------------------------------------------------- + +int main(int argc, char **argv) +{ + int ret; + sigset_t mask; + pthread_attr_t attr; + void *retval; + + CYG_TEST_INIT(); + + // Make a full signal set + sigfillset( &mask ); + + + // Install signal handlers + { + struct sigaction sa; + + sa.sa_sigaction = sigusr1; + sa.sa_mask = mask; + sa.sa_flags = SA_SIGINFO; + + ret = sigaction( SIGUSR1, &sa, NULL ); + + CYG_TEST_CHECK( ret == 0 , "sigaction returned error"); + } + { + struct sigaction sa; + + sa.sa_sigaction = sigusr2; + sa.sa_mask = mask; + sa.sa_flags = SA_SIGINFO; + + ret = sigaction( SIGUSR2, &sa, NULL ); + + CYG_TEST_CHECK( ret == 0 , "sigaction returned error"); + } + + + // Create the timers + + { + struct sigevent sev; + struct itimerspec value; + + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGUSR1; + sev.sigev_value.sival_int = 0xABCDEF01; + + value.it_value.tv_sec = 1; + value.it_value.tv_nsec = 0; + value.it_interval.tv_sec = 0; + value.it_interval.tv_nsec = 0; + + ret = timer_create( CLOCK_REALTIME, &sev, &timer1 ); + + CYG_TEST_CHECK( ret == 0 , "timer_create returned error"); + + ret = timer_settime( timer1, 0, &value, NULL ); + + CYG_TEST_CHECK( ret == 0 , "timer_settime returned error"); + } + +#if 1 + { + struct sigevent sev; + struct itimerspec value; + + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGUSR2; + sev.sigev_value.sival_int = 0xABCDEF02; + + value.it_value.tv_sec = 0; + value.it_value.tv_nsec = 500000000; + value.it_interval.tv_sec = 0; + value.it_interval.tv_nsec = 250000000; + + ret = timer_create( CLOCK_REALTIME, &sev, &timer2 ); + + CYG_TEST_CHECK( ret == 0 , "timer_create returned error"); + + ret = timer_settime( timer2, 0, &value, NULL ); + + CYG_TEST_CHECK( ret == 0 , "timer_settime returned error"); + } +#endif + + // Mask all signals + pthread_sigmask( SIG_SETMASK, &mask, NULL ); + + sem_init( &sem, 0, 0 ); + + // Create test threads + + { + pthread_attr_init( &attr ); + + pthread_attr_setstackaddr( &attr, (void *)&thread1_stack[sizeof(thread1_stack)] ); + pthread_attr_setstacksize( &attr, sizeof(thread1_stack) ); + + pthread_create( &thread1, + &attr, + pthread_entry1, + (void *)0x12345671); + } + + { + pthread_attr_init( &attr ); + + pthread_attr_setstackaddr( &attr, (void *)&thread2_stack[sizeof(thread2_stack)] ); + pthread_attr_setstacksize( &attr, sizeof(thread2_stack) ); + + pthread_create( &thread2, + &attr, + pthread_entry2, + (void *)0x12345672); + } + + // Wait for other thread to get started + CYG_TEST_INFO( "Main: calling sem_wait()"); + sem_wait( &sem ); + CYG_TEST_INFO( "Main: calling sem_wait() again"); + sem_wait( &sem ); + + // Now join with thread1 + CYG_TEST_INFO( "Main: calling pthread_join(thread1)"); + pthread_join( thread1, &retval ); + + CYG_TEST_CHECK( retval == (void *)0x12345671, "Thread 1 retval wrong"); + + // And thread 2 + CYG_TEST_INFO( "Main: calling pthread_join(thread2)"); + pthread_join( thread2, &retval ); + + // now delete the timers + CYG_TEST_INFO( "Main: calling timer_delete(timer1)"); + ret = timer_delete( timer1 ); + + CYG_TEST_CHECK( ret == 0 , "timer_delete(timer1) returned error"); + + CYG_TEST_INFO( "Main: calling timer_delete(timer2)"); + ret = timer_delete( timer2 ); + + CYG_TEST_CHECK( ret == 0 , "timer_delete(timer2) returned error"); + + + CYG_TEST_CHECK( retval == (void *)0x12345672, "Thread 2 retval wrong"); + + CYG_TEST_CHECK( sigusr1_called == 1, "SIGUSR1 signal handler not called once" ); + CYG_TEST_CHECK( sigusr2_called == 6, "SIGUSR2 signal handler not called six times" ); + + CYG_TEST_PASS_FINISH( "timer1" ); +} + +#endif + +//-------------------------------------------------------------------------- +// end of timer1.c diff --git a/packages/compat/posix/v2_0/tests/tm_basic.cxx b/packages/compat/posix/v2_0/tests/tm_basic.cxx new file mode 100644 index 00000000..1f8d9521 --- /dev/null +++ b/packages/compat/posix/v2_0/tests/tm_basic.cxx @@ -0,0 +1,1696 @@ +//========================================================================== +// +// tm_basic.cxx +// +// Basic timing test / scaffolding +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2002 Jonathan Larmour +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas,nickg +// Contributors: jlarmour +// Date: 1998-10-19 +// Description: Very simple kernel timing test +//####DESCRIPTIONEND#### +//========================================================================== + + +#include +#include +#include +#include +#ifdef CYGPKG_KERNEL +#include +#endif + +#ifndef CYGPKG_POSIX_SIGNALS +#define NA_MSG "No POSIX signals" +#elif !defined(CYGPKG_POSIX_TIMERS) +#define NA_MSG "No POSIX timers" +#elif !defined(CYGPKG_POSIX_PTHREAD) +#define NA_MSG "POSIX threads not enabled" +#elif !defined(CYGFUN_KERNEL_API_C) +#define NA_MSG "Kernel C API not enabled" +#elif !defined(CYGSEM_KERNEL_SCHED_MLQUEUE) +#define NA_MSG "Kernel mlqueue scheduler not enabled" +#elif !defined(CYGVAR_KERNEL_COUNTERS_CLOCK) +#define NA_MSG "Kernel clock not enabled" +#elif CYGNUM_KERNEL_SCHED_PRIORITIES <= 12 +#define NA_MSG "Kernel scheduler properties <= 12" +#endif + +//========================================================================== + +#ifdef NA_MSG +extern "C" void +cyg_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(NA_MSG); +} +#else + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include CYGHWR_MEMORY_LAYOUT_H + + +// POSIX headers + +#include +#include +#include +#include +#include +#include + +//========================================================================== +// Define this to see the statistics with the first sample datum removed. +// This can expose the effects of caches on the speed of operations. + +#undef STATS_WITHOUT_FIRST_SAMPLE + +//========================================================================== + +// Structure used to keep track of times +typedef struct fun_times { + cyg_uint32 start; + cyg_uint32 end; +} fun_times; + +//========================================================================== + +#define STACK_SIZE (PTHREAD_STACK_MIN*2) + +// Defaults +#define NTEST_THREADS 16 +#define NMUTEXES 32 +#define NMBOXES 32 +#define NSEMAPHORES 32 +#define NTIMERS 32 + + +#define NSAMPLES 32 +#define NTHREAD_SWITCHES 128 +#define NSCHEDS 128 + +#define NSAMPLES_SIM 2 +#define NTEST_THREADS_SIM 2 +#define NTHREAD_SWITCHES_SIM 4 +#define NMUTEXES_SIM 2 +#define NMBOXES_SIM 2 +#define NSEMAPHORES_SIM 2 +#define NSCHEDS_SIM 4 +#define NTIMERS_SIM 2 + +//========================================================================== + +static int nsamples; +static int ntest_threads; +static int nthread_switches; +static int nmutexes; +static int nmboxes; +static int nsemaphores; +static int nscheds; +static int ntimers; + +static char stacks[NTEST_THREADS][STACK_SIZE]; +static pthread_t threads[NTEST_THREADS]; +static int overhead; +static sem_t synchro; +static fun_times thread_ft[NTEST_THREADS]; + +static fun_times test2_ft[NTHREAD_SWITCHES]; + +static pthread_mutex_t test_mutexes[NMUTEXES]; +static fun_times mutex_ft[NMUTEXES]; +static pthread_t mutex_test_thread_handle; + +#if 0 +static cyg_mbox test_mboxes[NMBOXES]; +static cyg_handle_t test_mbox_handles[NMBOXES]; +static fun_times mbox_ft[NMBOXES]; +static cyg_thread mbox_test_thread; +static cyg_handle_t mbox_test_thread_handle; +#endif + +static sem_t test_semaphores[NSEMAPHORES]; +static fun_times semaphore_ft[NSEMAPHORES]; +static pthread_t semaphore_test_thread_handle; + +static fun_times sched_ft[NSCHEDS]; + +static timer_t timers[NTIMERS]; +static fun_times timer_ft[NTIMERS]; + +static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION; +static long ns_per_system_clock; + +#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) +// Data kept by kernel real time clock measuring clock interrupt latency +extern cyg_tick_count total_clock_latency, total_clock_interrupts; +extern cyg_int32 min_clock_latency, max_clock_latency; +extern bool measure_clock_latency; +#endif + +#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_DSR_LATENCY) +extern cyg_tick_count total_clock_dsr_latency, total_clock_dsr_calls; +extern cyg_int32 min_clock_dsr_latency, max_clock_dsr_latency; +extern bool measure_clock_latency; +#endif + +//========================================================================== + +void run_sched_tests(void); +void run_thread_tests(void); +void run_thread_switch_test(void); +void run_mutex_tests(void); +void run_mutex_circuit_test(void); +void run_mbox_tests(void); +void run_mbox_circuit_test(void); +void run_semaphore_tests(void); +void run_semaphore_circuit_test(void); +void run_timer_tests(void); + +//========================================================================== + +#ifndef max +#define max(n,m) (m > n ? n : m) +#endif + +//========================================================================== +// Wait until a clock tick [real time clock] has passed. This should keep it +// from happening again during a measurement, thus minimizing any fluctuations +void +wait_for_tick(void) +{ + cyg_tick_count_t tv0, tv1; + tv0 = cyg_current_time(); + while (true) { + tv1 = cyg_current_time(); + if (tv1 != tv0) break; + } +} + +//-------------------------------------------------------------------------- +// Display a number of ticks as microseconds +// Note: for improved calculation significance, values are kept in ticks*1000 +void +show_ticks_in_us(cyg_uint32 ticks) +{ + long long ns; + ns = (ns_per_system_clock * (long long)ticks) / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; + ns += 5; // for rounding to .01us + diag_printf("%5d.%02d", (int)(ns/1000), (int)((ns%1000)/10)); +} + +//-------------------------------------------------------------------------- +// +// If the kernel is instrumented to measure clock interrupt latency, these +// measurements can be drastically perturbed by printing via "diag_printf()" +// since that code may run with interrupts disabled for long periods. +// +// In order to get accurate/reasonable latency figures _for the kernel +// primitive functions beint tested_, the kernel's latency measurements +// are suspended while the printing actually takes place. +// +// The measurements are reenabled after the printing, thus allowing for +// fair measurements of the kernel primitives, which are not distorted +// by the printing mechanisms. + +#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY) +void +disable_clock_latency_measurement(void) +{ + wait_for_tick(); + measure_clock_latency = false; +} + +void +enable_clock_latency_measurement(void) +{ + wait_for_tick(); + measure_clock_latency = true; +} + +// Ensure that the measurements are reasonable (no startup anomalies) +void +reset_clock_latency_measurement(void) +{ + disable_clock_latency_measurement(); + total_clock_latency = 0; + total_clock_interrupts = 0; + min_clock_latency = 0x7FFFFFFF; + max_clock_latency = 0; +#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_DSR_LATENCY) + total_clock_dsr_latency = 0; + total_clock_dsr_calls = 0; + min_clock_dsr_latency = 0x7FFFFFFF; + max_clock_dsr_latency = 0; +#endif + enable_clock_latency_measurement(); + +} +#else +#define disable_clock_latency_measurement() +#define enable_clock_latency_measurement() +#define reset_clock_latency_measurement() +#endif + +//-------------------------------------------------------------------------- + +void +show_times_hdr(void) +{ + disable_clock_latency_measurement(); + diag_printf("\n"); + diag_printf(" Confidence\n"); + diag_printf(" Ave Min Max Var Ave Min Function\n"); + diag_printf(" ====== ====== ====== ====== ========== ========\n"); + enable_clock_latency_measurement(); +} + +void +show_times_detail(fun_times ft[], int nsamples, char *title, bool ignore_first) +{ + int i, delta, min, max, con_ave, con_min, ave_dev; + int start_sample, total_samples; + cyg_int32 total, ave; + + if (ignore_first) { + start_sample = 1; + total_samples = nsamples-1; + } else { + start_sample = 0; + total_samples = nsamples; + } + total = 0; + min = 0x7FFFFFFF; + max = 0; + for (i = start_sample; i < nsamples; i++) { + if (ft[i].end < ft[i].start) { + // Clock wrapped around (timer tick) + delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start; + } else { + delta = ft[i].end - ft[i].start; + } + delta -= overhead; + if (delta < 0) delta = 0; + delta *= 1000; + total += delta; + if (delta < min) min = delta; + if (delta > max) max = delta; + } + ave = total / total_samples; + total = 0; + ave_dev = 0; + for (i = start_sample; i < nsamples; i++) { + if (ft[i].end < ft[i].start) { + // Clock wrapped around (timer tick) + delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start; + } else { + delta = ft[i].end - ft[i].start; + } + delta -= overhead; + if (delta < 0) delta = 0; + delta *= 1000; + delta = delta - ave; + if (delta < 0) delta = -delta; + ave_dev += delta; + } + ave_dev /= total_samples; + con_ave = 0; + con_min = 0; + for (i = start_sample; i < nsamples; i++) { + if (ft[i].end < ft[i].start) { + // Clock wrapped around (timer tick) + delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start; + } else { + delta = ft[i].end - ft[i].start; + } + delta -= overhead; + if (delta < 0) delta = 0; + delta *= 1000; + if ((delta <= (ave+ave_dev)) && (delta >= (ave-ave_dev))) con_ave++; + if ((delta <= (min+ave_dev)) && (delta >= (min-ave_dev))) con_min++; + } + con_ave = (con_ave * 100) / total_samples; + con_min = (con_min * 100) / total_samples; + show_ticks_in_us(ave); + show_ticks_in_us(min); + show_ticks_in_us(max); + show_ticks_in_us(ave_dev); + disable_clock_latency_measurement(); + diag_printf(" %3d%% %3d%%", con_ave, con_min); + diag_printf(" %s\n", title); + enable_clock_latency_measurement(); +} + +void +show_times(fun_times ft[], int nsamples, char *title) +{ + show_times_detail(ft, nsamples, title, false); +#ifdef STATS_WITHOUT_FIRST_SAMPLE + show_times_detail(ft, nsamples, "", true); +#endif +} + +//-------------------------------------------------------------------------- + +void +show_test_parameters(void) +{ + disable_clock_latency_measurement(); + diag_printf("\nTesting parameters:\n"); + diag_printf(" Clock samples: %5d\n", nsamples); + diag_printf(" Threads: %5d\n", ntest_threads); + diag_printf(" Thread switches: %5d\n", nthread_switches); + diag_printf(" Mutexes: %5d\n", nmutexes); + diag_printf(" Mailboxes: %5d\n", nmboxes); + diag_printf(" Semaphores: %5d\n", nsemaphores); + diag_printf(" Scheduler operations: %5d\n", nscheds); + diag_printf(" Timers: %5d\n", ntimers); + diag_printf("\n"); + enable_clock_latency_measurement(); +} + +void +end_of_test_group(void) +{ + disable_clock_latency_measurement(); + diag_printf("\n"); + enable_clock_latency_measurement(); +} + +//-------------------------------------------------------------------------- +// Compute a name for a thread + +char * +thread_name(char *basename, int indx) { + return "<>"; // Not currently used +} + +//-------------------------------------------------------------------------- +// test0 - null test, just return + +void * +test0(void *indx) +{ + return indx; +} + +//-------------------------------------------------------------------------- +// test3 - loop, yeilding repeatedly and checking for cancellation + +void * +test3(void *indx) +{ + for(;;) + { + sched_yield(); + pthread_testcancel(); + } + + return indx; +} + +//-------------------------------------------------------------------------- +// test1 - empty test, simply exit. Last thread signals parent. + +void * +test1( void *indx) +{ + if ((cyg_uint32)indx == (cyg_uint32)(ntest_threads-1)) { + sem_post(&synchro); // Signal that last thread is dying + } + return indx; +} + +//-------------------------------------------------------------------------- +// test2 - measure thread switch times + +void * +test2(void *indx) +{ + int i; + for (i = 0; i < nthread_switches; i++) { + if ((int)indx == 0) { + HAL_CLOCK_READ(&test2_ft[i].start); + } else { + HAL_CLOCK_READ(&test2_ft[i].end); + } + sched_yield(); + } + if ((int)indx == 1) { + sem_post(&synchro); + } + + return indx; +} + +//-------------------------------------------------------------------------- +// Full-circuit mutex unlock/lock test + +void * +mutex_test(void * indx) +{ + int i; + pthread_mutex_lock(&test_mutexes[0]); + for (i = 0; i < nmutexes; i++) { + sem_wait(&synchro); + wait_for_tick(); // Wait until the next clock tick to minimize aberations + HAL_CLOCK_READ(&mutex_ft[i].start); + pthread_mutex_unlock(&test_mutexes[0]); + pthread_mutex_lock(&test_mutexes[0]); + sem_post(&synchro); + } + return indx; +} + +//-------------------------------------------------------------------------- +// Full-circuit mbox put/get test + +#if 0 +void +mbox_test(cyg_uint32 indx) +{ + void *item; + do { + item = cyg_mbox_get(test_mbox_handles[0]); + HAL_CLOCK_READ(&mbox_ft[(int)item].end); + cyg_semaphore_post(&synchro); + } while ((int)item != (nmboxes-1)); + cyg_thread_exit(0); +} +#endif + +//-------------------------------------------------------------------------- +// Full-circuit semaphore post/wait test + +void * +semaphore_test(void * indx) +{ + int i; + for (i = 0; i < nsemaphores; i++) { + sem_wait(&test_semaphores[0]); + HAL_CLOCK_READ(&semaphore_ft[i].end); + sem_post(&synchro); + } + return indx; +} + +//-------------------------------------------------------------------------- +// +// This set of tests is used to measure kernel primitives that deal with threads +// + +void +run_thread_tests(void) +{ + + + int i; + struct sched_param schedparam; + pthread_attr_t attr; + int policy; + void *retval; + + // Set my priority higher than any I plan to create + schedparam.sched_priority = 30; + pthread_setschedparam( pthread_self(), SCHED_RR, &schedparam ); + + // Initiaize thread creation attributes + + pthread_attr_init( &attr ); + pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); + pthread_attr_setschedpolicy( &attr, SCHED_RR ); + schedparam.sched_priority = 10; + pthread_attr_setschedparam( &attr, &schedparam ); + + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < ntest_threads; i++) { + HAL_CLOCK_READ(&thread_ft[i].start); + + pthread_attr_setstackaddr( &attr, &stacks[i][STACK_SIZE] ); + pthread_attr_setstacksize( &attr, STACK_SIZE ); + pthread_create( &threads[i], + &attr, + test0, + (void *)i + ); + + HAL_CLOCK_READ(&thread_ft[i].end); + } + show_times(thread_ft, ntest_threads, "Create thread"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < ntest_threads; i++) { + HAL_CLOCK_READ(&thread_ft[i].start); + sched_yield(); + HAL_CLOCK_READ(&thread_ft[i].end); + } + show_times(thread_ft, ntest_threads, "Yield thread [all lower priority]"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < ntest_threads; i++) { + HAL_CLOCK_READ(&thread_ft[i].start); + + schedparam.sched_priority = 11; + pthread_attr_setschedparam( &attr, &schedparam ); + pthread_setschedparam(threads[i], SCHED_RR, &schedparam); + + HAL_CLOCK_READ(&thread_ft[i].end); + } + show_times(thread_ft, ntest_threads, "Set priority"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < ntest_threads; i++) { + HAL_CLOCK_READ(&thread_ft[i].start); + pthread_getschedparam( threads[i], &policy, &schedparam ); + HAL_CLOCK_READ(&thread_ft[i].end); + } + show_times(thread_ft, ntest_threads, "Get priority"); + + cyg_thread_delay(1); // Let the test threads run + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < ntest_threads; i++) { + HAL_CLOCK_READ(&thread_ft[i].start); + pthread_join(threads[i], &retval); + HAL_CLOCK_READ(&thread_ft[i].end); + } + show_times(thread_ft, ntest_threads, "Join exited thread"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < ntest_threads; i++) { + HAL_CLOCK_READ(&thread_ft[i].start); + sched_yield(); + HAL_CLOCK_READ(&thread_ft[i].end); + } + show_times(thread_ft, ntest_threads, "Yield [no other] thread"); + + + // Recreate the test set + + schedparam.sched_priority = 10; + pthread_attr_setschedparam( &attr, &schedparam ); + + for (i = 0; i < ntest_threads; i++) { + pthread_attr_setstackaddr( &attr, &stacks[i][STACK_SIZE] ); + pthread_attr_setstacksize( &attr, STACK_SIZE ); + pthread_create( &threads[i], + &attr, + test3, + (void *)i + ); + } + + cyg_thread_delay(1); // Let the test threads run + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < ntest_threads; i++) { + HAL_CLOCK_READ(&thread_ft[i].start); + pthread_cancel(threads[i]); + HAL_CLOCK_READ(&thread_ft[i].end); + } + show_times(thread_ft, ntest_threads, "Cancel [running] thread"); + + cyg_thread_delay(1); // Let the test threads do their cancellations + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < ntest_threads; i++) { + HAL_CLOCK_READ(&thread_ft[i].start); + pthread_join(threads[i], &retval); + HAL_CLOCK_READ(&thread_ft[i].end); + } + show_times(thread_ft, ntest_threads, "Join [cancelled] thread"); + + + // Set my priority lower than any I plan to create + schedparam.sched_priority = 5; + pthread_setschedparam( pthread_self(), SCHED_RR, &schedparam ); + + // Set up the end-of-threads synchronizer + sem_init(&synchro, 0, 0); + + schedparam.sched_priority = 10; + pthread_attr_setschedparam( &attr, &schedparam ); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < ntest_threads; i++) { + HAL_CLOCK_READ(&thread_ft[i].start); + + pthread_attr_setstackaddr( &attr, &stacks[i][STACK_SIZE] ); + pthread_attr_setstacksize( &attr, STACK_SIZE ); + pthread_create( &threads[i], + &attr, + test2, + (void *)i + ); + + HAL_CLOCK_READ(&thread_ft[i].end); + } + show_times(thread_ft, ntest_threads, "Create [high priority] thread"); + + sem_wait(&synchro); // Wait for all threads to finish + + // Make sure they are all dead + for (i = 0; i < ntest_threads; i++) { + pthread_join(threads[i], &retval); + } + + run_thread_switch_test(); + end_of_test_group(); + +} + +//-------------------------------------------------------------------------- + +void +run_thread_switch_test(void) +{ + + int i; + struct sched_param schedparam; + pthread_attr_t attr; + void *retval; + + // Set my priority higher than any I plan to create + schedparam.sched_priority = 30; + pthread_setschedparam( pthread_self(), SCHED_RR, &schedparam ); + + // Initiaize thread creation attributes + + pthread_attr_init( &attr ); + pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); + pthread_attr_setschedpolicy( &attr, SCHED_RR ); + schedparam.sched_priority = 10; + pthread_attr_setschedparam( &attr, &schedparam ); + + // Set up the end-of-threads synchronizer + + sem_init(&synchro, 0, 0); + + // Set up for thread context switch + + for (i = 0; i < 2; i++) { + pthread_attr_setstackaddr( &attr, &stacks[i][STACK_SIZE] ); + pthread_attr_setstacksize( &attr, STACK_SIZE ); + pthread_create( &threads[i], + &attr, + test2, + (void *)i + ); + } + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + + sem_wait(&synchro); + + show_times(test2_ft, nthread_switches, "Thread switch"); + + // Clean up + for (i = 0; i < 2; i++) { + pthread_join(threads[i], &retval); + } + +} + + +//-------------------------------------------------------------------------- + +void +run_mutex_tests(void) +{ + + int i; + pthread_mutexattr_t attr; + + pthread_mutexattr_init( &attr ); + + // Mutex primitives + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmutexes; i++) { + HAL_CLOCK_READ(&mutex_ft[i].start); + pthread_mutex_init(&test_mutexes[i], &attr); + HAL_CLOCK_READ(&mutex_ft[i].end); + } + show_times(mutex_ft, nmutexes, "Init mutex"); + + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmutexes; i++) { + HAL_CLOCK_READ(&mutex_ft[i].start); + pthread_mutex_lock(&test_mutexes[i]); + HAL_CLOCK_READ(&mutex_ft[i].end); + } + show_times(mutex_ft, nmutexes, "Lock [unlocked] mutex"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmutexes; i++) { + HAL_CLOCK_READ(&mutex_ft[i].start); + pthread_mutex_unlock(&test_mutexes[i]); + HAL_CLOCK_READ(&mutex_ft[i].end); + } + show_times(mutex_ft, nmutexes, "Unlock [locked] mutex"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmutexes; i++) { + HAL_CLOCK_READ(&mutex_ft[i].start); + pthread_mutex_trylock(&test_mutexes[i]); + HAL_CLOCK_READ(&mutex_ft[i].end); + } + show_times(mutex_ft, nmutexes, "Trylock [unlocked] mutex"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmutexes; i++) { + HAL_CLOCK_READ(&mutex_ft[i].start); + pthread_mutex_trylock(&test_mutexes[i]); + HAL_CLOCK_READ(&mutex_ft[i].end); + } + show_times(mutex_ft, nmutexes, "Trylock [locked] mutex"); + + // Must unlock mutices before destroying them. + for (i = 0; i < nmutexes; i++) { + pthread_mutex_unlock(&test_mutexes[i]); + } + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmutexes; i++) { + HAL_CLOCK_READ(&mutex_ft[i].start); + pthread_mutex_destroy(&test_mutexes[i]); + HAL_CLOCK_READ(&mutex_ft[i].end); + } + show_times(mutex_ft, nmutexes, "Destroy mutex"); + + + run_mutex_circuit_test(); + end_of_test_group(); +} + +//-------------------------------------------------------------------------- + +void +run_mutex_circuit_test(void) +{ + int i; + pthread_mutexattr_t mattr; + struct sched_param schedparam; + pthread_attr_t attr; + void *retval; + + // Set my priority lower than any I plan to create + schedparam.sched_priority = 5; + pthread_setschedparam( pthread_self(), SCHED_RR, &schedparam ); + + // Initiaize thread creation attributes + + pthread_attr_init( &attr ); + pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); + pthread_attr_setschedpolicy( &attr, SCHED_RR ); + schedparam.sched_priority = 10; + pthread_attr_setschedparam( &attr, &schedparam ); + + // Set up for full mutex unlock/lock test + pthread_mutexattr_init( &mattr ); + pthread_mutex_init(&test_mutexes[0], &mattr); + sem_init(&synchro, 0, 0); + + pthread_attr_setstackaddr( &attr, &stacks[0][STACK_SIZE] ); + pthread_attr_setstacksize( &attr, STACK_SIZE ); + pthread_create( &mutex_test_thread_handle, + &attr, + mutex_test, + (void *)0 + ); + + // Need to raise priority so that this thread will block on the "lock" + schedparam.sched_priority = 20; + pthread_setschedparam( pthread_self(), SCHED_RR, &schedparam ); + + for (i = 0; i < nmutexes; i++) { + sem_post(&synchro); + pthread_mutex_lock(&test_mutexes[0]); + HAL_CLOCK_READ(&mutex_ft[i].end); + pthread_mutex_unlock(&test_mutexes[0]); + sem_wait(&synchro); + } + pthread_join(mutex_test_thread_handle, &retval); + show_times(mutex_ft, nmutexes, "Unlock/Lock mutex"); + +} + + +//-------------------------------------------------------------------------- +// Message queue tests + +// Currently disabled, pending implementation of POSIX message queues + +#if 0 +void +run_mbox_tests(void) +{ + int i, cnt; + void *item; + // Mailbox primitives + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + cyg_mbox_create(&test_mbox_handles[i], &test_mboxes[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Create mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + cnt = cyg_mbox_peek(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Peek [empty] mbox"); + +#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + cyg_mbox_put(test_mbox_handles[i], (void *)i); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Put [first] mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + cnt = cyg_mbox_peek(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Peek [1 msg] mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + cyg_mbox_put(test_mbox_handles[i], (void *)i); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Put [second] mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + cnt = cyg_mbox_peek(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Peek [2 msgs] mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + item = cyg_mbox_get(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Get [first] mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + item = cyg_mbox_get(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Get [second] mbox"); +#endif // ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + cyg_mbox_tryput(test_mbox_handles[i], (void *)i); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Tryput [first] mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + item = cyg_mbox_peek_item(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Peek item [non-empty] mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + item = cyg_mbox_tryget(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Tryget [non-empty] mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + item = cyg_mbox_peek_item(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Peek item [empty] mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + item = cyg_mbox_tryget(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Tryget [empty] mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + cyg_mbox_waiting_to_get(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Waiting to get mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + cyg_mbox_waiting_to_put(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Waiting to put mbox"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nmboxes; i++) { + HAL_CLOCK_READ(&mbox_ft[i].start); + cyg_mbox_delete(test_mbox_handles[i]); + HAL_CLOCK_READ(&mbox_ft[i].end); + } + show_times(mbox_ft, nmboxes, "Delete mbox"); + + run_mbox_circuit_test(); + end_of_test_group(); +} + +//-------------------------------------------------------------------------- + +void +run_mbox_circuit_test(void) +{ +#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT + int i; + // Set my priority lower than any I plan to create + cyg_thread_set_priority(cyg_thread_self(), 3); + // Set up for full mbox put/get test + cyg_mbox_create(&test_mbox_handles[0], &test_mboxes[0]); + cyg_semaphore_init(&synchro, 0); + cyg_thread_create(2, // Priority - just a number + mbox_test, // entry + 0, // index + thread_name("thread", 0), // Name + &stacks[0][0], // Stack + STACK_SIZE, // Size + &mbox_test_thread_handle, // Handle + &mbox_test_thread // Thread data structure + ); + cyg_thread_resume(mbox_test_thread_handle); + for (i = 0; i < nmboxes; i++) { + wait_for_tick(); // Wait until the next clock tick to minimize aberations + HAL_CLOCK_READ(&mbox_ft[i].start); + cyg_mbox_put(test_mbox_handles[0], (void *)i); + cyg_semaphore_wait(&synchro); + } + cyg_thread_delete(mbox_test_thread_handle); + show_times(mbox_ft, nmboxes, "Put/Get mbox"); +#endif +} + +#endif + +//-------------------------------------------------------------------------- + +void +run_semaphore_tests(void) +{ + + int i; + int sem_val; + + // Semaphore primitives + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nsemaphores; i++) { + HAL_CLOCK_READ(&semaphore_ft[i].start); + sem_init(&test_semaphores[i], 0, 0); + HAL_CLOCK_READ(&semaphore_ft[i].end); + } + show_times(semaphore_ft, nsemaphores, "Init semaphore"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nsemaphores; i++) { + HAL_CLOCK_READ(&semaphore_ft[i].start); + sem_post(&test_semaphores[i]); + HAL_CLOCK_READ(&semaphore_ft[i].end); + } + show_times(semaphore_ft, nsemaphores, "Post [0] semaphore"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nsemaphores; i++) { + HAL_CLOCK_READ(&semaphore_ft[i].start); + sem_wait(&test_semaphores[i]); + HAL_CLOCK_READ(&semaphore_ft[i].end); + } + show_times(semaphore_ft, nsemaphores, "Wait [1] semaphore"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nsemaphores; i++) { + HAL_CLOCK_READ(&semaphore_ft[i].start); + sem_trywait(&test_semaphores[i]); + HAL_CLOCK_READ(&semaphore_ft[i].end); + } + show_times(semaphore_ft, nsemaphores, "Trywait [0] semaphore"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nsemaphores; i++) { + sem_post(&test_semaphores[i]); + HAL_CLOCK_READ(&semaphore_ft[i].start); + sem_trywait(&test_semaphores[i]); + HAL_CLOCK_READ(&semaphore_ft[i].end); + } + show_times(semaphore_ft, nsemaphores, "Trywait [1] semaphore"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nsemaphores; i++) { + HAL_CLOCK_READ(&semaphore_ft[i].start); + sem_getvalue(&test_semaphores[i], &sem_val); + HAL_CLOCK_READ(&semaphore_ft[i].end); + } + show_times(semaphore_ft, nsemaphores, "Get value of semaphore"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < nsemaphores; i++) { + HAL_CLOCK_READ(&semaphore_ft[i].start); + sem_destroy(&test_semaphores[i]); + HAL_CLOCK_READ(&semaphore_ft[i].end); + } + show_times(semaphore_ft, nsemaphores, "Destroy semaphore"); + + run_semaphore_circuit_test(); + end_of_test_group(); +} + +//-------------------------------------------------------------------------- + +void +run_semaphore_circuit_test(void) +{ + + int i; + struct sched_param schedparam; + pthread_attr_t attr; + void *retval; + + // Set my priority lower than any I plan to create + schedparam.sched_priority = 5; + pthread_setschedparam( pthread_self(), SCHED_RR, &schedparam ); + + // Initiaize thread creation attributes + + pthread_attr_init( &attr ); + pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); + pthread_attr_setschedpolicy( &attr, SCHED_RR ); + schedparam.sched_priority = 10; + pthread_attr_setschedparam( &attr, &schedparam ); + + // Set up for full semaphore post/wait test + sem_init(&test_semaphores[0], 0, 0); + sem_init(&synchro, 0, 0); + + pthread_attr_setstackaddr( &attr, &stacks[0][STACK_SIZE] ); + pthread_attr_setstacksize( &attr, STACK_SIZE ); + pthread_create( &semaphore_test_thread_handle, + &attr, + semaphore_test, + (void *)0 + ); + + + for (i = 0; i < nsemaphores; i++) { + wait_for_tick(); // Wait until the next clock tick to minimize aberations + HAL_CLOCK_READ(&semaphore_ft[i].start); + sem_post(&test_semaphores[0]); + sem_wait(&synchro); + } + pthread_join(semaphore_test_thread_handle, &retval); + + show_times(semaphore_ft, nsemaphores, "Post/Wait semaphore"); + + +} + +//-------------------------------------------------------------------------- + +// Timer callback function +void +sigrt0(int signo, siginfo_t *info, void *context) +{ + diag_printf("sigrt0 called\n"); + // empty call back +} + +// Callback used to test determinancy +static volatile int timer_cnt; +void +sigrt1(int signo, siginfo_t *info, void *context) +{ + if (timer_cnt == nscheds) return; + sched_ft[timer_cnt].start = 0; + HAL_CLOCK_READ(&sched_ft[timer_cnt++].end); + if (timer_cnt == nscheds) { + sem_post(&synchro); + } +} + +static sem_t timer_sem; + +static void +sigrt2(int signo, siginfo_t *info, void *context) +{ + if (timer_cnt == nscheds) { + sem_post(&synchro); + sem_post(&timer_sem); + } else { + sched_ft[timer_cnt].start = 0; + sem_post(&timer_sem); + } +} + +// Null thread, used to keep scheduler busy +void * +timer_test(void * id) +{ + while (true) { + cyg_thread_yield(); + pthread_testcancel(); + } + + return id; +} + +// Thread that suspends itself at the first opportunity +void * +timer_test2(void *id) +{ + while (timer_cnt != nscheds) { + HAL_CLOCK_READ(&sched_ft[timer_cnt++].end); + sem_wait(&timer_sem); + } + return id; +} + +void +run_timer_tests(void) +{ + int res; + int i; + struct sigaction sa; + struct sigevent sigev; + struct itimerspec tp; + + // Install signal handlers + sigemptyset( &sa.sa_mask ); + sa.sa_flags = SA_SIGINFO; + + sa.sa_sigaction = sigrt0; + sigaction( SIGRTMIN, &sa, NULL ); + + sa.sa_sigaction = sigrt1; + sigaction( SIGRTMIN+1, &sa, NULL ); + + sa.sa_sigaction = sigrt2; + sigaction( SIGRTMIN+2, &sa, NULL ); + + // Set up common bits of sigevent + + sigev.sigev_notify = SIGEV_SIGNAL; + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < ntimers; i++) { + HAL_CLOCK_READ(&timer_ft[i].start); + sigev.sigev_signo = SIGRTMIN; + sigev.sigev_value.sival_ptr = (void*)(&timers[i]); + res = timer_create( CLOCK_REALTIME, &sigev, &timers[i]); + HAL_CLOCK_READ(&timer_ft[i].end); + CYG_ASSERT( res == 0 , "timer_create() returned error"); + } + show_times(timer_ft, ntimers, "Create timer"); + + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + tp.it_value.tv_sec = 0; + tp.it_value.tv_nsec = 0; + tp.it_interval.tv_sec = 0; + tp.it_interval.tv_nsec = 0; + for (i = 0; i < ntimers; i++) { + HAL_CLOCK_READ(&timer_ft[i].start); + res = timer_settime( timers[i], 0, &tp, NULL ); + HAL_CLOCK_READ(&timer_ft[i].end); + CYG_ASSERT( res == 0 , "timer_settime() returned error"); + } + show_times(timer_ft, ntimers, "Initialize timer to zero"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + tp.it_value.tv_sec = 1; + tp.it_value.tv_nsec = 250000000; + tp.it_interval.tv_sec = 0; + tp.it_interval.tv_nsec = 0; + for (i = 0; i < ntimers; i++) { + HAL_CLOCK_READ(&timer_ft[i].start); + res = timer_settime( timers[i], 0, &tp, NULL ); + HAL_CLOCK_READ(&timer_ft[i].end); + CYG_ASSERT( res == 0 , "timer_settime() returned error"); + } + show_times(timer_ft, ntimers, "Initialize timer to 1.25 sec"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + tp.it_value.tv_sec = 0; + tp.it_value.tv_nsec = 0; + tp.it_interval.tv_sec = 0; + tp.it_interval.tv_nsec = 0; + for (i = 0; i < ntimers; i++) { + HAL_CLOCK_READ(&timer_ft[i].start); + res = timer_settime( timers[i], 0, &tp, NULL ); + HAL_CLOCK_READ(&timer_ft[i].end); + CYG_ASSERT( res == 0 , "timer_settime() returned error"); + } + show_times(timer_ft, ntimers, "Disable timer"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + for (i = 0; i < ntimers; i++) { + HAL_CLOCK_READ(&timer_ft[i].start); + res = timer_delete( timers[i] ); + HAL_CLOCK_READ(&timer_ft[i].end); + CYG_ASSERT( res == 0 , "timer_settime() returned error"); + } + show_times(timer_ft, ntimers, "Delete timer"); + + + + sigev.sigev_signo = SIGRTMIN+1; + sigev.sigev_value.sival_ptr = (void*)(&timers[i]); + res = timer_create( CLOCK_REALTIME, &sigev, &timers[0]); + CYG_ASSERT( res == 0 , "timer_create() returned error"); + tp.it_value.tv_sec = 0; + tp.it_value.tv_nsec = 50000000; + tp.it_interval.tv_sec = 0; + tp.it_interval.tv_nsec = 50000000;; + timer_cnt = 0; + res = timer_settime( timers[0], 0, &tp, NULL ); + CYG_ASSERT( res == 0 , "timer_settime() returned error"); + sem_init(&synchro, 0, 0); + wait_for_tick(); // Wait until the next clock tick to minimize aberations + do + { res = sem_wait(&synchro); + } while( res == -1 && errno == EINTR ); + CYG_ASSERT( res == 0 , "sem_wait() returned error"); + tp.it_value.tv_sec = 0; + tp.it_value.tv_nsec = 0; + tp.it_interval.tv_sec = 0; + tp.it_interval.tv_nsec = 0; + res = timer_settime( timers[0], 0, &tp, NULL ); + CYG_ASSERT( res == 0 , "timer_settime() returned error"); + res = timer_delete( timers[0] ); + CYG_ASSERT( res == 0 , "timer_delete() returned error"); + show_times(sched_ft, nscheds, "Timer latency [0 threads]"); + + + + + struct sched_param schedparam; + pthread_attr_t attr; + void *retval; + + // Set my priority higher than any I plan to create + schedparam.sched_priority = 20; + pthread_setschedparam( pthread_self(), SCHED_RR, &schedparam ); + + + // Initiaize thread creation attributes + + pthread_attr_init( &attr ); + pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); + pthread_attr_setschedpolicy( &attr, SCHED_RR ); + schedparam.sched_priority = 10; + pthread_attr_setschedparam( &attr, &schedparam ); + + for (i = 0; i < 2; i++) { + pthread_attr_setstackaddr( &attr, &stacks[i][STACK_SIZE] ); + pthread_attr_setstacksize( &attr, STACK_SIZE ); + res = pthread_create( &threads[i], + &attr, + timer_test, + (void *)i + ); + CYG_ASSERT( res == 0 , "pthread_create() returned error"); + } + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + + sigev.sigev_signo = SIGRTMIN+1; + sigev.sigev_value.sival_ptr = (void*)(&timers[i]); + res = timer_create( CLOCK_REALTIME, &sigev, &timers[0]); + CYG_ASSERT( res == 0 , "timer_create() returned error"); + tp.it_value.tv_sec = 0; + tp.it_value.tv_nsec = 50000000; + tp.it_interval.tv_sec = 0; + tp.it_interval.tv_nsec = 50000000;; + timer_cnt = 0; + res = timer_settime( timers[0], 0, &tp, NULL ); + CYG_ASSERT( res == 0 , "timer_settime() returned error"); + + sem_init(&synchro, 0, 0); + do + { res = sem_wait(&synchro); + } while( res == -1 && errno == EINTR ); + CYG_ASSERT( res == 0 , "sem_wait() returned error"); + res = timer_delete(timers[0]); + CYG_ASSERT( res == 0 , "timerdelete() returned error"); + show_times(sched_ft, nscheds, "Timer latency [2 threads]"); + for (i = 0; i < 2; i++) { + pthread_cancel(threads[i]); + pthread_join(threads[i], &retval); + } + + + + for (i = 0; i < ntest_threads; i++) { + pthread_attr_setstackaddr( &attr, &stacks[i][STACK_SIZE] ); + pthread_attr_setstacksize( &attr, STACK_SIZE ); + res = pthread_create( &threads[i], + &attr, + timer_test, + (void *)i + ); + CYG_ASSERT( res == 0 , "pthread_create() returned error"); + } + wait_for_tick(); // Wait until the next clock tick to minimize aberations + sigev.sigev_signo = SIGRTMIN+1; + sigev.sigev_value.sival_ptr = (void*)(&timers[i]); + res = timer_create( CLOCK_REALTIME, &sigev, &timers[0]); + CYG_ASSERT( res == 0 , "timer_create() returned error"); + tp.it_value.tv_sec = 0; + tp.it_value.tv_nsec = 50000000; + tp.it_interval.tv_sec = 0; + tp.it_interval.tv_nsec = 50000000;; + timer_cnt = 0; + res = timer_settime( timers[0], 0, &tp, NULL ); + CYG_ASSERT( res == 0 , "timer_settime() returned error"); + + sem_init(&synchro, 0, 0); + do + { res = sem_wait(&synchro); + } while( res == -1 && errno == EINTR ); + CYG_ASSERT( res == 0 , "sem_wait() returned error"); + res = timer_delete(timers[0]); + CYG_ASSERT( res == 0 , "timerdelete() returned error"); + show_times(sched_ft, nscheds, "Timer latency [many threads]"); + for (i = 0; i < ntest_threads; i++) { + pthread_cancel(threads[i]); + pthread_join(threads[i], &retval); + } + + sem_init(&synchro, 0, 0); + sem_init(&timer_sem, 0, 0); + pthread_attr_setstackaddr( &attr, &stacks[0][STACK_SIZE] ); + pthread_attr_setstacksize( &attr, STACK_SIZE ); + res = pthread_create( &threads[0], + &attr, + timer_test2, + (void *)0 + ); + CYG_ASSERT( res == 0 , "pthread_create() returned error"); + + wait_for_tick(); // Wait until the next clock tick to minimize aberations + sigev.sigev_signo = SIGRTMIN+2; + sigev.sigev_value.sival_ptr = (void*)(threads[0]); + res = timer_create( CLOCK_REALTIME, &sigev, &timers[0]); + CYG_ASSERT( res == 0 , "timer_create() returned error"); + tp.it_value.tv_sec = 0; + tp.it_value.tv_nsec = 50000000; + tp.it_interval.tv_sec = 0; + tp.it_interval.tv_nsec = 50000000;; + timer_cnt = 0; + res = timer_settime( timers[0], 0, &tp, NULL ); + CYG_ASSERT( res == 0 , "timer_settime() returned error"); + + do + { res = sem_wait(&synchro); + } while( res == -1 && errno == EINTR ); + CYG_ASSERT( res == 0 , "sem_wait() returned error"); + res = timer_delete(timers[0]); + CYG_ASSERT( res == 0 , "timerdelete() returned error"); + show_times(sched_ft, nscheds, "Timer -> thread post latency"); + sem_post(&timer_sem); +// pthread_cancel(threads[0]); + pthread_join(threads[0], &retval); + + + end_of_test_group(); +} + + +//-------------------------------------------------------------------------- + +void +run_all_tests() +{ + int i; + cyg_uint32 tv[nsamples], tv0, tv1; +// cyg_uint32 min_stack, max_stack, total_stack, actual_stack, j; + cyg_tick_count_t ticks, tick0, tick1; +#ifdef CYG_SCHEDULER_LOCK_TIMINGS + cyg_uint32 lock_ave, lock_max; +#endif +#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY) + cyg_int32 clock_ave; +#endif + + disable_clock_latency_measurement(); + +// cyg_test_dump_thread_stack_stats( "Startup, main stack", thread[0] ); + cyg_test_dump_interrupt_stack_stats( "Startup" ); + cyg_test_dump_idlethread_stack_stats( "Startup" ); + cyg_test_clear_interrupt_stack(); + + diag_printf("\neCos Kernel Timings\n"); + diag_printf("Notes: all times are in microseconds (.000001) unless otherwise stated\n"); +#ifdef STATS_WITHOUT_FIRST_SAMPLE + diag_printf(" second line of results have first sample removed\n"); +#endif + + cyg_thread_delay(2); // Make sure the clock is actually running + + ns_per_system_clock = 1000000/rtc_resolution[1]; + + for (i = 0; i < nsamples; i++) { + HAL_CLOCK_READ(&tv[i]); + } + tv0 = 0; + for (i = 1; i < nsamples; i++) { + tv0 += tv[i] - tv[i-1]; + } + end_of_test_group(); + + overhead = tv0 / (nsamples-1); + diag_printf("Reading the hardware clock takes %d 'ticks' overhead\n", overhead); + diag_printf("... this value will be factored out of all other measurements\n"); + + // Try and measure how long the clock interrupt handling takes + for (i = 0; i < nsamples; i++) { + tick0 = cyg_current_time(); + while (true) { + tick1 = cyg_current_time(); + if (tick0 != tick1) break; + } + HAL_CLOCK_READ(&tv[i]); + } + tv1 = 0; + for (i = 0; i < nsamples; i++) { + tv1 += tv[i] * 1000; + } + tv1 = tv1 / nsamples; + tv1 -= overhead; // Adjust out the cost of getting the timer value + diag_printf("Clock interrupt took"); + show_ticks_in_us(tv1); + diag_printf(" microseconds (%d raw clock ticks)\n", tv1/1000); + enable_clock_latency_measurement(); + + ticks = cyg_current_time(); + + show_test_parameters(); + show_times_hdr(); + + reset_clock_latency_measurement(); + + run_thread_tests(); + run_mutex_tests(); +// run_mbox_tests(); + run_semaphore_tests(); + run_timer_tests(); + +#ifdef CYG_SCHEDULER_LOCK_TIMINGS + Cyg_Scheduler::get_lock_times(&lock_ave, &lock_max); + diag_printf("\nMax lock:"); + show_ticks_in_us(lock_max); + diag_printf(", Ave lock:"); + show_ticks_in_us(lock_ave); + diag_printf("\n"); +#endif + +#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY) + // Display latency figures in same format as all other numbers + disable_clock_latency_measurement(); + clock_ave = (total_clock_latency*1000) / total_clock_interrupts; + show_ticks_in_us(clock_ave); + show_ticks_in_us(min_clock_latency*1000); + show_ticks_in_us(max_clock_latency*1000); + show_ticks_in_us(0); + diag_printf(" Clock/interrupt latency\n\n"); + enable_clock_latency_measurement(); +#endif + +#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_DSR_LATENCY) + disable_clock_latency_measurement(); + clock_ave = (total_clock_dsr_latency*1000) / total_clock_dsr_calls; + show_ticks_in_us(clock_ave); + show_ticks_in_us(min_clock_dsr_latency*1000); + show_ticks_in_us(max_clock_dsr_latency*1000); + show_ticks_in_us(0); + diag_printf(" Clock DSR latency\n\n"); + enable_clock_latency_measurement(); +#endif + +#if 0 + disable_clock_latency_measurement(); + min_stack = STACK_SIZE; + max_stack = 0; + total_stack = 0; + for (i = 0; i < (int)NTEST_THREADS; i++) { + for (j = 0; j < STACK_SIZE; j++) { + if (stacks[i][j]) break; + } + actual_stack = STACK_SIZE-j; + if (actual_stack < min_stack) min_stack = actual_stack; + if (actual_stack > max_stack) max_stack = actual_stack; + total_stack += actual_stack; + } + for (j = 0; j < STACKSIZE; j++) { + if (((char *)stack[0])[j]) break; + } + diag_printf("%5d %5d %5d (main stack: %5d) Thread stack used (%d total)\n", + total_stack/NTEST_THREADS, min_stack, max_stack, + STACKSIZE - j, STACK_SIZE); +#endif + +// cyg_test_dump_thread_stack_stats( "All done, main stack", thread[0] ); + cyg_test_dump_interrupt_stack_stats( "All done" ); + cyg_test_dump_idlethread_stack_stats( "All done" ); + + enable_clock_latency_measurement(); + + ticks = cyg_current_time(); + diag_printf("\nTiming complete - %d ms total\n\n", (int)((ticks*ns_per_system_clock)/1000)); + + CYG_TEST_PASS_FINISH("Basic timing OK"); +} + +int main( int argc, char **argv ) +{ + CYG_TEST_INIT(); + + if (cyg_test_is_simulator) { + nsamples = NSAMPLES_SIM; + ntest_threads = NTEST_THREADS_SIM; + nthread_switches = NTHREAD_SWITCHES_SIM; + nmutexes = NMUTEXES_SIM; + nmboxes = NMBOXES_SIM; + nsemaphores = NSEMAPHORES_SIM; + nscheds = NSCHEDS_SIM; + ntimers = NTIMERS_SIM; + } else { + nsamples = NSAMPLES; + ntest_threads = NTEST_THREADS; + nthread_switches = NTHREAD_SWITCHES; + nmutexes = NMUTEXES; + nmboxes = NMBOXES; + nsemaphores = NSEMAPHORES; + nscheds = NSCHEDS; + ntimers = NTIMERS; + } + + // Sanity +#ifdef WORKHORSE_TEST + ntest_threads = max(512, ntest_threads); + nmutexes = max(1024, nmutexes); + nsemaphores = max(1024, nsemaphores); + nmboxes = max(1024, nmboxes); + ncounters = max(1024, ncounters); + ntimers = max(1024, ntimers); +#else + ntest_threads = max(64, ntest_threads); + nmutexes = max(32, nmutexes); + nsemaphores = max(32, nsemaphores); + nmboxes = max(32, nmboxes); + ntimers = max(32, ntimers); +#endif + + run_all_tests(); + +} + +#endif // CYGFUN_KERNEL_API_C, etc. + +// EOF tm_basic.cxx diff --git a/packages/compat/uitron/v2_0/ChangeLog b/packages/compat/uitron/v2_0/ChangeLog new file mode 100644 index 00000000..225ce801 --- /dev/null +++ b/packages/compat/uitron/v2_0/ChangeLog @@ -0,0 +1,877 @@ +2005-08-02 Andrew Lunn + + * tests/test2.c (task1): Cast to fix compiler warning. + +2003-02-24 Jonathan Larmour + + * cdl/uitron.cdl: Update doc link. + +2002-05-27 Jesper Skov + + * cdl/uitron.cdl: Don't build C tests when C++ options selected. + +2002-05-22 Nick Garnett + + * doc/uitron.sgml: Fixed dangling xref. + +2002-02-19 Mark Salter + + * doc/uitron.sgml: Fixed typos and such. + +2002-02-14 Hugo Tyson + + * doc/uitron.sgml: General polishing... Tidied up broken emPHAsis + on closing parentheses of function lists. Reduced line length of + same to fit real paper, I hope. Added LITERAL tags all over + config option mentions. + + New stuff... Added a whole new section "[u]ITRON Configuration + FAQ" based on some email answers I have given in the past in + support of customers. + +2002-02-13 Hugo Tyson + + * doc/uitron.sgml: NEW FILE: Make id tags qualified with + compat-uitron- and add a couple of tags; tidy up formatting of + some function listings; correct comment on using functions in your + own DSRs and ISRs. + +2002-01-24 Jesper Skov + + * include/uit_func.inl (ena_int, dis_int): Wrap + HAL_MASK_INTERRUPT/HAL_UNMASK_INTERRUPT in interrupt + disable/restore pairs. + * tests/testintr.cxx (detach_isr, attach_isr): Change order of + mask/unmask and disable/restore. + +2001-04-30 Jonathan Larmour + + * src/uit_objs.cxx: Workaround xscale tools preprocessor bug + by avoiding determining the stack size with the preprocessor. + * cdl/tasks.cdl (CYGDAT_UITRON_TASK_EXTERNS and + CYGDAT_UITRON_TASK_INITIALISERS): Ditto + +2001-04-21 Bart Veer + + * tests/testintr.cxx (task1): + Disable one of the tests on the synthetic target, it requires + consistent cpu timing that cannot be guaranteed. + +2000-11-01 Jesper Skov + + * include/uit_func.inl: CYG_SCHED_UNIQUE_PRIORITIES changed to + CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES + +2000-09-13 Jonathan Larmour + + * include/uit_objs.hxx (CYG_UITRON_OBJS_INIT_PRIORITY): Define + with correct priority now. + +2000-08-03 Jonathan Larmour + + * include/uit_func.inl (ref_mpf): Compute used blocks from + bytes used / blocks size rather than now obsolete blockcount member + +2000-07-04 Jonathan Larmour + + * include/uit_func.inl: Update all memory pool related functions to + reflect the new interface to memory pools, and that they come from + the new CYGPKG_MEMALLOC package + + * cdl/uitron.cdl: CYGPKG_UITRON_MEMPOOLFIXED and + CYGPKG_UITRON_MEMPOOLVAR require the CYGPKG_MEMALLOC package + + * include/uit_objs.hxx: Update includes - memory pool implementations + are now in CYGPKG_MEMALLOC + +2000-06-15 Gary Thomas + + * include/uit_ifnc.h (CYGPRI_UITRON_SET_RETCODE): Always return + 'HANDLED'. This fixes some confusion when interrupt chaining. + +2000-05-15 Hugo Tyson + + * include/uit_ifnc.h (cyg_uitron_dsr): make this be extern "C" + always; it went wrong when uitron funcs are inline or C++. + + * src/uit_ifnc.cxx (CYGIMP_UITRON_INLINE_FUNCS): When [re]defining + this, match what CDL defined. Warnings--; + +2000-05-08 Jesper Skov + + * tests/testintr.cxx (attach_isr, detach_isr): Don't check for + clean vector after a detach when chaining is enabled. + +2000-03-28 Jesper Skov + + * tests/testintr.cxx: Synchronize with clock before making timer + measurement. + +2000-03-28 John Dallaway + + * cdl/uitron.cdl: + + Adjust documentation URLs. + +2000-03-22 Jesper Skov + + * include/uit_ifnc.h (ret_int): Fix compiler warning. + +2000-03-13 Jesper Skov + + * tests/testintr.cxx: Don't try to disable clock on PowerPC. + +2000-03-03 Hugo Tyson + + * tests/testintr.cxx (task1): Only test ena_int() and dis_int() + for E_PAR if CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS. + +2000-02-28 Hugo Tyson + + * include/uit_func.h: add ena_int() and dis_int(). + + * include/uit_func.inl (dis_int): New function added. + (ena_int): New function added. + + * tests/testintr.cxx (task1): Add a test of ena_int() and + dis_int(); easiest done here because we have an interrupt number - + for the clock - in our hands here already for the rest of the + test. + +2000-02-02 Jesper Skov + + * tests/testintr.cxx: Don't output DELAYLOCKSCHED quite so often + on synthetic target. + +2000-01-31 Hugo Tyson + + * tests/testintr.cxx (CHECK_TID): Test that get_tid() returns 0 in + ISR context ie. non-task portion. + + * include/uit_func.inl (get_tid): Check the sched lock for + non-task portions, ie. ISR/DSR will have the scheduler locked. + +2000-01-31 Simon FitzMaurice + * compat/uitron/current/cdl/uitron.cdl + + Adjust help URLs in line with new doc layout. + +2000-01-28 Simon FitzMaurice + * compat/uitron/current/cdl/uitron.cdl + + Adjust help URLs in line with new doc layout. + +2000-01-28 Jonathan Larmour + + * tests/testintr.cxx (DELAYLOCKSCHED): When in long testing loops, + occasionally output a message to show the test is still alive + +2000-01-26 Hugo Tyson + + * include/pkgconf/uitron.h: Add new option + CYGSEM_UITRON_TIME_IS_MILLISECONDS to control just what it says. + + * include/uit_func.inl (CYG_UITRON_TIME_UIT_TO_SYS32): et al; new + macros optionally to convert to/from milliSeconds if option + CYGSEM_UITRON_TIME_IS_MILLISECONDS is set. + + * src/uit_func.cxx: Initialize Cyg_Clock::converter type objects + if the time unit is set to milliSeconds. + + * cdl/uitron.cdl: Add new option + CYGSEM_UITRON_TIME_IS_MILLISECONDS to control just what it says. + + Add an include of the kernel config file to the generated + pkgconf/uitron.h: tests at the very least need it! This is a + correct thing to do because the kernel config defines a lot of the + semantics of the uITRON layer, as well as being needed for + backward compatibility. + + Also add uit_ifnc.cxx to the files that need compiling. Due to + the previous screwup, no testing has been applied to the uITRON + system under CDL, because it thought the kernel was absent, so + this had not been detected. Doh. + +2000-01-25 Jesper Skov + + * tests/testintr.cxx (cyg_start): externC addded. + +2000-01-19 Hugo Tyson + + * cdl/*.cdl: Add descriptions to a number of options &c which were + lacking same, also tidied up other typos as noticed en passant. + +1999-11-09 Jonathan Larmour + + * src/uit_objs.cxx: Make the stack size failsafe be tested against + the minimum stack size, not the typical one. + +1999-11-03 John Dallaway + + * cdl/uitron.cdl: Define tests. + +1999-10-07 John Dallaway + + * cdl/uitron.cdl: Specify radio buttons using CDL interfaces. + +1999-09-06 Jonathan Larmour + + * include/uit_objs.hxx (CYG_UITRON_OBJS_INIT_PRIORITY): Revert the + below change - we may still be shipping antiquated compilers to + customers. Sigh. + +1999-09-02 Hugo Tyson + + * include/uit_objs.hxx (CYG_UITRON_OBJS_INIT_PRIORITY): Enable + using init priority on uitron objects, now that the compilers all + support it fully. AFAI can tell from a quite broad experiment. + +1999-09-01 Hugo Tyson + + * tests/testintr.cxx (attach_isr): Make it all work: my chosen + default interrupt "level" of 0 means make no interrupts on the + tx39 ;-( oh well. Made the whole test simulator-friendly ie. much + shorter, made the output more friendly to me. + +1999-08-26 Hugo Tyson + + * cdl/uitron.cdl (CYGNUM_UITRON_ISR_ACTION_QUEUESIZE): add a + "default_value 32" - ooops. + +1999-08-26 Hugo Tyson + + * cdl/uitron.cdl: Add configury for lovely new interrupt-safe + functions: just "try immediate execution" [is the sched lock one?] + and queue size. + + * include/pkgconf/uitron.h: Add configury for lovely new + interrupt-safe functions: just "try immediate execution" [ie. if + the sched lock is one] and queue size. + + * include/uit_ifnc.inl: Respond to general configury wrt the + presence of semas, flags, mboxes: only define the ixxx_yyy() + function if the corresponding xxx_yyy() func exists. Remove the + static definitions of the configuration symbols. + + * src/uit_ifnc.cxx: Respond to general configury wrt the presence + of semas, flags, mboxes: the functions called may not exist! + +1999-08-25 Hugo Tyson + + * include/uit_ifnc.h: New file. Prototypes of interrupt-safe + ixxx_yyy() style functions as a porting/backwards-compatibility + aid. Prototype of a suitable DSR to mate with an ISR that uses + them too. + + * include/uit_ifnc.inl: New file. Bodies for possible inlining of + the ixxx_yyy() style functions; organized much like the standard + uITRON functions. + + * src/uit_ifnc.cxx: New file. Implementation of the DSR provided, + plus concrete instantiations of the ixxx_yyy() style functions. + + * tests/testintr.cxx: New file. Test for the ixxx_yyy() functions + newly provided above. Rather unpleasant: it is necessary to break + type-safety to get access to the kernel's interrupt object that + drives the realtime clock. Perhaps a neater way will follow. + + * tests/PKGconf.mak (TESTS): Add new testcase testintr.cxx + * src/PKGconf.mak (COMPILE): Add new source file uit_ifnc.cxx + +1999-08-17 John Dallaway + + * cdl/uitron.cdl: Implement radio buttons using + "FIXME radio" hack in description field for now. + +1999-07-30 John Dallaway + + * cdl/uitron.cdl: Tidy display string capitalisation. + +1999-05-26 Jesper Skov + + * tests/testcx7.cxx: Include new stackmon header. + +1999-05-20 Hugo Tyson + + * tests/testcx7.cxx (task1): Add some statistics dumping about + stack usage; since this is quite a long and arduous test. This + just helps en passant with testing the interrupt stack work that's + been happening recently. C++ only, so not for test7. + +1999-05-17 Hugo Tyson + + * include/uit_func.inl (ter_tsk): Only up the priority of the + killee if priorities are not unique or we are not already + elevated. This is to prevent asserts with the bitmap scheduler. + (chg_pri): Support a level X feature, pri zero => reset to the + thread's initial priority. + +1999-05-14 Hugo Tyson + + * include/uit_objs.hxx: object array declaration macro now + contains constructor priority ordering rune; if 0'd out pending + 99r1 compiler cutover. + +1999-04-23 Hugo Tyson + + * tests/testcx7.cxx: T2_MALLOC definition; only make it smaller + than the main consumer malloc if coaleasing is enabled, otherwise + the mempool cannot allocate blocks for the consumer for next time. + Fixes PR 18817 - only a random perm disable coalescence. + + * tests/test7.c: Ditto. + +1999-04-15 John Dallaway + + * include/pkgconf/uitron.h: Tidy display string capitalization. + +1999-04-09 Hugo Tyson + + * include/uit_func.inl (dis_dsp): Remove bad old code which used + to lock the scheduler to implement dis_dsp() and ena_dsp() - which + also stopped the clock, for example. Instead change the calling + thread's priority to 0 internally so that it cannot be preempted + by uITRON threads at least, whose priorities are 1--N. Same + applies to loc/unl_cpu(). Save the "real" priority in a static, + and take notice of it everywhere relevant, such as thread and + system state inquiries, changing (our own) priority, checking for + dispatch enabled in sleeping calls, and so on. + + * src/uit_func.cxx: New variable cyg_uitron_dis_dsp_old_priority + for holding the "real" priority of a thread whilst we change our + priority to zero (the highest) to prevent dispatching in dis_dsp() + or loc_cpu(). + + * include/uit_func.inl (get_tid): Return 0 for the task id if not + in a uITRON thread, this is better conformance to the spec. + +1999-03-22 Hugo Tyson + + * src/uit_objs.cxx: + Use CYGNUM_HAL_STACK_SIZE_TYPICAL for the stack size instead of + CYGNUM_HAL_MINIMUM_STACK_SIZE. + +1999-02-23 Jonathan Larmour + + * tests/test1.c, tests/test2.c, tests/test3.c, tests/test4.c, + tests/test5.c, tests/test6.c, tests/test7.c, tests/test8.c, + tests/test9.c, tests/testcxx.cxx, tests/testcx2.cxx, + tests/testcx3.cxx, tests/testcx4.cxx, tests/testcx5.cxx, + tests/testcx6.cxx, tests/testcx7.cxx, tests/testcx8.cxx, + tests/testcx9.cxx: + Change all non-applicable cases to use CYG_TEST_NA rather than + CYG_TEST_PASS/CYG_TEST_EXIT + +1999-02-22 Hugo Tyson + + * src/uit_objs.cxx: Eeeek! Previous fix was bogus: the override + was too late in the file to take effect. The declaration of the + objects (including stacks) is moved to below the override CPP + runes. + +1999-02-12 Hugo Tyson + + * src/uit_objs.cxx (CYG_UITRON_DECL): + Override CYGNUM_UITRON_STACK_SIZE if CYGNUM_HAL_MINIMUM_STACK_SIZE + demands it. + + * include/pkgconf/uitron.h (CYGNUM_UITRON_STACK_SIZE): + Document that this option can be overridden by HALs demands. + +1999-02-02 Jesper Skov + PR 18968 + * tests/test2.c (task1): + * tests/testcx2.cxx (task1): + Reduce run time on SIM. + +1999-01-26 Jesper Skov + PR 18788 + * tests/test4.c (task1): + * tests/testcx4.cxx (task1): + Extend timeouts when running on HW to avoid failures due to + overhead of GDB interaction. + +1999-01-25 Jesper Skov + PR 18576 + * include/pkgconf/uitron.h (CYGDAT_UITRON_SEMA_INITIALIZERS): + Let default initializers have values that don't cause tests to + fail. + +1998-11-25 Hugo Tyson + + * include/uit_func.inl (del_xxx &c): + Make error returns more consistent; E_NOEXS rather than E_OBJ if + the object disappeared during a race. + +1998-11-19 Hugo Tyson + + * src/uit_func.cxx (SET_UP_PTRS): + PR 17999; work around codegen bug on tx39 with -Os. + The code is better with the fix regardless, so it's got no + downside. Explicitly condition whether to run a follow-on loop + rather than letting the for-loop sort it out itself. + +1998-11-16 Hugo Tyson + + * tests/testcx7.cxx (check_waitstate): + Add a routine to check the reported waiting state of the synch + object in question, and call it as necessary. This only added to + the C++ version of the test for enhanced coverage, in case the + enquiry call perturbs the object state; having both versions + present is better. This checks a very recent fix to + kernel...thread.cxx (1998-10-27). + +1998-10-21 Hugo Tyson + + * src/uit_func.cxx: + Provide weakly named dummies for task[1-4], which are the defaults + referred to by the task array, so that the uITRON system can be + initialized even when no uITRON tasks have been provided (so long + as no other changes to the task init configury have been made) + This does not pollute the namespace, for these are weak symbols. + Changing them to cyg_uitron_task... would be possible, but it + carries the false implication that those are cygnus names, when + they are really entirely up to the user. + + * tests/test[123456789].c: + * tests/testcxx.cxx: + * tests/testcx[23456789].cxx: + Undo the previous change: remove dummies for task[1-4] when we + decide not to test anything, they will be provided with weak names + regardles in src/uit_func.cxx. + +1998-10-20 Hugo Tyson + + * tests/test[123456789].c: + * tests/testcxx.cxx: + * tests/testcx[23456789].cxx: + Provide dummies for task[1-4] when we decide not to test anything, + to encourage correct linking. + +1998-10-16 Hugo Tyson + + * tests/testcx*.cxx (cyg_start): + [all the C++ tests] + changed cyg_start to externC so that it truly does override the + default one; this is needed for handling the "I cannot test in + this configuration" failures. Of course the C ones were C to + start with. + +1998-10-16 Hugo Tyson + + * tests/test[123456789].c: + * tests/testcxx.cxx: + * tests/testcx[23456789].cxx: + All tests are now much more self-configuring wrt turning off + if there are no uITRON objects of the right type to manipulate. + The huge (50-line) #if statement is arranged the way it is so that + clauses checking on each feature can be pasted in and out easily. + So yes, the "&& 1" at the end has a purpose. + + Here for the record is a table of feature versus test-used-in: + tsk :: 1 2 3 4 5 6 7 8 9 + sem :: 2 3 5 6 7 8 + flg :: 2 5 6 7 + mbx :: 2 5 6 7 + mpl :: 2 5 7 9 + mpf :: 2 5 7 9 + alm :: 4 + cyc :: 4 + + +1998-10-16 Hugo Tyson + + * tests/test9.c: + * tests/testcx9.cxx: + New tests, test create and delete of memory pools + +1998-10-15 Hugo Tyson + + * include/pkgconf/uitron.h: + Add configury for create/delete of memory pools. + Tidy up naming of initializer macros to use for non-existent + (initially) uITRON objects. + Improve comments in CDL-- info fields. + + * include/uit_func.h: + Add prototypes for cre/del_mpf/mpl(). + + * include/uit_func.inl: + Implement cre/del_mpf/mpl(). + + * src/uit_objs.cxx: + Support CYG_UIT_MEMPOOLFIXED_NOEXS/CYG_UIT_MEMPOOLVAR_NOEXS(...) + mempool construction macros for non-existent (initially) mempools. + Rename _NONE construction macros to _NOEXS which will make a lot + more sense to uITRON folks. + +1998-10-14 Hugo Tyson + + * include/pkgconf/uitron.h: + Add configury for create/delete of tasks. + + * include/uit_func.h: + Add prototypes for cre/del_tsk(); correct comment in exd_tsk(). + + * include/uit_func.inl: + Implement cre/del_tsk() and complete exd_tsk(). + Improve NULL/NADR checking on other cre/del calls. + + * src/uit_func.cxx (cyg_uitron_start): + Deal better with start tasks stuff, for task create/delete. + + * src/uit_objs.cxx: + Support CYG_UIT_TASK_NONE(...) task constructor for those tasks + which do not initially exist + + * tests/PKGconf.mak: + Add new tests test8.c, testcx[678].cxx to the build. + + * tests/test6.c: + Tidy comments, untabify. + + * tests/test7.c: + Tidy comments, untabify, test creation with NADR record pointer. + No impact from the new cre/del_tsk() functionality on test7, since + a task may only be deleted when it is dormant, so deletion is NOT + another way out of a waiting state. + + * tests/test8.c: + New test, tests cre_tsk() and del_tsk() and exd_tsk() ie. the + creation and deletion of tasks. + + * tests/testcx6.cxx: + * tests/testcx7.cxx: + * tests/testcx8.cxx: + New tests, C++ versions of tests 6, 7, and 8. + +1998-10-09 Hugo Tyson + + * tests/test7.c: + Test interactions with deleting objects (as applicable) and + killing, signalling and the like. Also test killing the task + after other treatments more generically. + + * tests/test6.c (task1): + Change "N/A:" to "N/A" in the exit message when we didn't actually + do any testing due to create/delete being disabled for all object + types. + +1998-10-08 Hugo Tyson + + In general, these changes are to support create/delete of uITRON + objects; this requires that an object can be destroyed whilst + there are threads waiting on it, and that they shall be awoken + with a specific return code E_DLT. The implementation uses an + array of pointers in addition to the array of objects: ptrs[N] + should either be NULL or &objs[N] in this version. That + restriction is not checked, in order that in future, true dynamic + allocation can be used, and ptrs[N] could point anywhere. The + implications of this are mainly in the area of getting the + addresses of objects, via the ptr array or from the object array? + The config of whether there is a ptr array is per object type. + + * include/pkgconf/uitron.h: + Configury of the existence or not of create/delete for object + type: initially only SEMAS, MBOXES, FLAGS. + Configury of the number of objects created initially, if cre/del + are enabled. + + * tests/test6.c: + * tests/test7.c: + * tests/PKGconf.mak: + Two new test programs (duh!): test6 tests create and delete of + SEMAS, MBOXES, FLAGS explicitly, for bad params handling, ability + to use after deletion and recreation &c &c. test7 tests the + semantics of sleeping on some synchronization primitive, permed + with suspension, signalling, killing, releasing and so forth. + Both will migrate into C++ versions also in future. + + * include/uit_func.h: + Enable cre/del_{mbx,flg,sem} prototypes. + + * include/uit_func.inl: + Implement cre/del_{mbx,flg,sem} depending on configury, and handle + the pointer arrays generally in other client routines. + + * include/uit_objs.hxx: + Define the pointer arrays for access to created objects. + + * include/uit_type.h: + Enable definitions of the structures used in create calls. + + * src/uit_func.cxx: + Initialization code for the pointer arrays, akin to the task + startup code. + + * src/uit_objs.cxx: + Instantiate the pointer arrays themselves. + + +1998-09-25 Bart Veer + + * include/pkgconf/uitron.h: + PR 17482: added #ifdef protection. If CYGPKG_UITRON_MEMPOOLFIXED + is not defined then the contained option + CYGNUM_UITRON_MEMPOOLFIXED may not be defined either. Ditto for + CYGNUM_UITRON_MEMPOOLVAR which suffers from the same problem. + And ditto for CYGPKG_UITRON_SEMAS + +1998-09-20 Mark Galassi + + * include/pkgconf/uitron.h: added one or two CDL doc strings. + +Tue Sep 15 19:12:28 1998 David Moore + + * include/pkgconf/uitron.h: Cleaned up comments. + +1998-09-12 Mark Galassi +small changes to the descriptive information in the uITRON CDL + +1998-09-12 Mark Galassi + + * include/pkgconf/uitron.h: small editing of the description + fields: renamed things like to NAME, so that it does not + confuse SGML when incorporated into the documentation. + Also added various "doc" fields to the CFG_DATA comments. + +Wed Sep 9 18:36:15 1998 Hugo Tyson + + * include/uit_func.inl: + * include/uit_objs.hxx: + * src/uit_objs.cxx: + Condition features on CYGPKG_UITRON_SEMAS [for example] as well as + 0 < CYG_UITRON_NUM( SEMAS ) so that we get warning free + compilation with no semas enabled. Ditto for flags, mboxes, + mempools fixed and variable, alarms and cyclics. + + * include/pkgconf/uitron.h: + Add a couple of requires statements from cyclics and alarms on the + kernel clock. + Also change some grammar after review. + Add an option (actually a pair, makes it better documentation IMO) + to require strict semantics from the kernel setup. + Add an option to control the optional sema initializer; it was + omitted since the editor way of configury used a #if 0. + +Fri Sep 4 17:54:29 1998 Hugo Tyson + + * include/pkgconf/uitron.h: + Remove redundant and now unnecessary defs of CYGPKG_UITRON. + +Wed Sep 2 19:06:17 1998 Hugo Tyson + + * include/uit_func.inl: + Memory pools and message boxes and flags + and cnt_sem2-type semaphores now all have absolute timeouts + instead of relative ones in the timely wait functions. + We add in the current time here first. + +Wed Sep 2 16:45:40 1998 Hugo Tyson + + * include/pkgconf/uitron.h (CYGDAT_UITRON_TASK_INITIALIZERS): + Use the new kernel thread initializer with priority and thread + name in it. + + * include/uit_func.inl: + * include/uit_objs.hxx: + * src/uit_func.cxx (cyg_uitron_start): + * src/uit_objs.cxx: + Our tasks are now Cyg_Threads rather than a derived class. + Original priorities of tasks are held in an array. An accessor + macro is used for the off-by-one nature of uitron IDs. The array + of original priorities is set up in cyg_uitron_start(), and + created in uit_objs.cxx. + +Wed Sep 2 15:15:26 1998 Hugo Tyson + + * include/pkgconf/uitron.h: + Comment more strongly in the 'description' that the number of + initializers better match the number of things specified. + +Tue Sep 1 19:00:02 1998 Hugo Tyson + + * include/uit_objs.hxx: + Do not include ; it is deprecated. + Instead, include only kernel headers that are needed. + + * include/uit_func.inl (ref_sys): + Use new kernel function Cyg_Interrupt::interrupts_enabled() + instead of a state variable. Tidy up associated code. + Include kernel headers that are needed because they were not + included in uit_objs.hxx for tidiness. + + * src/uit_func.cxx: + Elide state variable that used to be used for tracking interrupt + enabledness state. + + * tests/testcx5.cxx (task1): + * tests/test5.c (task1): + Test interrupt enable and disable stuff, and status reporting. + +Tue Sep 1 15:12:29 1998 Hugo Tyson + + * include/uit_func.inl (ref_mpf): + Change comment "ECC" to "eCos". + +1998-08-28 Bart Veer + + * include/uit_func.inl: + * tests/test1.c, tests/test2.c, tests/test3.c, tests/test4.c, + tests/test5.c, tests/testcxx.cxx, tests/testcx2.cxx, + tests/testcx3.cxx, tests/testcx4.cxx, tests/testcx5.cxx: + + Updated for new kernel configuration option symbol names + + +Fri Aug 28 09:21:55 1998 Jonathan Larmour + + * src/uit_func.cxx (cyg_uitron_start): + Remove call to Cyg_Scheduler::start() and adjust comments to + explain where to call it from + + * tests/test1.c, tests/test2.c, tests/test3.c, tests/test4.c, + tests/test5.c, tests/testcxx.cxx, tests/testcx2.cxx, + tests/testcx3.cxx, tests/testcx4.cxx, tests/testcx5.cxx: + Change the normal entry point at the top to be cyg_package_start() + under the new startup scheme. This overrides the default package + configuration and ensure cyg_uitron_start() gets called. + Change the "default" entry point at the bottom (when the test is + N/A for some reason) to cyg_start() under the new startup scheme. + +Wed Aug 26 18:20:47 1998 Hugo Tyson + + * include/pkgconf/uitron.h: + Initial version of cdl control statements for config options. + All very groovy, and looking good IMO. + A few FIX-MEs remain, no big deal. + +Mon Aug 24 19:05:52 1998 Hugo Tyson + + * include/pkgconf/uitron.h: + Change the names of config options to helpful, positive sense, and + tidy some of the names for inclusion in the GUI tool. Clean up + the namespace too. + + * include/uit_func.h: + * include/uit_func.inl: + * src/uit_func.cxx: + * src/uit_objs.cxx: + Configure according to new option names and object construction + macros. Simple changes but widespread. + + * tests/test[12345].c: + * tests/testcx[x2345].cxx: + Configure according to new option names. + Make it main( void ) to avoid a warning. + +Fri Aug 21 18:45:16 1998 Hugo Tyson + + * tests/testcx4.cxx (task1): + * tests/test4.c (task1): + * include/uit_func.inl (def_alm): + Tidy the alarm and timer funcs in the course of fixing a kernel + bug actually. Test the functionality affected by the kernel + change a bit more. + +Thu Aug 20 14:33:36 1998 Hugo Tyson + + * include/uit_func.inl (ref_alm): + Elide an unused variable following the previous change. + +Mon Aug 17 15:45:07 1998 Hugo Tyson + + * include/pkgconf/uitron.h: + Add the config option CYGSEM_UITRON_PARAMS_CHECK_NADR_ONLY. + + * tests/testcxx.cxx: + * tests/testcx2.cxx: + * tests/testcx4.cxx: + Avoid testing with NULL as a bad parameter when only NADR is + checked. (NADR does not cast to any-pointer in C++ so we don't + test it in these programs) Check for NADR various places as well + as NULL. + + * tests/test1.c (task1): + * tests/test2.c (task1): + * tests/test4.c (task1): + Avoid testing with NULL as a bad parameter when only NADR is + checked. Check for NADR various places as well as NULL, and test + NADR as a bad param as well as NULL. + + +Mon Aug 17 14:45:30 1998 Hugo Tyson + + * include/uit_func.inl: + PR# 16536: Check for dormant tasks various places; E_OBJ + must be returned. All this error checking rather bloats the code, + unfortunately. + + * tests/testcxx.cxx: + * tests/test1.c: + Test the new checks above. + +Fri Aug 14 17:41:35 1998 Hugo Tyson + + * include/uit_func.inl ([t]wai/pol_flg): + Check for zero in a wait-for-flag operation; such a wait can never + be awakened, and so should return E_PAR. + + * tests/testcx2.cxx (task1): + * tests/test2.c (task1): + Test the above new checking. + +Fri Jul 24 17:12:54 1998 Hugo Tyson + + PR#15865 + * include/uit_func.inl: return a bool (strictly 1 or 0) for wtsk + rather than -1 or zero as the spec implies. + ref_flg() ref_sem() only affected. + +Fri Jul 24 13:26:51 1998 Hugo Tyson + + PR#16531 + * include/uit_func.inl: return E_OBJ when (force)resuming a + non-suspended task. + * tests/test1.c: test for that error code. + * tests/testcxx.cxx: test for that error code. + +Fri Jul 24 13:02:46 1998 Hugo Tyson + + * Changelog: Initial ChangeLog entry. + + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/compat/uitron/v2_0/cdl/flags.cdl b/packages/compat/uitron/v2_0/cdl/flags.cdl new file mode 100644 index 00000000..d7d6b402 --- /dev/null +++ b/packages/compat/uitron/v2_0/cdl/flags.cdl @@ -0,0 +1,82 @@ +# ==================================================================== +# +# flags.cdl +# +# uITRON flags related configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: hmt +# Contributors: +# Date: 1999-07-07 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_option CYGNUM_UITRON_FLAGS { + display "Number of eventflags" + flavor data + legal_values 1 to 65535 + default_value 5 + description " + The number of uITRON eventflag objects present in the system. + Valid eventflag object IDs will range from 1 to this value." +} +cdl_component CYGPKG_UITRON_FLAGS_CREATE_DELETE { + display "Support create and delete" + flavor bool + default_value 1 + description " + Support eventflag create and delete operations (cre_flg, del_flg). + Otherwise all eventflags are created, up to the number specified above." + + cdl_option CYGNUM_UITRON_FLAGS_INITIALLY { + display "Number of eventflags created initially" + flavor data + legal_values 0 to 65535 + default_value 5 + description " + The number of uITRON eventflags initially created. + This number should not be more than the number + of eventflags in the system, though setting it to a large + value to mean 'all' is acceptable. + Initially, only eventflags numbered 1 to this number exist; + higher numbered ones must be created before use." + } +} diff --git a/packages/compat/uitron/v2_0/cdl/mboxes.cdl b/packages/compat/uitron/v2_0/cdl/mboxes.cdl new file mode 100644 index 00000000..74d3f59a --- /dev/null +++ b/packages/compat/uitron/v2_0/cdl/mboxes.cdl @@ -0,0 +1,82 @@ +# ==================================================================== +# +# mboxes.cdl +# +# uITRON mbox related configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: hmt +# Contributors: +# Date: 1999-07-07 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_option CYGNUM_UITRON_MBOXES { + display "Number of mailboxes" + flavor data + legal_values 1 to 65535 + default_value 4 + description " + The number of uITRON mailboxes present in the system. + Valid mailbox object IDs will range from 1 to this value." +} +cdl_component CYGPKG_UITRON_MBOXES_CREATE_DELETE { + display "Support create and delete" + flavor bool + default_value 1 + description " + Support mailbox create and delete operations (cre_mbx, del_mbx). + Otherwise all mailboxes are created, up to the number specified above." + + cdl_option CYGNUM_UITRON_MBOXES_INITIALLY { + display "Number of mailboxes created initially" + flavor data + legal_values 0 to 65535 + default_value 4 + description " + The number of uITRON mailboxes initially created. + This number should not be more than the number + of mailboxes in the system, though setting it to a large + value to mean 'all' is acceptable. + Initially, only mailboxes numbered 1 to this number exist; + higher numbered ones must be created before use." + } +} diff --git a/packages/compat/uitron/v2_0/cdl/mempoolfixed.cdl b/packages/compat/uitron/v2_0/cdl/mempoolfixed.cdl new file mode 100644 index 00000000..30d6ec2e --- /dev/null +++ b/packages/compat/uitron/v2_0/cdl/mempoolfixed.cdl @@ -0,0 +1,138 @@ +# ==================================================================== +# +# mempoolfixed.cdl +# +# uITRON fixed memory pool related configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: hmt +# Contributors: +# Date: 1999-07-07 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_option CYGNUM_UITRON_MEMPOOLFIXED { + display "Number of fixed-size memorypools" + flavor data + legal_values 1 to 65535 + default_value 3 + description " + The number of uITRON Fixed-Size + Memorypools present in the system. + Valid Fixed-Size Memorypool IDs will range + from 1 to this value." +} +cdl_component CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE { + display "Support create and delete" + flavor bool + default_value 1 + active_if (0 < CYGNUM_UITRON_MEMPOOLFIXED) + description " + Support fixed-size memory pool + create and delete operations + (cre_mpf, del_mpf). + Otherwise all fixed mempools are created, + up to the number specified above." + + cdl_option CYGNUM_UITRON_MEMPOOLFIXED_INITIALLY { + display "Number of fixed mempools created initially" + flavor data + legal_values 0 to 65535 + default_value 3 + description " + The number of fixed mempools initially created. + This number should not be more than the number + of fixed mempools in the system, though setting + it to a large value to mean 'all' is acceptable. + Initially, only fixed mempools numbered from + 1 to this number exist; + higher numbered ones must be created before use. + Whilst all mempools must be initialized to tell + the system what memory to use for each pool, + it is only useful to initialize the blocksize of + fixed mempools up to this number; + the blocksize for higher numbered ones + will be defined when they are created." + } +} +cdl_option CYGDAT_UITRON_MEMPOOLFIXED_EXTERNS { + display "Externs for initialization" + flavor data + default_value {"static char fpool1[ 2000 ], \\\n\ + fpool2[ 2000 ], \\\n\ + fpool3[ 2000 ];"} + description " + Fixed mempool initializers may refer to external + objects such as memory for the pool to manage. + Use this option to define or declare any external + objects needed by the pool's static initializer below. + Example: create some memory for a mempool using + 'static char fpool1\[2000\];' + to set up a chunk of memory of 2000 bytes. + Note: this option is invoked in the 'outermost' context + of C++ source, where global/static objects are created; + it should contain valid, self-contained, C++ source." +} +cdl_option CYGDAT_UITRON_MEMPOOLFIXED_INITIALIZERS { + display "Static initializers" + flavor data + default_value {"CYG_UIT_MEMPOOLFIXED( fpool1, 2000, 20 ), \\\n\ + CYG_UIT_MEMPOOLFIXED( fpool2, 2000, 100 ), \\\n\ + CYG_UIT_MEMPOOLFIXED( fpool3, 2000, 500 ),"} + description " + Fixed block memory pools should be statically + initialized: enter a list of initializers + separated by commas, one per line. + An initializer is + 'CYG_UIT_MEMPOOLFIXED(ADDR,SIZE,BLOCK)' + where addr is the address of memory to manage, + size is the total size of that memory, and + block is the block size for allocation by the pool. + If create and delete operations are supported, + initializers of the form + 'CYG_UIT_MEMPOOLFIXED_NOEXS(ADDR,SIZE)' should be + used for pools which are not initially created, to tell + the system what memory to use for each pool. + Note: this option is invoked in the context of a + C++ array initializer, between curly brackets. + Ensure that the number of initializers here exactly + matches the total number of fixed pools specified." +} diff --git a/packages/compat/uitron/v2_0/cdl/mempoolvar.cdl b/packages/compat/uitron/v2_0/cdl/mempoolvar.cdl new file mode 100644 index 00000000..59456131 --- /dev/null +++ b/packages/compat/uitron/v2_0/cdl/mempoolvar.cdl @@ -0,0 +1,129 @@ +# ==================================================================== +# +# mempoolvar.cdl +# +# uITRON variable memory pool related configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: hmt +# Contributors: +# Date: 1999-07-07 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_option CYGNUM_UITRON_MEMPOOLVAR { + display "Number of variable-size memory pools" + flavor data + legal_values 1 to 65535 + default_value 3 + description " + The number of uITRON Variable-Size Memorypools present in the system. + Valid Variable-Size Memorypool IDs will range from 1 to this value." +} +cdl_component CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE { + display "Support create and delete" + flavor bool + default_value 1 + active_if (0 < CYGNUM_UITRON_MEMPOOLVAR) + description " + Support variable-size memory pool create and delete operations + (cre_mpl, del_mpl). Otherwise all variable-size mempools are created, + up to the number specified above." + + cdl_option CYGNUM_UITRON_MEMPOOLVAR_INITIALLY { + display "Number of variable-size mempools created initially" + flavor data + legal_values 0 to 65535 + default_value 3 + description " + The number of variable-size mempools initially created. + This number should not be more than the number + of variable mempools in the system, though setting + it to a large value to mean 'all' is acceptable. + Initially, only variable mempools numbered from + 1 to this number exist; + higher numbered ones must be created before use. + All mempools must be initialized to tell + the system what memory to use for each pool." + } +} +cdl_option CYGDAT_UITRON_MEMPOOLVAR_EXTERNS { + display "Externs for initialization" + flavor data + default_value {"static char vpool1[ 2000 ], \\\n\ + vpool2[ 2000 ], \\\n\ + vpool3[ 2000 ];"} + description " + Variable mempool initializers may refer to external + objects such as memory for the pool to manage. + Use this option to define or declare any external + objects needed by the pool's static initializer below. + Example: create some memory for a mempool using + 'static char vpool1\[2000\];' + to set up a chunk of memory of 2000 bytes. + Note: this option is invoked in the 'outermost' context + of C++ source, where global/static objects are created; + it should contain valid, self-contained, C++ source." +} +cdl_option CYGDAT_UITRON_MEMPOOLVAR_INITIALIZERS { + display "Static initializers" + flavor data + default_value {"CYG_UIT_MEMPOOLVAR( vpool1, 2000 ), \\\n\ + CYG_UIT_MEMPOOLVAR( vpool2, 2000 ), \\\n\ + CYG_UIT_MEMPOOLVAR( vpool3, 2000 ),"} + description " + Variable block memory pools should be statically + initialized: enter a list of initializers + separated by commas, one per line. + An initializer is + 'CYG_UIT_MEMPOOLVAR(ADDR,SIZE)' + where addr is the address of memory to manage, and + size is the total size of that memory. + If create and delete operations are supported, + initializers of the form + 'CYG_UIT_MEMPOOLVAR_NOEXS(ADDR,SIZE)' should be + used for pools which are not initially created, to tell + the system what memory to use for each pool. + Note: this option is invoked in the context of a + C++ array initializer, between curly brackets. + Ensure that the number of initializers here exactly + matches the total number of variable pools specified." +} diff --git a/packages/compat/uitron/v2_0/cdl/semas.cdl b/packages/compat/uitron/v2_0/cdl/semas.cdl new file mode 100644 index 00000000..9e0fb0f4 --- /dev/null +++ b/packages/compat/uitron/v2_0/cdl/semas.cdl @@ -0,0 +1,115 @@ +# ==================================================================== +# +# semas.cdl +# +# uITRON semaphore related configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: hmt +# Contributors: +# Date: 1999-07-07 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_option CYGNUM_UITRON_SEMAS { + display "Number of semaphores" + flavor data + legal_values 1 to 65535 + default_value 3 + description " + The number of uITRON semaphores present in the system. + Valid semaphore object IDs will range from 1 to this value." +} +cdl_component CYGPKG_UITRON_SEMAS_CREATE_DELETE { + display "Support create and delete" + flavor bool + default_value 1 + description " + Support semaphore create and delete operations (cre_sem, del_sem). + Otherwise all semaphores are created, up to the number specified + above." + + cdl_option CYGNUM_UITRON_SEMAS_INITIALLY { + display "Number of semaphores created initially" + flavor data + legal_values 0 to 65535 + default_value 3 + description " + The number of uITRON semaphores initially created. + This number should not be more than the number + of semaphores in the system, though setting it to a large + value to mean 'all' is acceptable. + Initially, only semaphores numbered 1 to this number exist; + higher numbered ones must be created before use. + It is only useful to initialize semaphores up to this number; + higher numbered ones must be created in order to use them, + and so they will be re-initialized." + } +} +cdl_component CYGPKG_UITRON_SEMAS_ARE_INITIALIZED { + display "Initialize semaphore counts" + flavor bool + default_value 0 + description " + Initialize semaphores to specific count values. + Otherwise semaphores are initialized with the count + set to zero." + + cdl_option CYGDAT_UITRON_SEMA_INITIALIZERS { + display "Static initializers" + parent CYGPKG_UITRON_SEMAS_ARE_INITIALIZED + flavor data + default_value {"CYG_UIT_SEMA( 0 ),\ + CYG_UIT_SEMA( 0 ),\ + CYG_UIT_SEMA( 0 )"} + description " + A list of initializers separated by commas, + one per line. + An initializer is 'CYG_UIT_SEMA(INITIAL-COUNT)' + or 'CYG_UIT_SEMA_NOEXS' for slots above the number + initially to be created, when create and delete + operations are supported. + Note: this option is invoked in the context of a + C++ array initializer, between curly brackets. + Ensure that the number of initializers here exactly + matches the total number of semaphores specified." + } +} diff --git a/packages/compat/uitron/v2_0/cdl/tasks.cdl b/packages/compat/uitron/v2_0/cdl/tasks.cdl new file mode 100644 index 00000000..fd965ca0 --- /dev/null +++ b/packages/compat/uitron/v2_0/cdl/tasks.cdl @@ -0,0 +1,164 @@ +# ==================================================================== +# +# tasks.cdl +# +# uITRON task related configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: hmt +# Contributors: +# Date: 1999-07-07 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_option CYGNUM_UITRON_TASKS { + display "Number of tasks" + flavor data + legal_values 1 to 65535 + default_value 4 + description " + The number of uITRON tasks present in the system. + Valid task object IDs will range from 1 to this value." +} +cdl_option CYGNUM_UITRON_START_TASKS { + display "Start tasks" + flavor data + legal_values 0 to 65535 + default_value 1 + description " + The number of uITRON tasks to start automatically. + Tasks from 1 to this value will be started + at the beginning of application execution. + A value of zero here means to start them all. + Tasks started in this way have a start code of + zero, as if they were started by sta_tsk(i,0). + If create and delete operations are supported, + this number should be no greater than the number + of tasks created initially." +} +cdl_component CYGPKG_UITRON_TASKS_CREATE_DELETE { + display "Support create and delete" + flavor bool + default_value 1 + description " + Support task create and delete operations (cre_tsk, del_tsk). + Otherwise all tasks are created, up to the number specified above." + + cdl_option CYGNUM_UITRON_TASKS_INITIALLY { + display "Number of tasks created initially" + flavor data + legal_values 1 to 65535 + default_value 4 + description " + The number of uITRON tasks initially created. + This number should not be more than the number + of tasks in the system, though setting it to a large + value to mean 'all' is acceptable. + Initially, only tasks numbered 1 to this number exist; + higher numbered ones must be created before use." + } +} +cdl_option CYGNUM_UITRON_STACK_SIZE { + display "Default stack size" + flavor data + legal_values 128 to 0x7FFFFFFF + default_value 2048 + description " + Define a default stack size for uITRON tasks, + for use in the initialization options below. + This will be overridden where it is used if the + architectural HAL requires a minimum stack size + to handle interrupts correctly." +} +cdl_option CYGDAT_UITRON_TASK_EXTERNS { + display "Externs for initialization" + flavor data + default_value {"extern \"C\" void task1( unsigned int ); \\\n\ + extern \"C\" void task2( unsigned int ); \\\n\ + extern \"C\" void task3( unsigned int ); \\\n\ + extern \"C\" void task4( unsigned int ); \\\n\ + static char stack1[ MAX(CYGNUM_UITRON_STACK_SIZE, CYGNUM_HAL_STACK_SIZE_MINIMUM) ], \\\n\ + stack2[ MAX(CYGNUM_UITRON_STACK_SIZE, CYGNUM_HAL_STACK_SIZE_MINIMUM) ], \\\n\ + stack3[ MAX(CYGNUM_UITRON_STACK_SIZE, CYGNUM_HAL_STACK_SIZE_MINIMUM) ], \\\n\ + stack4[ MAX(CYGNUM_UITRON_STACK_SIZE, CYGNUM_HAL_STACK_SIZE_MINIMUM) ];"} + description " + Task initializers may refer to external objects + such as memory for stack or functions to call. + Use this option to define or declare any external + objects needed by the task static initializer below. + Example: create some memory for a stack using + 'static char stack1\[CYGNUM_UITRON_STACK_SIZE\];' + to set up a chunk of memory of the default stack size. + Note: this option is invoked in the 'outermost' context + of C++ source, where global/static objects are created; + it should contain valid, self-contained, C++ source." +} +cdl_option CYGDAT_UITRON_TASK_INITIALIZERS { + display "Static initializers" + flavor data + default_value {"CYG_UIT_TASK( \"t1\", 1, task1, &stack1, MAX(CYGNUM_UITRON_STACK_SIZE, CYGNUM_HAL_STACK_SIZE_MINIMUM) ), \\\n\ + CYG_UIT_TASK( \"t2\", 2, task2, &stack2, MAX(CYGNUM_UITRON_STACK_SIZE, CYGNUM_HAL_STACK_SIZE_MINIMUM) ), \\\n\ + CYG_UIT_TASK( \"t3\", 3, task3, &stack3, MAX(CYGNUM_UITRON_STACK_SIZE, CYGNUM_HAL_STACK_SIZE_MINIMUM) ), \\\n\ + CYG_UIT_TASK( \"t4\", 4, task4, &stack4, MAX(CYGNUM_UITRON_STACK_SIZE, CYGNUM_HAL_STACK_SIZE_MINIMUM) ),"} + description " + Tasks must be statically + initialized: enter a list of initializers + separated by commas, one per line. + An initializer is + 'CYG_UIT_TASK(NAME,PRIO,FUNC,STACK,SIZE)' + where name is a quoted string to name the task, + prio is the initial priority of the task, + func is the name of the entry point, + stack is the address of the task's stack, + and size is the size of the task's stack. + When create and delete operations are supported, + 'CYG_UIT_TASK_NOEXS(NAME,STACK,SIZE)' should be + used for tasks which are not initially created, + in order to tell the system what memory to use + for stacks when these tasks are created later on. + Using 'CYGNUM_UITRON_STACK_SIZE' for size + is recommended, to use the option defined above, + so long as that truly is the size of your stack(s). + Note: this option is invoked in the context of a + C++ array initializer, between curly brackets. + Ensure that the number of initializers here exactly + matches the number of tasks specified." +} diff --git a/packages/compat/uitron/v2_0/cdl/uitron.cdl b/packages/compat/uitron/v2_0/cdl/uitron.cdl new file mode 100644 index 00000000..e142800c --- /dev/null +++ b/packages/compat/uitron/v2_0/cdl/uitron.cdl @@ -0,0 +1,437 @@ +# ==================================================================== +# +# uitron.cdl +# +# uITRON configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): bartv +# Original data: hmt +# Contributors: +# Date: 1999-06-13 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_UITRON { + display "uITRON compatibility layer" + include_dir cyg/compat/uitron + doc ref/compat-uitron.html + requires CYGPKG_KERNEL + description " + eCos supports a uITRON Compatibility Layer, providing + full Level S (Standard) compliance with Version 3.02 of + the uITRON Standard, plus many Level E (Extended) features. + uITRON is the premier Japanese embedded RTOS standard." + + compile uit_func.cxx uit_ifnc.cxx uit_objs.cxx + + # ------------------------------------------------------------------------ + # Conformance check + # ------------------------------------------------------------------------ + cdl_interface CYGINT_UITRON_CONFORMANCE { + requires 1 == CYGINT_UITRON_CONFORMANCE + } + + cdl_option CYGIMP_UITRON_STRICT_CONFORMANCE { + display "Check strict uITRON standards conformance" + default_value 0 + requires CYGVAR_KERNEL_COUNTERS_CLOCK + requires CYGSEM_KERNEL_SCHED_MLQUEUE + requires !CYGSEM_KERNEL_SCHED_TIMESLICE + requires CYGFUN_KERNEL_THREADS_TIMER + implements CYGINT_UITRON_CONFORMANCE + description " + Require the rest of the system configuration + to match the needs of strict uITRON standards conformance. + This option can only be set if the rest of the system is + configured correctly for uITRON semantics, for example + there must be a realtime clock, a suitable scheduler, and no + timeslicing. + Of course a system without this selected can be completely + conformant; this is here to help you check." + } + cdl_option CYGIMP_UITRON_LOOSE_CONFORMANCE { + display "System configuration overrides uITRON" + default_value 1 + implements CYGINT_UITRON_CONFORMANCE + description " + Do not require the rest of the system configuration + to match the needs of strict uITRON standards conformance. + For example a bitmap scheduler, or timeslicing, can be used + with the uITRON functions, but such an environment is not + strictly conformant with the uITRON specification. + Of course a system with this selected can be completely + conformant; but it is up to you to configure it correctly." + } + + # ------------------------------------------------------------------------ + # uITRON FUNCTION CALLS + # ------------------------------------------------------------------------ + cdl_option CYGIMP_UITRON_INLINE_FUNCS { + display "Inline functions" + default_value 0 + description " + If compiling your application with a C++ compiler, + uITRON functions can be inline: set this to make it so. + Inlining functions often increases execution speed, + though possibly at the cost of a larger executable, + depending on what functions are used. + Do NOT set this if compiling your application + in plain C." + } + + cdl_option CYGIMP_UITRON_CPP_OUTLINE_FUNCS { + display "C++ function names" + default_value 0 + description " + If compiling your application with a C++ compiler, + uITRON functions can be given C++ style mangled names: + set this to make it so. + This option may make debugging your program easier, + depending on your development environment. + Do NOT set this if compiling your application + in plain C." + } + + cdl_option CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS { + display "Return error codes for bad params" + default_value 1 + description " + When an application is fully debugged there is no need + to check for bad parameters on every system call, for those + parameters which are typically pointers or constants. + Removing the checking code saves space + and improves performance: set this to make it so. + When this option is set, the correctness of parameters + is asserted using CYG_ASSERT() which compiles to + nothing in a non-debug configuration." + } + + cdl_option CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR { + display "NULL is a good pointer" + default_value 0 + description " + uITRON deliberately defines the constant NADR (-1) for + use as an invalid memory address. + The value -1 is chosen to allow working in microcontrollers + which have real memory at address zero, the traditional 'C' + NULL pointer. + By default, uITRON functions check for both NULL and NADR as + bad addresses: set this option to prevent checking for + NULL and allow pointers to address zero to be used." + } + + # ------------------------------------------------------------------------ + # uITRON KERNEL OBJECTS + # ------------------------------------------------------------------------ + cdl_component CYGPKG_UITRON_SEMAS { + display "Semaphores" + flavor bool + default_value 1 + description " + uITRON Semaphore objects are used with functions + named xxx_sem(); they support traditional semaphore + semantics." + + script semas.cdl + } + + cdl_component CYGPKG_UITRON_MBOXES { + display "Mailboxes" + flavor bool + default_value 1 + description " + uITRON Mailbox objects are used with functions + named xxx_msg() and xxx_mbx(); they support + passing addresses (of 'messages') between tasks + in a safe manner." + + script mboxes.cdl + } + + cdl_component CYGPKG_UITRON_FLAGS { + display "Eventflags" + flavor bool + default_value 1 + description " + uITRON Eventflag objects are used with functions + named xxx_flg(); they support communication between + tasks by means of setting and clearing bits in a word + or flag value. + Waiting for all or any of a set of bits is supported." + + script flags.cdl + } + + # ------------------------------------------------------------------------ + # uITRON TASKS + # ------------------------------------------------------------------------ + cdl_component CYGPKG_UITRON_TASKS { + display "Tasks" + flavor none + description " + uITRON Tasks are the basic blocks of multi-tasking + in the uITRON world; they are threads or lightweight + processes, sharing the address space and the CPU. + They communicate using the primitives outlined above. + Each has a stack, an entry point (a C or C++ function), + and (where appropriate) a scheduling priority." + + script tasks.cdl + } + + # ------------------------------------------------------------------------ + # Memory Pools, both fixed and variable block + # ------------------------------------------------------------------------ + cdl_component CYGPKG_UITRON_MEMPOOLFIXED { + display "Fixed-size memorypools" + flavor bool + default_value 1 + requires CYGPKG_MEMALLOC + description " + uITRON supports memory pools for dynamic, task-safe + memory allocation. + Two kinds are supported, fixed-size and variable-size. + There may be multiple of each + type of pool, each with differing characteristics. + This option controls whether there are any fixed-size + memorypools in the system. + A fixed-size memorypool allocates blocks of memory of + its preset fixed size and none other." + + script mempoolfixed.cdl + } + + cdl_component CYGPKG_UITRON_MEMPOOLVAR { + display "Variable-size memorypools" + flavor bool + default_value 1 + requires CYGPKG_MEMALLOC + description " + uITRON supports memory pools for dynamic, task-safe + memory allocation. + Two kinds are supported, fixed-size and variable-size. + There may be multiple of each + type of pool, each with differing characteristics. + This option controls whether there are any variable-size + memorypools in the system. + A variable-size memorypool allocates blocks of memory of + any size requested, resources permitting." + + script mempoolvar.cdl + } + + # ------------------------------------------------------------------------ + # One-shot Alarm and Cyclic Alarm handlers: + # ------------------------------------------------------------------------ + + cdl_option CYGSEM_UITRON_TIME_IS_MILLISECONDS { + display "uITRON time unit is mS" + flavor bool + default_value 0 + active_if CYGVAR_KERNEL_COUNTERS_CLOCK + description " + Setting this option enables a conversion feature so that + time parameters to uITRON APIs are converted from milliSeconds + to whatever the eCos kernel real-time clock's units are, + or vice versa. + If this option is not set, time parameters are expressed in + kernel clock ticks." + } + + cdl_component CYGPKG_UITRON_ALARMS { + display "Alarm handlers" + flavor bool + default_value 1 + requires CYGVAR_KERNEL_COUNTERS_CLOCK + description " + uITRON Alarm Handlers are used with functions + named def_alm() and ref_alm(); they support + simple timing, with a function callback + at the end of the timed period." + + + cdl_option CYGNUM_UITRON_ALARMS { + display "Number of alarm handlers" + flavor data + legal_values 1 to 65535 + default_value 3 + description " + The number of uITRON alarm + handlers present in the system. + Valid alarm handler numbers will range + from 1 to this value." + } + } + + cdl_component CYGPKG_UITRON_CYCLICS { + display "Cyclic handlers" + flavor bool + default_value 1 + requires CYGVAR_KERNEL_COUNTERS_CLOCK + description " + uITRON Cyclic Handlers are used with functions + named xxx_cyc(); they support timing + with a periodic function callback that + can be dynamically turned on or off, and + resynchronized with external events." + + cdl_option CYGNUM_UITRON_CYCLICS { + display "Number cyclic handlers" + flavor data + legal_values 1 to 65535 + default_value 3 + description " + The number of uITRON cyclics + handlers present in the system. + Valid cyclic handler numbers will range + from 1 to this value." + } + } + + # ------------------------------------------------------------------------ + # Interrupt-safe functions [ixxx_yyy()]: + # ------------------------------------------------------------------------ + cdl_component CYGPKG_UITRON_INTERRUPT_FUNCTIONS { + display "Interrupt-safe functions" + flavor none + description "The uITRON system provides some functions which may + safely be used within interrupt handlers. In eCos, this + means within ISRs, providing that the corresponding DSR is + associated with that interrupt. These functions are + typically named ixxx_yyy(), according to the uITRON + specification, for example isig_sem() corresponds to normal + function sig_sem()." + + cdl_option CYGSEM_UITRON_ISRFUNCS_TRY_IMMEDIATE_EXECUTION { + display "Execute in ISR if safe" + parent CYGPKG_UITRON_INTERRUPT_FUNCTIONS + flavor bool + default_value 1 + description " + These functions of necessity maintain a queue of + operations requested for deferred execution. However, + during an interrupt, it may be safe to perform scheduling + operations. If this option is set, the interrupt-safe + functions will have effect there and then if it is indeed + safe, rather than queueing a request to perform the + operation in the DSR." + } + cdl_option CYGNUM_UITRON_ISR_ACTION_QUEUESIZE { + display "Deferred operation queue size" + parent CYGPKG_UITRON_INTERRUPT_FUNCTIONS + flavor data + legal_values 4 8 16 32 64 128 256 + default_value 32 + description "These functions of necessity maintain a queue of + operations requested for deferred execution. This option + controls the queue size. It must be a power of two for + implementation reasons." + } + } + + # ------------------------------------------------------------------------ + # uITRON VERSION INFORMATION + # ------------------------------------------------------------------------ + cdl_component CYGPKG_UITRON_VERSION { + display "Version information" + flavor none + description " + The get_ver() uITRON system call returns + several version related values describing + the vendor, product and CPU in question + as well as the version of the uITRON + standard supported. + These values may be specified here." + + script version.cdl + } + + define_proc { + puts $::cdl_header "/***** proc output start *****/" + puts $::cdl_header "#include " + puts $::cdl_header "#include " + puts $::cdl_header "/***** proc output end *****/" + } + + cdl_component CYGPKG_UITRON_OPTIONS { + display "uITRON build options" + flavor none + description " + Package specific build options including control over + compiler flags used only in building this package, + and details of which tests are built." + + cdl_option CYGPKG_UITRON_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the uITRON compatibility layer. These flags are used in addition + to the set of global flags." + } + + cdl_option CYGPKG_UITRON_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the uITRON compatibility layer. These flags are removed from + the set of global flags if present." + } + + cdl_option CYGPKG_UITRON_TESTS { + display "uITRON tests" + flavor data + no_define + calculated { + "tests/testcxx tests/testcx2 tests/testcx3 tests/testcx4 tests/testcx5 tests/testcx6 tests/testcx7 tests/testcx8 tests/testcx9" + . ((!CYGIMP_UITRON_INLINE_FUNCS && !CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ? + " tests/test1 tests/test2 tests/test3 tests/test4 tests/test5 tests/test6 tests/test7 tests/test8 tests/test9 tests/testintr" : "") + } + description " + This option specifies the set of tests for the uITRON compatibility layer." + } + } +} diff --git a/packages/compat/uitron/v2_0/cdl/version.cdl b/packages/compat/uitron/v2_0/cdl/version.cdl new file mode 100644 index 00000000..9ddd388e --- /dev/null +++ b/packages/compat/uitron/v2_0/cdl/version.cdl @@ -0,0 +1,167 @@ +# ==================================================================== +# +# verion.cdl +# +# uITRON version related configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: hmt +# Contributors: +# Date: 1999-07-07 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_option CYGNUM_UITRON_VER_MAKER { + display "OS maker" + flavor data + legal_values 0 to 0xFFFF + default_value 0 + description " + This value is returned in the 'maker' + field of the T_VER structure in + response to a get_ver() system call." +} +cdl_option CYGNUM_UITRON_VER_ID { + display "OS identification" + flavor data + legal_values 0 to 0xFFFF + default_value 0 + description " + This value is returned in the 'id' + field of the T_VER structure in + response to a get_ver() system call." +} +cdl_option CYGNUM_UITRON_VER_SPVER { + display "ITRON specification" + flavor data + legal_values 0 to 0xFFFF + default_value 0x5302 + description " + This value is returned in the 'spver' + field of the T_VER structure in + response to a get_ver() system call. + Do NOT change this value." +} +cdl_option CYGNUM_UITRON_VER_PRVER { + display "OS product version" + flavor data + legal_values 0 to 0xFFFF + default_value 0x0100 + description " + This value is returned in the 'prver' + field of the T_VER structure in + response to a get_ver() system call." +} +# PRNO fields in own folder +cdl_component CYGPKG_UITRON_VERSION_PRNO { + display "Product info" + flavor none + description " + The get_ver() uITRON system call returns + several version related values describing + the vendor, product and CPU in question + as well as the version of the uITRON + standard supported. + These values may be specified here." + + cdl_option CYGNUM_UITRON_VER_PRNO_0 { + display "Field 0" + flavor data + legal_values 0 to 0xFFFF + default_value 0 + description " + This value is returned in the 'prno\[0\]' + field of the T_VER structure in + response to a get_ver() system call." + } + cdl_option CYGNUM_UITRON_VER_PRNO_1 { + display "Field 1" + flavor data + legal_values 0 to 0xFFFF + default_value 0 + description " + This value is returned in the 'prno\[1\]' + field of the T_VER structure in + response to a get_ver() system call." + } + cdl_option CYGNUM_UITRON_VER_PRNO_2 { + display "Field 2" + flavor data + legal_values 0 to 0xFFFF + default_value 0 + description " + This value is returned in the 'prno\[2\]' + field of the T_VER structure in + response to a get_ver() system call." + } + cdl_option CYGNUM_UITRON_VER_PRNO_3 { + display "Field 3" + flavor data + legal_values 0 to 0xFFFF + default_value 0 + description " + This value is returned in the 'prno\[3\]' + field of the T_VER structure in + response to a get_ver() system call." + } +} + +cdl_option CYGNUM_UITRON_VER_CPU { + display "CPU information" + flavor data + legal_values 0 to 0xFFFF + default_value 0 + description " + This value is returned in the 'cpu' + field of the T_VER structure in + response to a get_ver() system call." +} +cdl_option CYGNUM_UITRON_VER_VAR { + display "System variant" + flavor data + legal_values 0 to 0xFFFF + default_value 0x8000 + description " + This value is returned in the 'var' + field of the T_VER structure in + response to a get_ver() system call. + Do NOT change this value." +} diff --git a/packages/compat/uitron/v2_0/doc/uitron.sgml b/packages/compat/uitron/v2_0/doc/uitron.sgml new file mode 100644 index 00000000..716b8da5 --- /dev/null +++ b/packages/compat/uitron/v2_0/doc/uitron.sgml @@ -0,0 +1,1385 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + µITRON + +<!-- <xref> -->µITRON API + +<!-- <index></index> -->Introduction to µITRON +The µITRON specification +defines a highly flexible operating system architecture designed +specifically for application in embedded systems. The specification addresses +features which are common to the majority of processor architectures and +deliberately avoids virtualization which would adversely impact +real-time performance. The µITRON specification +may be implemented on many hardware platforms and provides significant +advantages by reducing the effort involved in understanding and +porting application software to new processor architectures. +Several revisions of the µITRON specification exist. + In this release, eCos supports the + µITRON version 3.02 specification, with complete + “Standard functionality” (level S), plus many + “Extended” (level E) functions. The definitive + reference on µITRON is Dr. Sakamura’s book: + µITRON 3.0, An Open and Portable Real-Time Operating + System for Embedded Systems. + The book can be purchased from the IEEE Press, and + an ASCII version of the standard can be found online at +http://www.itron.gr.jp/. +The old address + +http://tron.um.u-tokyo.ac.jp/TRON/ITRON/ +still exists as a mirror site. + + +<!-- <index></index> -->µITRON and <EMPHASIS>eCos</EMPHASIS> +The eCos kernel implements the functionality +used by the µITRON compatibility subsystem. +The configuration of the kernel influences the behavior of µITRON +programs. +In particular, the default configuration has time slicing +(also known as round-robin scheduling) switched on; this means that +a task can be moved from RUN state +to READY state at any time, in +order that one of its peers may run. This is not strictly conformant +to the µITRON specification, which +states that timeslicing may be implemented by periodically issuing +a rot_rdq(0) call from +within a periodic task or cyclic handler; otherwise it is expected +that a task runs until it is pre-empted in consequence of synchronization +or communication calls it makes, or the effects of an interrupt +or other external event on a higher priority task cause that task +to become READY. To disable timeslicing +functionality in the kernel and µITRON +compatibility environment, please disable the +CYGSEM_KERNEL_SCHED_TIMESLICE +configuration option in the kernel package. A description of kernel +scheduling is in . +For another example, the semantics of task queueing when waiting +on a synchronization object depend solely on the way the underlying +kernel is configured. As discussed above, the multi-level queue +scheduler is the only one which is µITRON +compliant, and it queues waiting tasks in FIFO order. Future releases +of that scheduler might be configurable to support priority ordering +of task queues. Other schedulers might be different again: for example +the bitmap scheduler can be used with the µITRON +compatibility layer, even though it only allows one task at each +priority and as such is not µITRON +compliant, but it supports only priority ordering of task queues. +So which queueing scheme is supported is not really a property of +the µITRON compatibility layer; it +depends on the kernel. +In this version of the µITRON +compatibility layer, the calls to disable and enable scheduling +and interrupts (dis_dsp(), +ena_dsp(), loc_cpu() +and unl_cpu()) +call underlying kernel functions; in particular, the xxx_dsp() functions +lock the scheduler entirely, which prevents dispatching of DSRs; functions +implemented by DSRs include clock counters and alarm timers. Thus time “stops” while +dispatching is disabled with dis_dsp(). +Like all parts of the eCos system, the +detailed semantics of the µITRON layer +are dependent on its configuration and the configuration of other components +that it uses. The µITRON configuration +options are all defined in the file pkgconf/uitron.h, +and can be set using the configuration tool or editing the +.ecc +file in your build directory by hand. +An important configuration option for the µITRON +compatibility layer is “Option: Return Error Codes for Bad Params” +( +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +), which allows a lot of the error +checking code in the µITRON compatibility layer to +be removed. Of course this leaves a program open to undetected errors, +so it should only be used once an application is fully debugged and +tested. Its benefits include reduced code size and faster execution. +However, it affects the API significantly, in that with this option +enabled, bad calls do not return errors, but cause an assert +failure (if that is itself enabled) or malfunction internally. There +is discussion in more detail about this in each section below. +We now give a brief description of the µITRON +functions which are implemented in this release. Note that all C +and C++ source files should have the following #include statement: +#include <cyg/compat/uitron/uit_func.h> + + +<!-- <index></index> -->Task Management Functions +The following functions are fully supported in this release: +ER sta_tsk( + ID tskid, + INT stacd ) + +void ext_tsk( void ) + +void exd_tsk( void ) + +ER dis_dsp( void ) + +ER ena_dsp( void ) + +ER chg_pri( + ID tskid, + PRI tskpri ) + +ER rot_rdq( + PRI tskpri ) + +ER get_tid( + ID *p_tskid ) + +ER ref_tsk( + T_RTSK *pk_rtsk, + ID tskid ) + +ER ter_tsk( + ID tskid ) + +ER rel_wai( + ID tskid ) +The following two functions are supported in this release, +when enabled with the configuration option +CYGPKG_UITRON_TASKS_CREATE_DELETE +with some restrictions: +ER cre_tsk( + ID tskid, + T_CTSK *pk_ctsk ) + +ER del_tsk( + ID tskid ) +These functions are restricted as follows: +Because of the static initialization facilities provided for +system objects, a task is allocated stack space statically in the +configuration. So while tasks can be created and deleted, the same +stack space is used for that task (task ID number) each time. Thus +the stack size (pk_ctsk->stksz) requested in cre_tsk() is +checked for being less than that which was statically allocated, +and otherwise ignored. This ensures that the new task will have +enough stack to run. For this reason del_tsk() does +not in any sense free the memory that was in use for the task's +stack. +The task attributes (pk_ctsk->tskatr) are +ignored; current versions of eCos do not need +to know whether a task is written in assembler or C/C++ so +long as the procedure call standard appropriate to the CPU is followed. +Extended information (pk_ctsk->exinf) is + ignored. + +Error checking +For all these calls, an invalid task id (tskid) (less than +1 or greater than the number of configured tasks) only returns E_ID +when bad params return errors ( +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +is enabled, see above). +Similarly, the following conditions are only checked for, +and only return errors if +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +is enabled: + + +pk_crtk in +cre_tsk() + is a valid pointer, otherwise return E_PAR + + +ter_tsk() + or +rel_wai() + on the calling task returns E_OBJ + + +the CPU is not locked already in +dis_dsp() + and +ena_dsp() +; returns E_CTX + + +priority level in +chg_pri() + and +rot_rdq() + is checked for validity, E_PAR + + +return value pointer in +get_tid() + and +ref_tsk() + is a valid pointer, or E_PAR + + +The following conditions are checked for, and return + error codes if appropriate, regardless of the setting of +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +: + + +When create and delete functions +cre_tsk() + and +del_tsk() + are supported, all calls which use a valid task ID number check +that the task exists; if not, E_NOEXS is returned + + +When supported, +cre_tsk() +: the task must not already exist; otherwise E_OBJ + + +When supported, +cre_tsk() +: the requested stack size must not be larger than that statically +configured for the task; see the configuration options +“Static initializers”, and “Default stack size”. +Else E_NOMEM + + +When supported, +del_tsk() +: the underlying +eCos + thread must not be running - this would imply either a bug or some +program bypassing the +µITRON compatibility layer and manipulating the thread directly. +E_OBJ + + +sta_tsk() +: the task must be dormant, else E_OBJ + + +ter_tsk() +: the task must not be dormant, else E_OBJ + + +chg_pri() +: the task must not be dormant, else E_OBJ + + +rel_wai() +: the task must be in +WAIT or WAIT-SUSPEND + state, else E_OBJ + + + + + +<!-- <index></index> -->Task-Dependent Synchronization Functions +These functions are fully supported in this release: +ER sus_tsk( + ID tskid ) + +ER rsm_tsk( + ID tskid ) + +ER frsm_tsk( + ID tskid ) + +ER slp_tsk( void ) + +ER tslp_tsk( + TMO tmout ) + +ER wup_tsk( + ID tskid ) + +ER can_wup( + INT *p_wupcnt, ID tskid ) + +Error checking +The following conditions are only checked for, and only return +errors if +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +is enabled (see the configuration option “Return Error Codes for Bad +Params”): + + +invalid tskid; less than 1 or greater than +CYGNUM_UITRON_TASKS +returns E_ID + + +wup_tsk() +, +sus_tsk() +, +rsm_tsk() +, +frsm_tsk() + on the calling task returns E_OBJ + + +dispatching is enabled in +tslp_tsk() + and +slp_tsk() +, or E_CTX + + +tmout must be positive, otherwise E_PAR + + +return value pointer in +can_wup() + is a valid pointer, or E_PAR + + +The following conditions are checked for, and can + return error codes, regardless of the setting of +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS: + + + +When create and delete functions +cre_tsk() + and +del_tsk() + are supported, all calls which use a valid task ID number check +that the task exists; if not, E_NOEXS is returned + + +sus_tsk() +: the task must not be dormant, else E_OBJ + + +frsm/rsm_tsk() +: the task must be suspended, else E_OBJ + + +tslp/slp_tsk() +: return codes E_TMOUT, E_RLWAI and E_DLT +are returned depending on the reason for terminating the sleep + + +wup_tsk() + and +can_wup() +: the task must not be dormant, or E_OBJ is returned + + + + + +<!-- <index></index> --> Synchronization and Communication Functions +These functions are fully supported in this release: +ER sig_sem( + ID semid ) + + +ER wai_sem( + ID semid ) + + +ER preq_sem( + ID semid ) + + +ER twai_sem( + ID semid, TMO tmout ) + + +ER ref_sem( + T_RSEM *pk_rsem , ID semid ) + + +ER set_flg( + ID flgid, UINT setptn ) + + +ER clr_flg( + ID flgid, UINT clrptn ) + + +ER wai_flg( + UINT *p_flgptn, ID flgid , + UINT waiptn , UINT wfmode ) + + +ER pol_flg( + UINT *p_flgptn, ID flgid , + UINT waiptn , UINT wfmode ) + + +ER twai_flg( + UINT *p_flgptn ID flgid , + UINT waiptn , UINT wfmode, TMO tmout ) + + +ER ref_flg( + T_RFLG *pk_rflg, ID flgid ) + + +ER snd_msg( + ID mbxid, T_MSG *pk_msg ) + + +ER rcv_msg( + T_MSG **ppk_msg, ID mbxid ) + + +ER prcv_msg( + T_MSG **ppk_msg, ID mbxid ) + + +ER trcv_msg( + T_MSG **ppk_msg, ID mbxid , TMO tmout ) + + +ER ref_mbx( + T_RMBX *pk_rmbx, ID mbxid ) +The following functions are supported in this release (with +some restrictions) if enabled with the appropriate configuration +option for the object type (for example +CYGPKG_UITRON_SEMAS_CREATE_DELETE): + +ER cre_sem( + ID semid, T_CSEM *pk_csem ) + + +ER del_sem( + ID semid ) + + +ER cre_flg( + ID flgid, T_CFLG *pk_cflg ) + + +ER del_flg( + ID flgid ) + + +ER cre_mbx( + ID mbxid, T_CMBX *pk_cmbx ) + + +ER del_mbx( + ID mbxid ) +In general the queueing order when waiting on a synchronization +object depends on the underlying kernel configuration. The multi-level +queue scheduler is required for strict µITRON +conformance and it queues tasks in FIFO order, so requests to create +an object with priority queueing of tasks (pk_cxxx->xxxatr = TA_TPRI) +are rejected with E_RSATR. Additional undefined bits in +the attributes fields must be zero. +In general, extended information (pk_cxxx->exinf) +is ignored. +For semaphores, the initial semaphore count (pk_csem->isemcnt) +is supported; the new semaphore's count is set. The maximum +count is not supported, and is not in fact defined in type pk_csem. +For flags, multiple tasks are allowed to wait. Because single +task waiting is a subset of this, the W bit (TA_WMUL) of +the flag attributes is ignored; all other bits must be zero. The +initial flag value is supported. +For mailboxes, the buffer count is defined statically by kernel +configuration option +CYGNUM_KERNEL_SYNCH_MBOX_QUEUE_SIZE; +therefore the buffer count field is not supported and is not in +fact defined in type pk_cmbx. Queueing of messages is FIFO +ordered only, so TA_MPRI (in pk_cmbx->mbxatr) +is not supported. + +Error checking +The following conditions are only checked for, and only return +errors if +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +is enabled: + + +invalid object id; less than 1 or greater than +CYGNUM_UITRON_TASKS/SEMAS/MBOXES +as appropriate returns E_ID + + +dispatching is enabled in any call which can sleep, or +E_CTX + + +tmout must be positive, otherwise E_PAR + + +pk_cxxx pointers in +cre_xxx() + must be valid pointers, or E_PAR + + +return value pointer in +ref_xxx() + is valid pointer, or E_PAR + + +flag wait pattern must be non-zero, and mode must be valid, +or E_PAR + + +return value pointer in flag wait calls is a valid pointer, +or E_PAR + + +The following conditions are checked for, and can return error +codes, regardless of the setting of +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +: + + +When create and delete functions +cre_xxx() + and +del_xxx() + are supported, all calls which use a valid object ID number check +that the object exists. If not, E_NOEXS is returned. + + +In create functions +cre_xxx() +, when supported, if the object already exists, then E_OBJ + + +In any call which can sleep, such as +twai_sem() +: return codes E_TMOUT, E_RLWAI, E_DLT +or of course E_OK are returned depending on the reason +for terminating the sleep + + +In polling functions such as +preq_sem() +return codes E_TMOUT or E_OK are returned depending +on the state of the synchronization object + + +In creation functions, the attributes must be compatible +with the selected underlying kernel configuration: in +cre_sem() + pk_csem->sematr + must be equal to +TA_TFIFO + else E_RSATR. + + +In +cre_flg() + pk_cflg->flgatr + must be either +TA_WMUL + or +TA_WSGL + else E_RSATR. + + +In +cre_mbx() + +pk_cmbx->mbxatr + must be +TA_TFIFO + TA_MFIFO + else E_RSATR. + + + + + +<!-- <index></index> -->Extended Synchronization and Communication Functions +None of these functions are supported in this release. + + +<!-- <index></index> -->Interrupt management functions +These functions are fully supported in this release: +void ret_int( void ) + + +ER loc_cpu( void ) + + +ER unl_cpu( void ) + + +ER dis_int( + UINT eintno ) + + +ER ena_int( + UINT eintno ) + + +void ret_wup( + ID tskid ) + + +ER iwup_tsk( + ID tskid ) + + +ER isig_sem( + ID semid ) + + +ER iset_flg( + ID flgid , + UID setptn ) + + +ER isend_msg( + ID mbxid , + T_MSG *pk_msg ) +Note that ret_int() and +the ret_wup() are implemented +as macros, containing a “return” statement. +Also note that ret_wup() and +the ixxx_yyy() style functions +will only work when called from an ISR whose associated DSR is cyg_uitron_dsr(), +as specified in include file <cyg/compat/uitron/uit_ifnc.h>, +which defines the ixxx_yyy() style +functions also. +If you are writing interrupt handlers more in the +eCos style, with separate ISR and DSR routines both of +your own devising, do not use these special functions from a DSR: use plain +xxx_yyy() style functions (with no ‘i’ prefix) +instead, and do not call any µITRON functions from the ISR at +all. +The following functions are not supported in this release: +ER def_int( + UINT dintno, + T_DINT *pk_dint ) + +ER chg_iXX( + UINT iXXXX ) + + +ER ref_iXX( + UINT * p_iXXXX ) +These unsupported functions are all Level C (CPU dependent). +Equivalent functionality is available via other eCos-specific +APIs. + +Error checking +The following conditions are only checked for, and only return +errors if +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +is enabled: + + +loc/unl_cpu() +: these must only be called in a +µITRON task context, else E_CTX. + + +dis/ena_int() +: the interrupt number must be in range as specified by the platform +HAL in qustion, else E_PAR. + + + + + +<!-- <index></index> --> Memory pool Management Functions +These functions are fully supported in this release: +ER get_blf( + VP *p_blf, ID mpfid ) + + +ER pget_blf( + VP *p_blf, ID mpfid ) + + +ER tget_blf( + VP *p_blf, ID mpfid, TMO tmout ) + + +ER rel_blf( + ID mpfid, VP blf ) + + +ER ref_mpf( + T_RMPF *pk_rmpf, ID mpfid ) + + +ER get_blk( + VP *p_blk, ID mplid, INT blksz ) + + +ER pget_blk( + VP *p_blk, ID mplid, INT blksz ) + + +ER tget_blk( + VP *p_blk, ID mplid, INT blksz, TMO tmout ) + + +ER rel_blk( + ID mplid, VP blk ) + + +ER ref_mpl( + T_RMPL *pk_rmpl, ID mplid ) + + +Note that of the memory provided for a particular pool to +manage in the static initialization of the memory pool objects, +some memory will be used to manage the pool itself. Therefore the +number of blocks * the blocksize will be less than the total +memory size. +The following functions are supported in this release, when +enabled with +CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE +or +CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE +as appropriate, with some restrictions: +ER cre_mpl( + ID mplid, T_CMPL *pk_cmpl ) + + +ER del_mpl( + ID mplid ) + + +ER cre_mpf( + ID mpfid, T_CMPF *pk_cmpf ) + + +ER del_mpf( + ID mpfid ) +Because of the static initialization facilities provided for +system objects, a memory pool is allocated a region of memory to +manage statically in the configuration. So while memory pools can +be created and deleted, the same area of memory is used for that +memory pool (memory pool ID number) each time. The requested variable pool +size (pk_cmpl->mplsz) or the number of fixed-size +blocks (pk_cmpf->mpfcnt) times the block size +(pk_cmpf->blfsz) are checked for fitting within +the statically allocated memory area, so if a create call succeeds, +the resulting pool will be at least as large as that requested. +For this reason del_mpl() and del_mpf() do +not in any sense free the memory that was managed by the deleted +pool for use by other pools; it may only be managed by a pool of +the same object id. +For both fixed and variable memory pools, the queueing order +when waiting on a synchronization object depends on the underlying +kernel configuration. The multi-level queue scheduler is required +for strict µITRON conformance and +it queues tasks in FIFO order, so requests to create an object with +priority queueing of tasks (pk_cxxx->xxxatr = TA_TPRI) +are rejected with E_RSATR. Additional undefined bits in +the attributes fields must be zero. +In general, extended information (pk_cxxx->exinf) +is ignored. + +Error checking +The following conditions are only checked for, and only return +errors if +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +is enabled: + + +invalid object id; less than 1 or greater than +CYGNUM_UITRON_MEMPOOLVAR/MEMPOOLFIXED +as appropriate returns E_ID + + +dispatching is enabled in any call which can sleep, or +E_CTX + + +tmout must be positive, otherwise E_PAR + + +pk_cxxx pointers in +cre_xxx() + must be valid pointers, or E_PAR + + +return value pointer in +ref_xxx() + is a valid pointer, or E_PAR + + +return value pointers in get block routines is a valid +pointer, or E_PAR + + +blocksize request in get variable block routines is greater +than zero, or E_PAR + + +The following conditions are checked for, and can return error +codes, regardless of the setting of +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS: + + + +When create and delete functions +cre_xxx() + and +del_xxx() + are supported, all calls which use a valid object ID number check +that the object exists. If not, E_NOEXS is returned. + + +When create functions +cre_xxx() + are supported, if the object already exists, then E_OBJ + + +In any call which can sleep, such as +get_blk() +: return codes E_TMOUT, E_RLWAI, E_DLT +or of course E_OK are returned depending on the reason +for terminating the sleep + + +In polling functions such as +pget_blk() +return codes E_TMOUT or E_OK are returned depending +on the state of the synchronization object + + +In creation functions, the attributes must be compatible +with the selected underlying kernel configuration: in +cre_mpl() + +pk_cmpl->mplatr + must be equal to +TA_TFIFO + else E_RSATR. + + +In +cre_mpf() + +pk_cmpf->mpfatr + must be equal to +TA_TFIFO + else E_RSATR. + + +In creation functions, the requested size of the memory +pool must not be larger than that statically configured for the +pool else E_RSATR; see the configuration option +“Option: Static initializers”. + In +cre_mpl() + +pk_cmpl->mplsz + is the field of interest + + +In +cre_mpf() + the product of +pk_cmpf->blfsz + and +pk_cmpf->mpfcnt + must be smaller than the memory statically configured for the pool +else E_RSATR + + +In functions which return memory to the pool +rel_blk() + and +rel_blf() +, if the free fails, for example because the memory did not come +from that pool originally, then E_PAR is returned + + + + + +<!-- <index></index> -->Time Management Functions +These functions are fully supported in this release: +ER set_tim( + SYSTIME *pk_tim ) + + Setting the time may cause erroneous operation of the + kernel, for example a task performing a wait with a + time-out may never awaken. + +ER get_tim( + SYSTIME *pk_tim ) + + +ER dly_tsk( + DLYTIME dlytim ) + + +ER def_cyc( + HNO cycno, T_DCYC *pk_dcyc ) + + +ER act_cyc( + HNO cycno, UINT cycact ) + + +ER ref_cyc( + T_RCYC *pk_rcyc, HNO cycno ) + + +ER def_alm( + HNO almno, T_DALM *pk_dalm ) + + +ER ref_alm( + T_RALM *pk_ralm, HNO almno ) + + +void ret_tmr( void ) + + Error checking +The following conditions are only checked for, and only return +errors if +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +is enabled: + + +invalid handler number; less than 1 or greater than +CYGNUM_UITRON_CYCLICS/ALARMS +as appropriate, or E_PAR + + +dispatching is enabled in +dly_tsk() +, or E_CTX + + +dlytim must be positive or zero, otherwise E_PAR + + +return value pointer in +ref_xxx() + is a valid pointer, or E_PAR + + +params within pk_dalm and pk_dcyc must +be valid, or E_PAR + + +cycact in +act_cyc() + must be valid, or E_PAR + + +handler must be defined in +ref_xxx() + and +act_cyc() +, or E_NOEXS + + +parameter pointer must be a good pointer in +get_tim() + and +set_tim() +, otherwise E_PAR is returned + + +The following conditions are checked for, and can return + error codes, regardless of the setting of +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +: + + +dly_tsk() +: return code E_RLWAI is returned depending on the reason +for terminating the sleep + + + + + +<!-- <index></index> --> System Management Functions +These functions are fully supported in this release: + +ER get_ver( + T_VER *pk_ver ) + +ER ref_sys( + T_RSYS *pk_rsys ) + +ER ref_cfg( + T_RCFG *pk_rcfg ) + +Note that the information returned by each of these calls +may be configured to match the user's own versioning system, +and the values supplied by the default configuration may be inappropriate. +These functions are not supported in this release: +ER def_svc( + FN s_fncd, + T_DSVC *pk_dsvc ) + +ER def_exc( + UINT exckind, + T_DEXC *pk_dexc ) + + +Error checking +The following conditions are only checked for, and + only return errors if + +CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + is enabled: + + +return value pointer in all calls is a valid + pointer, or E_PAR + + + + + +<!-- <index></index> --> Network Support Functions +None of these functions are supported in this release. + + + +<!-- <index></index> -->µITRON Configuration FAQ +Q: How are µITRON objects created? + + +For each type of uITRON object (tasks, semaphores, flags, mboxes, mpf, mpl) +these two quantities are controlled by configuration: + + + +The maximum number of this type of object. + + +The number of these objects which exist initially. + + + +This is assuming that for the relevant object type, +create and delete +operations are enabled; enabled is the default. For example, the option +CYGPKG_UITRON_MBOXES_CREATE_DELETE +controls whether the functions +cre_mbx() +and +del_mbx() +exist in the API. If not, then the maximum number of +mboxes is the same as the initial number of mboxes, and so on for all +µITRON object types. + + +Mboxes have no initialization, so there are only a few, simple +configuration options: + + + +CYGNUM_UITRON_MBOXES +is the total number of mboxes that you can have in the +system. By default this is 4, so you can use mboxes 1,2,3 and 4. You +cannot create mboxes outside this range; trying to +cre_mbx(5,...) +will return an error. + + +CYGNUM_UITRON_MBOXES_INITIALLY +is the number of mboxes created +automatically for you, during startup. By default this is 4, so all 4 +mboxes exist already, and an attempt to create one of these +eg. cre_mbx(3,...) +will return an error because the mbox in quesion already +exists. You can delete a pre-existing mbox, and then re-create it. + + + +If you change +CYGNUM_UITRON_MBOXES_INITIALLY, +for example to 0, no mboxes +are created automatically for you during startup. Any attempt to use an +mbox without creating it will return E_NOEXS because the mbox does not +exist. You can create an mbox, say cre_mbx(3,...) +and then use it, say +snd_msg(3,&foo), and all will be well. + +Q: How are µITRON objects initialized? + + +Some object types have optional initialization. Semaphores are an +example. You could have +CYGNUM_UITRON_SEMAS=10 and +CYGNUM_UITRON_SEMAS_INITIALLY=5 +which means you can use semaphores 1-5 +straight off, but you must create semaphores 6-10 before you can use them. +If you decide not to initialize semaphores, semaphores 1-5 will have an +initial count of zero. If you decide to initialize them, you must supply +a dummy initializer for semaphores 6-10 also. For example, +in terms of the configuration output in +pkgconf/uitron.h: + + + #define CYGDAT_UITRON_SEMA_INITIALIZERS \ + CYG_UIT_SEMA( 1 ), \ + CYG_UIT_SEMA( 0 ), \ + CYG_UIT_SEMA( 0 ), \ + CYG_UIT_SEMA( 99 ), \ + CYG_UIT_SEMA( 1 ), \ + CYG_UIT_SEMA_NOEXS, \ + CYG_UIT_SEMA_NOEXS, \ + CYG_UIT_SEMA_NOEXS, \ + CYG_UIT_SEMA_NOEXS, \ + CYG_UIT_SEMA_NOEXS + + +Semaphore 1 will have initial count 1, semaphores 2 and 3 will be zero, +number 4 will be 99 initially, 5 will be one and numbers 6 though 10 do not +exist initially. + + +Aside: this is how the definition of the symbol would appear in the +configuration header file pkgconf/uitron.h — +unfortunately editing such a long, multi-line definition is somewhat +cumbersome in the GUI config tool in current releases. The macros +CYG_UIT_SEMA() +— to create a semaphore initializer — and +CYG_UIT_SEMA_NOEXS +— to invoke a dummy initializer — +are provided in in the environment to help with this. Similar macros are +provided for other object types. The resulting #define symbol is used in +the context of a C++ array initializer, such as: + +Cyg_Counting_Semaphore2 cyg_uitron_SEMAS[ CYGNUM_UITRON_SEMAS ] = { + CYGDAT_UITRON_SEMA_INITIALIZERS +}; + +which is eventually macro-processed to give + +Cyg_Counting_Semaphore2 cyg_uitron_SEMAS[ 10 ] = { + Cyg_Counting_Semaphore2( ( 1 ) ), + Cyg_Counting_Semaphore2( ( 0 ) ), + Cyg_Counting_Semaphore2( ( 0 ) ), + Cyg_Counting_Semaphore2( ( 99 ) ), + Cyg_Counting_Semaphore2( ( 1 ) ), + Cyg_Counting_Semaphore2(0), + Cyg_Counting_Semaphore2(0), + Cyg_Counting_Semaphore2(0), + Cyg_Counting_Semaphore2(0), + Cyg_Counting_Semaphore2(0), +}; + +so you can see how it is necessary to include the dummy entries in that +definition, otherwise the resulting code will not compile correctly. + + +If you choose +CYGNUM_UITRON_SEMAS_INITIALLY=0 +it is meaningless to initialize them, for they must be created and so +initialized then, before use. + +Q: What about µITRON tasks? + + +Some object types require initialization. Tasks are an example of this. +You must provide a task with a priority, a function to enter when the task +starts, a name (for debugging purposes), and some memory to use for the stack. +For example (again in terms of the resulting +definitions in pkgconf/uitron.h): + + +#define CYGNUM_UITRON_TASKS 4 // valid task ids are 1,2,3,4 +#define CYGNUM_UITRON_TASKS_INITIALLY 4 // they all exist at start + +#define CYGDAT_UITRON_TASK_EXTERNS \ +extern "C" void startup( unsigned int ); \ +extern "C" void worktask( unsigned int ); \ +extern "C" void lowtask( unsigned int ); \ +static char stack1[ CYGNUM_UITRON_STACK_SIZE ], \ + stack2[ CYGNUM_UITRON_STACK_SIZE ], \ + stack3[ CYGNUM_UITRON_STACK_SIZE ], \ + stack4[ CYGNUM_UITRON_STACK_SIZE ]; + +#define CYGDAT_UITRON_TASK_INITIALIZERS \ + CYG_UIT_TASK("main task", 8, startup, &stack1, sizeof( stack1 )), \ + CYG_UIT_TASK("worker 2" , 9, worktask, &stack2, sizeof( stack2 )), \ + CYG_UIT_TASK("worker 3" , 9, worktask, &stack3, sizeof( stack3 )), \ + CYG_UIT_TASK("low task" ,20, lowtask, &stack4, sizeof( stack4 )), \ + + + +So this example has all four tasks statically configured to exist, ready to +run, from the start of time. The “main task” runs a routine +called startup() at priority 8. Two +“worker” tasks run both a priority 9, and a “low +priority” task runs at priority 20 to do useful non-urgent background +work. + + +Task ID | Exists at | Function | Priority | Stack | Stack + number | startup | entry | | address | size +--------+-----------+----------+----------+---------+---------- + 1 | Yes | startup | 8 | &stack1 | CYGNUM... + 2 | Yes | worktask | 9 | &stack2 | CYGNUM... + 3 | Yes | worktask | 9 | &stack3 | CYGNUM... + 4 | Yes | lowtask | 20 | &stack4 | CYGNUM... +--------+-----------+----------+----------+---------+---------- + +Q: How can I create µITRON tasks in the program? + + +You must provide free slots in the task table in which to create new tasks, +by configuring the number of tasks existing initially to be smaller than +the total. +For a task ID which does not initially exist, it will be told what routine +to call, and what priority it is, when the task is created. But you must +still set aside memory for the task to use for its stack, and give it a +name during initialization. For example: + + + +#define CYGNUM_UITRON_TASKS 4 // valid task ids are 1-4 +#define CYGNUM_UITRON_TASKS_INITIALLY 1 // only task #1 exists + +#define CYGDAT_UITRON_TASK_EXTERNS \ +extern "C" void startup( unsigned int ); \ +static char stack1[ CYGNUM_UITRON_STACK_SIZE ], \ + stack2[ CYGNUM_UITRON_STACK_SIZE ], \ + stack3[ CYGNUM_UITRON_STACK_SIZE ], \ + stack4[ CYGNUM_UITRON_STACK_SIZE ]; + +#define CYGDAT_UITRON_TASK_INITIALIZERS \ + CYG_UIT_TASK( "main", 8, startup, &stack1, sizeof( stack1 ) ), \ + CYG_UIT_TASK_NOEXS( "slave", &stack2, sizeof( stack2 ) ), \ + CYG_UIT_TASK_NOEXS( "slave2", &stack3, sizeof( stack3 ) ), \ + CYG_UIT_TASK_NOEXS( "slave3", &stack4, sizeof( stack4 ) ), \ + + + +So tasks numbered 2,3 and 4 have been given their stacks during startup, +though they do not yet exist in terms of cre_tsk() and +del_tsk() so you can create tasks 2–4 at +runtime. + + +Task ID | Exists at | Function | Priority | Stack | Stack + number | startup | entry | | address | size +--------+-----------+----------+----------+---------+---------- + 1 | Yes | startup | 8 | &stack1 | CYGNUM... + 2 | No | N/A | N/A | &stack2 | CYGNUM... + 3 | No | N/A | N/A | &stack3 | CYGNUM... + 4 | No | N/A | N/A | &stack4 | CYGNUM... +--------+-----------+----------+----------+---------+---------- + + +(you must have at least one task at startup in order that the system can + actually run; this is not so for other uITRON object types) + +Q: Can I have different stack sizes for µITRON tasks? + + +Simply set aside different amounts of memory for each task to use for its +stack. Going back to a typical default setting for the µITRON tasks, +the definitions in pkgconf/uitron.h might look like this: + + +#define CYGDAT_UITRON_TASK_EXTERNS \ +extern "C" void task1( unsigned int ); \ +extern "C" void task2( unsigned int ); \ +extern "C" void task3( unsigned int ); \ +extern "C" void task4( unsigned int ); \ +static char stack1[ CYGNUM_UITRON_STACK_SIZE ], \ + stack2[ CYGNUM_UITRON_STACK_SIZE ], \ + stack3[ CYGNUM_UITRON_STACK_SIZE ], \ + stack4[ CYGNUM_UITRON_STACK_SIZE ]; + +#define CYGDAT_UITRON_TASK_INITIALIZERS \ + CYG_UIT_TASK( "t1", 1, task1, &stack1, CYGNUM_UITRON_STACK_SIZE ), \ + CYG_UIT_TASK( "t2", 2, task2, &stack2, CYGNUM_UITRON_STACK_SIZE ), \ + CYG_UIT_TASK( "t3", 3, task3, &stack3, CYGNUM_UITRON_STACK_SIZE ), \ + CYG_UIT_TASK( "t4", 4, task4, &stack4, CYGNUM_UITRON_STACK_SIZE ) + + + +Note that +CYGNUM_UITRON_STACK_SIZE +is used to control the size of the stack +objects themselves, and to tell the system what size stack is being provided. + + +Suppose instead stack sizes of 2000, 1000, 800 and 800 were required: +this could be achieved by using the GUI config tool to edit these +options, or editting the .ecc file to get these +results in pkgconf/uitron.h: + + +#define CYGDAT_UITRON_TASK_EXTERNS \ +extern "C" void task1( unsigned int ); \ +extern "C" void task2( unsigned int ); \ +extern "C" void task3( unsigned int ); \ +extern "C" void task4( unsigned int ); \ +static char stack1[ 2000 ], \ + stack2[ 1000 ], \ + stack3[ 800 ], \ + stack4[ 800 ]; + +#define CYGDAT_UITRON_TASK_INITIALIZERS \ + CYG_UIT_TASK( "t1", 1, task1, &stack1, sizeof( stack1 ) ), \ + CYG_UIT_TASK( "t2", 2, task2, &stack2, sizeof( stack2 ) ), \ + CYG_UIT_TASK( "t3", 3, task3, &stack3, sizeof( stack3 ) ), \ + CYG_UIT_TASK( "t4", 4, task4, &stack4, sizeof( stack4 ) ) + + +Note that the sizeof() operator has been used to tell the system what size +stacks are provided, rather than quoting a number (which is difficult for +maintenance) or the symbol +CYGNUM_UITRON_STACK_SIZE +(which is wrong). + + +We recommend using (if available in your release) the stacksize symbols +provided in the architectural HAL for your target, called +CYGNUM_HAL_STACK_SIZE_TYPICAL +and +CYGNUM_HAL_STACK_SIZE_MINIMUM. +So a better (more portable) version of the above might be: + + +#define CYGDAT_UITRON_TASK_EXTERNS \ +extern "C" void task1( unsigned int ); \ +extern "C" void task2( unsigned int ); \ +extern "C" void task3( unsigned int ); \ +extern "C" void task4( unsigned int ); \ +static char stack1[ CYGNUM_HAL_STACK_SIZE_TYPICAL + 1200 ], \ + stack2[ CYGNUM_HAL_STACK_SIZE_TYPICAL + 200 ], \ + stack3[ CYGNUM_HAL_STACK_SIZE_TYPICAL ], \ + stack4[ CYGNUM_HAL_STACK_SIZE_TYPICAL ]; + +#define CYGDAT_UITRON_TASK_INITIALIZERS \ + CYG_UIT_TASK( "t1", 1, task1, &stack1, sizeof( stack1 ) ), \ + CYG_UIT_TASK( "t2", 2, task2, &stack2, sizeof( stack2 ) ), \ + CYG_UIT_TASK( "t3", 3, task3, &stack3, sizeof( stack3 ) ), \ + CYG_UIT_TASK( "t4", 4, task4, &stack4, sizeof( stack4 ) ) + + + + diff --git a/packages/compat/uitron/v2_0/include/uit_func.h b/packages/compat/uitron/v2_0/include/uit_func.h new file mode 100644 index 00000000..f399a93a --- /dev/null +++ b/packages/compat/uitron/v2_0/include/uit_func.h @@ -0,0 +1,402 @@ +#ifndef CYGONCE_COMPAT_UITRON_UIT_FUNC_H +#define CYGONCE_COMPAT_UITRON_UIT_FUNC_H +//=========================================================================== +// +// uit_func.h +// +// uITRON compatibility functions +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON compatibility functions +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +// ------------------------------------------------------------------------ +// Source Code Organization +// +// First, see pkgconf/uitron.h for details of applicable configuration +// options. +// +// This file uit_func.h provides prototypes for the uITRON API. All the +// uITRON functions are listed here. The prototypes are configurable +// either to have C or C++ linkage, and if being compiled in a C++ +// environment, to be inline. +// +// The function prototypes are all in terms of uITRON type definitions from +// uit_type.h, which is included at the head of uit_func.h. +// +// The implementations of the uITRON functions are in uit_func.inl, which +// is either included at the end of uit_func.h (if functions are inline) or +// in uit_func.cxx (if outline). +// +// uit_func.cxx provides some startup functions plus, if the uITRON +// functions are out of line, uit_func.inl is included to instantiate those +// functions. +// +// uITRON system objects (tasks, semaphores...) are described in +// uit_obj.hxx. This is a C++ file and is used by the implementation of +// the uITRON functions. +// +// The uITRON system objects are instantiated in uit_obj.cxx, which uses +// uit_obj.hxx to define the objects, and the configuration file +// pkgconf/uitron.h to construct them as required. +// +// The include graph from an application, which should only include +// uit_func.h, is similar to the following: +// +// +// [inline uITRON functions:] +// +// +// . uit_func.h ; prototypes for funcs +// . . pkgconf/uitron.h ; configuration info +// . . uit_type.h ; typedefs for func args +// . (function prototypes) +// . . uit_func.inl ; full function bodies +// . . . uit_objs.hxx ; defs of uITRON data +// . . (function implementations) +// +// +// [out-of-line uITRON functions:] +// +// +// . uit_func.h ; prototypes for funcs +// . . pkgconf/uitron.h ; configuration info +// . . uit_type.h ; typedefs for func args +// . (function prototypes) +// +// +// [other uITRON compilation units:] +// +// uit_func.cxx ; out-of-line functions +// . pkgconf/uitron.h ; configuration info +// . uit_func.h ; prototypes for funcs +// . . uit_type.h ; typedefs for func args +// . (function prototypes) +// . . uit_func.inl ; full function bodies +// . . . uit_objs.hxx ; defs of uITRON data +// . . (function implementations) +// +// +// uit_objs.cxx ; static uITRON data objects +// . pkgconf/uitron.h ; configuration info +// . uit_objs.hxx ; defs of uITRON data +// (static uITRON system objects) +// +// +// The various include files are protected against multiple inclusion and +// so may be safely re-included as convenient. +// +// ------------------------------------------------------------------------ + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al + +#ifdef CYGPKG_UITRON + +#include // types; cyg_int32, CYG_ADDRWORD + +#include // uITRON types; ER ID TMO T_MSG + +// ------------------------------------------------------------------------ +// Object operations: +// +// The functions can be inlined in C compiled by C++, or C++ of course, +// and also outlined in extern "C" functions, eg. for taking the address +// of, or for use by a pure C program, or of course outlined in C++ for +// Code size reasons. +// +// +// Summary: +// +// IF compiling in C +// THEN functions must be C linkage and out of line: +// do NOT specify CYGIMP_UITRON_INLINE_FUNCS nor +// CYGIMP_UITRON_CPP_OUTLINE_FUNCS. +// IF compiling in C++ +// THEN functions can be inline: specify CYGIMP_UITRON_INLINE_FUNCS +// OR by default, functions are out of line: +// outline functions can have C++ linkage: +// specify CYGIMP_UITRON_CPP_OUTLINE_FUNCS +// OR by default, outline functions have C linkage. + + +#ifdef __cplusplus +// C++ environment; functions can be inline or not as we please. +// If not inline they might as well be "C" linkage for sharing with +// any pure "C" code present. + +#ifdef CYGIMP_UITRON_INLINE_FUNCS + +#define CYG_UIT_FUNC_EXTERN_BEGIN +#define CYG_UIT_FUNC_EXTERN_END +#define CYG_UIT_FUNC_INLINE inline +#ifndef CYGPRI_UITRON_FUNCS_HERE_AND_NOW +#define CYGPRI_UITRON_FUNCS_HERE_AND_NOW +#endif + +#else + +#ifdef CYGIMP_UITRON_CPP_OUTLINE_FUNCS +#define CYG_UIT_FUNC_EXTERN_BEGIN extern "C++" { +#define CYG_UIT_FUNC_EXTERN_END } +#else +#define CYG_UIT_FUNC_EXTERN_BEGIN extern "C" { +#define CYG_UIT_FUNC_EXTERN_END } +#endif + +#define CYG_UIT_FUNC_INLINE +#endif + +#else // !__cplusplus +// Vanilla "C" environment; external "C" linkage, no inline functions + +#ifdef CYGIMP_UITRON_INLINE_FUNCS +#error "Cannot inline uITRON functions in pure C environment" +#endif +#ifdef CYGIMP_UITRON_CPP_OUTLINE_FUNCS +#error "Cannot use C++ linkage of outline fns in pure C environment" +#endif + +#define CYG_UIT_FUNC_EXTERN_BEGIN +#define CYG_UIT_FUNC_EXTERN_END +#define CYG_UIT_FUNC_INLINE + +#endif // !__cplusplus + +// ======================================================================== +// u I T R O N F U N C T I O N S +// The function declarations themselves: + +CYG_UIT_FUNC_EXTERN_BEGIN + +// this routine is outside the uITRON specification; call it from main() to +// start the uITRON tasks and scheduler. It does not return. + +#ifdef CYGNUM_UITRON_START_TASKS +void cyg_uitron_start( void ); +#endif + +// ****************************************************** +// *** 6.5 C Language Interfaces *** +// ****************************************************** + +// - Task Management Functions + +ER cre_tsk ( ID tskid, T_CTSK *pk_ctsk ); +ER del_tsk ( ID tskid ); +ER sta_tsk ( ID tskid, INT stacd ); +void ext_tsk ( void ); +void exd_tsk ( void ); +ER ter_tsk ( ID tskid ); + +ER dis_dsp ( void ); +ER ena_dsp ( void ); +ER chg_pri ( ID tskid, PRI tskpri ); +ER rot_rdq ( PRI tskpri ); +ER rel_wai ( ID tskid ); +ER get_tid ( ID *p_tskid ); +ER ref_tsk ( T_RTSK *pk_rtsk, ID tskid ); + +// - Task-Dependent Synchronization Functions + +ER sus_tsk ( ID tskid ); +ER rsm_tsk ( ID tskid ); +ER frsm_tsk ( ID tskid ); +ER slp_tsk ( void ); +ER tslp_tsk ( TMO tmout ); +ER wup_tsk ( ID tskid ); +ER can_wup ( INT *p_wupcnt, ID tskid ); + +// - Synchronization and Communication Functions + +ER cre_sem ( ID semid, T_CSEM *pk_csem ); +ER del_sem ( ID semid ); +ER sig_sem ( ID semid ); +ER wai_sem ( ID semid ); +ER preq_sem ( ID semid ); +ER twai_sem ( ID semid, TMO tmout ); +ER ref_sem ( T_RSEM *pk_rsem, ID semid ); + +ER cre_flg ( ID flgid, T_CFLG *pk_cflg ); +ER del_flg ( ID flgid ); +ER set_flg ( ID flgid, UINT setptn ); +ER clr_flg ( ID flgid, UINT clrptn ); +ER wai_flg ( UINT *p_flgptn, ID flgid, UINT waiptn, UINT wfmode ); +ER pol_flg ( UINT *p_flgptn, ID flgid, UINT waiptn, UINT wfmode ); +ER twai_flg ( UINT *p_flgptn, ID flgid, UINT waiptn, UINT wfmode, + TMO tmout ); +ER ref_flg ( T_RFLG *pk_rflg, ID flgid ); + +ER cre_mbx ( ID mbxid, T_CMBX* pk_cmbx ); +ER del_mbx ( ID mbxid ); +ER snd_msg ( ID mbxid, T_MSG *pk_msg ); +ER rcv_msg ( T_MSG **ppk_msg, ID mbxid ); +ER prcv_msg ( T_MSG **ppk_msg, ID mbxid ); +ER trcv_msg ( T_MSG **ppk_msg, ID mbxid, TMO tmout ); +ER ref_mbx ( T_RMBX *pk_rmbx, ID mbxid ); + +// - Extended Synchronization and Communication Functions + +#if 0 // NOT SUPPORTED +ER cre_mbf ( ID mbfid, T_CMBF *pk_cmbf ); +ER del_mbf ( ID mbfid ); +ER snd_mbf ( ID mbfid, VP msg, INT msgsz ); +ER psnd_mbf ( ID mbfid, VP msg, INT msgsz ); +ER tsnd_mbf ( ID mbfid, VP msg, INT msgsz, TMO tmout ); +ER rcv_mbf ( VP msg, INT *p_msgsz, ID mbfid ); +ER prcv_mbf ( VP msg, INT *p_msgsz, ID mbfid ); +ER trcv_mbf ( VP msg, INT *p_msgsz, ID mbfid, TMO tmout ); +ER ref_mbf ( T_RMBF *pk_rmbf, ID mbfid ); +ER cre_por ( ID porid, T_CPOR *pk_cpor ); +ER del_por ( ID porid ); +ER cal_por ( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT + cmsgsz ); +ER pcal_por ( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT + cmsgsz ); +ER tcal_por ( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT + cmsgsz, TMO tmout ); +ER acp_por ( RNO *p_rdvno, VP msg, INT *p_cmsgsz, ID porid, UINT + acpptn ); +ER pacp_por ( RNO *p_rdvno, VP msg, INT *p_cmsgsz, ID porid, UINT + acpptn ); +ER tacp_por ( RNO *p_rdvno, VP msg, INT *p_cmsgsz, ID porid, UINT + acpptn, TMO tmout ); +ER fwd_por ( ID porid, UINT calptn, RNO rdvno, VP msg, INT cmsgsz + ); +ER rpl_rdv ( RNO rdvno, VP msg, INT rmsgsz ); +ER ref_por ( T_RPOR *pk_rpor, ID porid ); +#endif + +// - Interrupt Management Functions + +#if 0 // NOT SUPPORTED +ER def_int ( UINT dintno, T_DINT *pk_dint ); +void ret_wup ( ID tskid ); +#endif +#if 0 +void ret_int ( void ); +#endif +#define ret_int() return +ER loc_cpu ( void ); +ER unl_cpu ( void ); + +ER dis_int ( UINT eintno ); +ER ena_int ( UINT eintno ); + +#if 0 // NOT SUPPORTED +ER chg_iXX ( UINT iXXXX ); +ER ref_iXX ( UINT *p_iXXXX ); +#endif + +// - Memorypool Management Functions + +ER cre_mpl ( ID mplid, T_CMPL *pk_cmpl ); +ER del_mpl ( ID mplid ); +ER get_blk ( VP *p_blk, ID mplid, INT blksz ); +ER pget_blk ( VP *p_blk, ID mplid, INT blksz ); +ER tget_blk ( VP *p_blk, ID mplid, INT blksz, TMO tmout ); +ER rel_blk ( ID mplid, VP blk ); +ER ref_mpl ( T_RMPL *pk_rmpl, ID mplid ); + +ER cre_mpf ( ID mpfid, T_CMPF *pk_cmpf ); +ER del_mpf ( ID mpfid ); +ER get_blf ( VP *p_blf, ID mpfid ); +ER pget_blf ( VP *p_blf, ID mpfid ); +ER tget_blf ( VP *p_blf, ID mpfid, TMO tmout ); +ER rel_blf ( ID mpfid, VP blf ); +ER ref_mpf ( T_RMPF *pk_rmpf, ID mpfid ); + +// - Time Management Functions + +ER set_tim ( SYSTIME *pk_tim ); +ER get_tim ( SYSTIME *pk_tim ); +ER dly_tsk ( DLYTIME dlytim ); +ER def_cyc ( HNO cycno, T_DCYC *pk_dcyc ); +ER act_cyc ( HNO cycno, UINT cycact ); +ER ref_cyc ( T_RCYC *pk_rcyc, HNO cycno ); +ER def_alm ( HNO almno, T_DALM *pk_dalm ); +ER ref_alm ( T_RALM *pk_ralm, HNO almno ); +#if 0 +void ret_tmr ( void ); +#endif +#define ret_tmr() return + +// - System Management Functions + +ER get_ver ( T_VER *pk_ver ); +ER ref_sys ( T_RSYS *pk_rsys ); +ER ref_cfg ( T_RCFG *pk_rcfg ); +#if 0 // NOT SUPPORTED +ER def_svc ( FN s_fncd, T_DSVC *pk_dsvc ); +ER def_exc ( UINT exckind, T_DEXC *pk_dexc ); +#endif + +// - Network Support Functions + +#if 0 // NOT SUPPORTED +ER nrea_dat ( INT *p_reasz, VP dstadr, NODE srcnode, VP srcadr, + INT datsz ); +ER nwri_dat ( INT *p_wrisz, NODE dstnode, VP dstadr, VP srcadr, + INT datsz ); +ER nget_nod ( NODE *p_node ); +ER nget_ver ( T_VER *pk_ver, NODE node ); +#endif + +CYG_UIT_FUNC_EXTERN_END + +// ======================================================================== + +#ifdef CYGPRI_UITRON_FUNCS_HERE_AND_NOW +// functions are inline OR we are in the outline implementation, so define +// the functions as inlines or plain functions depending on the value of +// CYG_UIT_FUNC_INLINE from above. +#include +#endif // CYGPRI_UITRON_FUNCS_HERE_AND_NOW + +// ------------------------------------------------------------------------ +#endif // CYGPKG_UITRON + +#endif // CYGONCE_COMPAT_UITRON_UIT_FUNC_H +// EOF uit_func.h diff --git a/packages/compat/uitron/v2_0/include/uit_func.inl b/packages/compat/uitron/v2_0/include/uit_func.inl new file mode 100644 index 00000000..e4413a75 --- /dev/null +++ b/packages/compat/uitron/v2_0/include/uit_func.inl @@ -0,0 +1,1950 @@ +#ifndef CYGONCE_COMPAT_UITRON_UIT_FUNC_INL +#define CYGONCE_COMPAT_UITRON_UIT_FUNC_INL +//=========================================================================== +// +// uit_func.inl +// +// uITRON compatibility functions +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON compatibility functions +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#ifdef CYGPKG_UITRON + +#ifdef CYGPRI_UITRON_FUNCS_HERE_AND_NOW + +#include // uITRON setup CYGNUM_UITRON_SEMAS + +// kernel facilities only needed here +#include +#include + +// and the implementations of other kernel facilities +#include +#include +#include + + +// ------------------------------------------------------------------------ +// The variable where dis_dsp/ena_dsp state is held: +extern cyg_uint32 cyg_uitron_dis_dsp_old_priority; + +// ------------------------------------------------------------------------ +// Parameter checking; either check the expression and return an error code +// if not true, or assert the truth with a made-up message. + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +// default: uitron error codes are returned +#define CYG_UIT_PARAMCHECK( _true_, _error_ ) CYG_MACRO_START \ + if ( ! (_true_) ) return (_error_); \ +CYG_MACRO_END +#else +// ...but they are asserted if asserts are on +#define CYG_UIT_PARAMCHECK( _true_, _error_ ) CYG_MACRO_START \ + CYG_ASSERT( (_true_), "CYG_UIT_PARAMCHECK fail: " #_true_ ); \ +CYG_MACRO_END +#endif // else !CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + +// ------------------------------------------------------------------------ +// CYG_UITRON_CHECK_AND_GETP +// +// Macro to rangecheck and do the addressing of a static uitron system +// object; _which_ sort of object is given, and token pasting is used +// horribly to get the static array, limits and the like. +// +// Usage: +// INT snd_msg( ID mbxid, ... ) { +// Cyg_Mbox *p; +// CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); +// p->...(...); + +// internal: plain assignment to the object pointer, from static array +#define CYG_UIT_SPTR( _which_, _idx_, _ptr_ ) CYG_MACRO_START \ + (_ptr_) = CYG_UITRON_OBJS( _which_ ) + ((_idx_) - 1); \ +CYG_MACRO_END + +// internal: plain assignment to the object pointer, from pointer array +// with error checking. +#define CYG_UIT_SPTR_PTR( _which_, _idx_, _ptr_ ) CYG_MACRO_START \ + (_ptr_) = CYG_UITRON_PTRS( _which_ )[ ((_idx_) - 1) ]; \ + if ( NULL == (_ptr_) ) return E_NOEXS; \ +CYG_MACRO_END + +#define CYG_UITRON_CHECK_AND_GETP_DIRECT( _which_, _idx_, _ptr_ ) \ +CYG_MACRO_START \ + CYG_UIT_PARAMCHECK( 0 < (_idx_), E_ID ); \ + CYG_UIT_PARAMCHECK( CYG_UITRON_NUM( _which_ ) >= (_idx_), E_ID ); \ + CYG_UIT_SPTR( _which_, _idx_, _ptr_ ); \ +CYG_MACRO_END + +#define CYG_UITRON_CHECK_AND_GETP_INDIRECT( _which_, _idx_, _ptr_ ) \ +CYG_MACRO_START \ + CYG_UIT_PARAMCHECK( 0 < (_idx_), E_ID ); \ + CYG_UIT_PARAMCHECK( CYG_UITRON_NUM( _which_ ) >= (_idx_), E_ID ); \ + CYG_UIT_SPTR_PTR( _which_, _idx_, _ptr_ ); \ +CYG_MACRO_END + +// As above but for handler numbers which return E_PAR when out of range +#define CYG_UITRON_CHECK_AND_GETHDLR( _which_, _num_, _ptr_ ) \ +CYG_MACRO_START \ + CYG_UIT_PARAMCHECK( 0 < (_num_), E_PAR ); \ + CYG_UIT_PARAMCHECK( CYG_UITRON_NUM( _which_ ) >= (_num_), E_PAR ); \ + CYG_UIT_SPTR( _which_, _num_, _ptr_ ); \ +CYG_MACRO_END + +// And a macro to check that creation of an object is OK +#define CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( _which_, _idx_ ) \ +CYG_MACRO_START \ + CYG_UIT_PARAMCHECK( 0 < (_idx_), E_ID ); \ + CYG_UIT_PARAMCHECK( CYG_UITRON_NUM( _which_ ) >= (_idx_), E_ID ); \ + Cyg_Scheduler::lock(); \ + if ( NULL != CYG_UITRON_PTRS( _which_ )[ ((_idx_) - 1) ] ) { \ + Cyg_Scheduler::unlock(); \ + return E_OBJ; \ + } \ +CYG_MACRO_END + +// define a magic new operator in order to call constructors +#define CYG_UITRON_NEWFUNCTION( _class_ ) \ +inline void *operator new(size_t size, _class_ *ptr) \ +{ \ + CYG_CHECK_DATA_PTR( ptr, "Bad pointer" ); \ + return ptr; \ +} + +// now configury to support selectable create/delete support ie. an +// array of pointers to the objects themselves. +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE +#define CYG_UITRON_CHECK_AND_GETP_TASKS( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_INDIRECT( TASKS, _idx_, _ptr_ ) +#else +#define CYG_UITRON_CHECK_AND_GETP_TASKS( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_DIRECT( TASKS, _idx_, _ptr_ ) +#endif + +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE +#define CYG_UITRON_CHECK_AND_GETP_SEMAS( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_INDIRECT( SEMAS, _idx_, _ptr_ ) +#else +#define CYG_UITRON_CHECK_AND_GETP_SEMAS( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_DIRECT( SEMAS, _idx_, _ptr_ ) +#endif + +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE +#define CYG_UITRON_CHECK_AND_GETP_MBOXES( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_INDIRECT( MBOXES, _idx_, _ptr_ ) +#else +#define CYG_UITRON_CHECK_AND_GETP_MBOXES( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_DIRECT( MBOXES, _idx_, _ptr_ ) +#endif + +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE +#define CYG_UITRON_CHECK_AND_GETP_FLAGS( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_INDIRECT( FLAGS, _idx_, _ptr_ ) +#else +#define CYG_UITRON_CHECK_AND_GETP_FLAGS( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_DIRECT( FLAGS, _idx_, _ptr_ ) +#endif + +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE +#define CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_INDIRECT( MEMPOOLFIXED, _idx_, _ptr_ ) +#else +#define CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_DIRECT( MEMPOOLFIXED, _idx_, _ptr_ ) +#endif + +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE +#define CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_INDIRECT( MEMPOOLVAR, _idx_, _ptr_ ) +#else +#define CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( _idx_, _ptr_ ) \ + CYG_UITRON_CHECK_AND_GETP_DIRECT( MEMPOOLVAR, _idx_, _ptr_ ) +#endif + +// ------------------------------------------------------------------------ +// Common error checking macros + +#if !defined( CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS ) && \ + !defined( CYGDBG_USE_ASSERTS ) +// if not checking and not asserted, these are removed to avoid usused +// variable warnings. +#define CYG_UITRON_CHECK_TASK_CONTEXT_SELF( _self_ ) CYG_EMPTY_STATEMENT +#define CYG_UITRON_CHECK_TASK_CONTEXT() CYG_EMPTY_STATEMENT +#define CYG_UITRON_CHECK_DISPATCH_ENABLED() CYG_EMPTY_STATEMENT +#define CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( _tmout_ ) CYG_EMPTY_STATEMENT + +#else +// the default: +// Check a task is actually a uITRON task +#define CYG_UITRON_CHECK_TASK_CONTEXT_SELF( _self_ ) CYG_MACRO_START \ + CYG_UIT_PARAMCHECK( \ + (&cyg_uitron_TASKS[0] <= (_self_)) && \ + ((_self_) < &cyg_uitron_TASKS[CYGNUM_UITRON_TASKS]), \ + E_CTX ); \ +CYG_MACRO_END + +#define CYG_UITRON_CHECK_TASK_CONTEXT() CYG_MACRO_START \ + Cyg_Thread *self = Cyg_Thread::self(); \ + CYG_UITRON_CHECK_TASK_CONTEXT_SELF( self ); \ +CYG_MACRO_END + +// Check dispatching is enabled for calls which might wait +#define CYG_UITRON_CHECK_DISPATCH_ENABLED() CYG_MACRO_START \ + CYG_UIT_PARAMCHECK( 0 == cyg_uitron_dis_dsp_old_priority, E_CTX ); \ +CYG_MACRO_END + +#define CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO(_tmout_) CYG_MACRO_START \ + CYG_UIT_PARAMCHECK( -1 <= (_tmout_), E_PAR ); \ + if ( TMO_POL != (_tmout_) ) \ + CYG_UITRON_CHECK_DISPATCH_ENABLED(); \ +CYG_MACRO_END + +#endif + +#ifdef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR +#define CYG_UIT_PARAMCHECK_PTR( _p_ ) CYG_MACRO_START \ + CYG_UIT_PARAMCHECK( NADR != (_p_), E_PAR ); \ +CYG_MACRO_END +#else // do check for NULL +#define CYG_UIT_PARAMCHECK_PTR( _p_ ) CYG_MACRO_START \ + CYG_UIT_PARAMCHECK( NADR != (_p_), E_PAR ); \ + CYG_UIT_PARAMCHECK( NULL != (_p_), E_PAR ); \ +CYG_MACRO_END +#endif // !CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + +// ------------------------------------------------------------------------ +// CYG_UITRON_FAIL_RETURN +// +// After a call which waits, it might return with success, or due to a +// timeout or a release wait (a forced escape from the waiting condition). +// This macro examines context and finds out which, then executes a return +// with the correct uITRON condition code. + +#define CYG_UITRON_FAIL_RETURN_SELF( _self_ ) CYG_MACRO_START \ + Cyg_Thread::cyg_reason reason = (_self_)->get_wake_reason(); \ + if ( Cyg_Thread::TIMEOUT == reason ) \ + return E_TMOUT; \ + if ( Cyg_Thread::BREAK == reason ) \ + return E_RLWAI; \ + if ( Cyg_Thread::DESTRUCT == reason ) \ + return E_DLT; \ + return E_SYS; /* if no plausible reason was found */ \ +CYG_MACRO_END + +#define CYG_UITRON_FAIL_RETURN() CYG_MACRO_START \ + Cyg_Thread *self = Cyg_Thread::self(); \ + CYG_UITRON_FAIL_RETURN_SELF( self ); \ +CYG_MACRO_END + +// ------------------------------------------------------------------------ +// Interrupts disabled? +#define CYG_UITRON_CHECK_CPU_UNLOC() \ + CYG_UIT_PARAMCHECK( (Cyg_Interrupt::interrupts_enabled()), E_CTX ) + +// ------------------------------------------------------------------------ +// Timing: is it in eCos clock ticks or milliSeconds (or something else?) + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK + +#ifdef CYGSEM_UITRON_TIME_IS_MILLISECONDS +extern Cyg_Clock::converter uit_clock_to_system; +extern Cyg_Clock::converter uit_clock_from_system; + +#define CYG_UITRON_TIME_UIT_TO_SYS32( t ) \ +Cyg_Clock::convert( (cyg_uint64)(t), &uit_clock_to_system ) + +#define CYG_UITRON_TIME_SYS_TO_UIT32( t ) \ +Cyg_Clock::convert( (cyg_uint64)(t), &uit_clock_from_system ) + +// long (cyg_uint64) versions: +#define CYG_UITRON_TIME_UIT_TO_SYS64( t ) \ +Cyg_Clock::convert( (t), &uit_clock_to_system ) + +#define CYG_UITRON_TIME_SYS_TO_UIT64( t ) \ +Cyg_Clock::convert( (t), &uit_clock_from_system ) + +#else // Time is whatever the system clock is doing: + +// Straight through - int (cyg_int32) argument versions: +#define CYG_UITRON_TIME_UIT_TO_SYS32( t ) ( t ) +#define CYG_UITRON_TIME_SYS_TO_UIT32( t ) ( t ) +// long (cyg_uint64) versions: +#define CYG_UITRON_TIME_UIT_TO_SYS64( t ) ( t ) +#define CYG_UITRON_TIME_SYS_TO_UIT64( t ) ( t ) +#endif + +#endif // CYGVAR_KERNEL_COUNTERS_CLOCK - otherwise these should not be used. + +// ------------------------------------------------------------------------ +// the function definitions themselves: + +// ****************************************************** +// *** 6.5 C Language Interfaces *** +// ****************************************************** + +// - Task Management Functions + +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE +CYG_UITRON_NEWFUNCTION( Cyg_Thread ) + +CYG_UIT_FUNC_INLINE +ER +cre_tsk ( ID tskid, T_CTSK *pk_ctsk ) +{ + ER ret = E_OK; + CYG_UIT_PARAMCHECK_PTR( pk_ctsk ); + CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( TASKS, tskid ); + + Cyg_Thread *p = &(CYG_UITRON_OBJS( TASKS )[ tskid - 1 ]); + cyg_uint32 state = p->get_state(); + if ( 0 == (state & Cyg_Thread::EXITED) ) + ret = E_OBJ; // how did it get to be running? + else if ( ((INT)p->get_stack_size()) < pk_ctsk->stksz ) + ret = E_NOMEM; // more stack requested than available + else { + CYG_UITRON_PTRS( TASKS )[ tskid - 1 ] = + new( p ) Cyg_Thread( + (CYG_ADDRWORD) pk_ctsk->itskpri, + (cyg_thread_entry *)pk_ctsk->task, + (CYG_ADDRWORD) 0, + // preserve the original name and stack: +#ifdef CYGVAR_KERNEL_THREADS_NAME + p->get_name(), +#else + NULL, +#endif + p->get_stack_base(), + p->get_stack_size() ); + // but ensure the task state is dormant: + // (it is not constructed dormant, but suspended) + p->kill(); +#ifdef CYGIMP_THREAD_PRIORITY + // and record the initial priority outside the task too. + CYG_UITRON_TASK_INITIAL_PRIORITY( tskid ) = pk_ctsk->itskpri; +#endif + } + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +del_tsk ( ID tskid ) +{ + Cyg_Thread *p; + ER ret = E_OK; + CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); + + Cyg_Scheduler::lock(); + // deal with the race condition here + if ( p != CYG_UITRON_PTRS( TASKS )[ tskid - 1 ] ) { + Cyg_Scheduler::unlock(); + return E_NOEXS; + } + cyg_uint32 state = p->get_state(); + if ( state & Cyg_Thread::EXITED ) + // just disconnect the pointer from its object + CYG_UITRON_PTRS( TASKS )[ tskid - 1 ] = NULL; + else + ret = E_OBJ; + Cyg_Scheduler::unlock(); + return ret; +} +#endif // CYGPKG_UITRON_TASKS_CREATE_DELETE + +CYG_UIT_FUNC_INLINE +ER +sta_tsk ( ID tskid, INT stacd ) +{ + Cyg_Thread *p; + ER ret = E_OK; + CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); + + Cyg_Scheduler::lock(); + cyg_uint32 state = p->get_state(); +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE + // there is a race condition with deleting the task + // so test it now that we have the scheduler locked + if ( p != CYG_UITRON_PTRS( TASKS )[ tskid - 1 ] ) + ret = E_NOEXS; + else // NOTE dangling else to the next line: +#endif + if ( state & Cyg_Thread::EXITED ) { + p->reinitialize(); +#ifdef CYGIMP_THREAD_PRIORITY + p->set_priority( CYG_UITRON_TASK_INITIAL_PRIORITY( tskid ) ); +#endif + p->set_entry_data( (CYG_ADDRWORD)stacd ); + p->force_resume(); + } + else + ret = E_OBJ; + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +void +ext_tsk ( void ) +{ + Cyg_Thread::exit(); +} + +CYG_UIT_FUNC_INLINE +void +exd_tsk ( void ) +{ +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE + Cyg_Thread *p; + + Cyg_Scheduler::lock(); + p = Cyg_Thread::self(); + ID tskid = (p - (&cyg_uitron_TASKS[0])) + 1; + // just disconnect the pointer from its object + CYG_UITRON_PTRS( TASKS )[ tskid - 1 ] = NULL; + // Any associated storage management, and possibly calling the task + // destructor, is for future versions. +#else + // do nothing - deletion not supported so just exit... +#endif + Cyg_Thread::exit(); + // does not return, does unlock the scheduler for us +} + +CYG_UIT_FUNC_INLINE +ER +ter_tsk ( ID tskid ) +{ + Cyg_Thread *p; + ER ret = E_OK; + CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); + CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); + Cyg_Scheduler::lock(); + if ( (0 != (Cyg_Thread::EXITED & p->get_state())) || + (Cyg_Thread::EXIT == p->get_wake_reason()) ) + // already dormant + ret = E_OBJ; + else { + p->force_resume(); // let it run + p->kill(); // and set prio high so it runs RIGHT NOW!! +#ifdef CYGIMP_THREAD_PRIORITY +#if CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES != 0 + // see if we are already at prio 0: + if ( 0 == cyg_uitron_dis_dsp_old_priority ) + // then dispatch is enabled, we are not at prio 0 +#endif + p->set_priority( (cyg_priority) 0 ); + // if we do not do this, then we are not running a strictly + // uITRON compatible scheduler - so just hope for the best. +#endif + } + Cyg_Scheduler::unlock(); +#ifdef CYGIMP_THREAD_PRIORITY +#if CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES == 0 + if ( (E_OK == ret) && (0 != cyg_uitron_dis_dsp_old_priority) ) { + // then dispatching is disabled, so our prio is 0 too + Cyg_Thread::yield(); // so let the dying thread run; + Cyg_Thread::yield(); // no cost here of making sure. + } +#endif +#endif + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +dis_dsp ( void ) +{ + CYG_UITRON_CHECK_TASK_CONTEXT(); + CYG_UITRON_CHECK_CPU_UNLOC(); + Cyg_Scheduler::lock(); + // Prevent preemption by going up to prio 0 + if ( 0 == cyg_uitron_dis_dsp_old_priority ) { +#ifdef CYGIMP_THREAD_PRIORITY + Cyg_Thread *p = Cyg_Thread::self(); + cyg_uitron_dis_dsp_old_priority = p->get_priority(); + p->set_priority( 0 ); +#else + cyg_uitron_dis_dsp_old_priority = 1; +#endif + } + Cyg_Scheduler::unlock(); + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +ena_dsp ( void ) +{ + CYG_UITRON_CHECK_TASK_CONTEXT(); + CYG_UITRON_CHECK_CPU_UNLOC(); + Cyg_Scheduler::lock(); + // Enable dispatching (if disabled) and maybe switch threads + if ( 0 != cyg_uitron_dis_dsp_old_priority ) { + // We had prevented preemption by going up to prio 0 +#ifdef CYGIMP_THREAD_PRIORITY + Cyg_Thread *p = Cyg_Thread::self(); + p->set_priority( cyg_uitron_dis_dsp_old_priority ); + p->to_queue_head(); // to ensure we continue to run + // if nobody higher pri +#endif + cyg_uitron_dis_dsp_old_priority = 0; + } + Cyg_Scheduler::unlock(); + CYG_UITRON_CHECK_DISPATCH_ENABLED(); // NB: afterwards! + return E_OK; +} + + +CYG_UIT_FUNC_INLINE +ER +chg_pri ( ID tskid, PRI tskpri ) +{ + Cyg_Thread *p; + ER ret = E_OK; + if ( 0 == tskid ) { + p = Cyg_Thread::self(); + CYG_UITRON_CHECK_TASK_CONTEXT_SELF( p ); + } + else + CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); + +#ifdef CYGIMP_THREAD_PRIORITY + if ( 0 == tskpri ) + // then use the initial priority [Level X] + tskpri = CYG_UITRON_TASK_INITIAL_PRIORITY( tskid ); +#endif + CYG_UIT_PARAMCHECK( 0 < tskpri, E_PAR ); +#ifdef CYGIMP_THREAD_PRIORITY +#if CYG_THREAD_MAX_PRIORITY < CYG_THREAD_MIN_PRIORITY + CYG_UIT_PARAMCHECK( CYG_THREAD_MAX_PRIORITY <= tskpri && + tskpri <= CYG_THREAD_MIN_PRIORITY, E_PAR ); +#else + CYG_UIT_PARAMCHECK( CYG_THREAD_MAX_PRIORITY >= tskpri && + tskpri >= CYG_THREAD_MIN_PRIORITY, E_PAR ); +#endif + // Handle changing our own prio specially, if dispatch disabled: + if ( 0 != cyg_uitron_dis_dsp_old_priority ) { + // our actual prio is 0 now and must remain so: + if ( Cyg_Thread::self() == p ) { // by whichever route p was set + // set the priority we will return to when dispatch is enabled: + cyg_uitron_dis_dsp_old_priority = (cyg_uint32)tskpri; + return E_OK; + } + } + Cyg_Scheduler::lock(); + if ( (p->get_state() & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || + (Cyg_Thread::EXIT == p->get_wake_reason()) ) + ret = E_OBJ; // task is dormant + else + p->set_priority( (cyg_priority)tskpri ); + Cyg_Scheduler::unlock(); +#endif // CYGIMP_THREAD_PRIORITY got priorities at all? + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +rot_rdq ( PRI tskpri ) +{ + // zero means our level; easiet way is to yield() the CPU. + if ( 0 == tskpri ) { + Cyg_Thread::yield(); + return E_OK; + } +#ifdef CYGIMP_THREAD_PRIORITY +#if CYG_THREAD_MAX_PRIORITY < CYG_THREAD_MIN_PRIORITY + CYG_UIT_PARAMCHECK( CYG_THREAD_MAX_PRIORITY <= tskpri && + tskpri <= CYG_THREAD_MIN_PRIORITY, E_PAR ); +#else + CYG_UIT_PARAMCHECK( CYG_THREAD_MAX_PRIORITY >= tskpri && + tskpri >= CYG_THREAD_MIN_PRIORITY, E_PAR ); +#endif + Cyg_Thread::rotate_queue( tskpri ); +#endif // CYGIMP_THREAD_PRIORITY got priorities at all? + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +rel_wai ( ID tskid ) +{ + Cyg_Thread *p; + ER ret = E_OK; + CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); + CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); + Cyg_Scheduler::lock(); // get an atomic view of the task + if ( (p->get_state() & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || + (Cyg_Thread::EXIT == p->get_wake_reason()) ) + ret = E_OBJ; // task is dormant + else { + p->release(); + // return E_OBJ if the thread was not sleeping + if ( Cyg_Thread::BREAK != p->get_wake_reason() ) + ret = E_OBJ; + } + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +get_tid ( ID *p_tskid ) +{ + Cyg_Thread *self = Cyg_Thread::self(); + CYG_UIT_PARAMCHECK_PTR( p_tskid ); + if ( (&cyg_uitron_TASKS[0] <= (self)) && + ((self) < &cyg_uitron_TASKS[CYGNUM_UITRON_TASKS]) && + (0 == Cyg_Scheduler::get_sched_lock()) ) + // then I am a uITRON task and not in an interrupt or DSR + *p_tskid = (self - (&cyg_uitron_TASKS[0])) + 1; + else + *p_tskid = 0; // Otherwise, non-task portion + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +ref_tsk ( T_RTSK *pk_rtsk, ID tskid ) +{ + Cyg_Thread *p; + if ( 0 == tskid ) { + p = Cyg_Thread::self(); + CYG_UITRON_CHECK_TASK_CONTEXT_SELF( p ); + tskid = (p - (&cyg_uitron_TASKS[0])) + 1; // it gets used below + } + else + CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); + + CYG_UIT_PARAMCHECK_PTR( pk_rtsk ); + pk_rtsk->exinf = NADR; + Cyg_Scheduler::lock(); // get an atomic view of the task + cyg_uint32 state = p->get_state(); + if ( (state & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || + (Cyg_Thread::EXIT == p->get_wake_reason()) ) + pk_rtsk->tskstat = TTS_DMT; + else if ( state == Cyg_Thread::RUNNING ) + // If it's us, it's running, else it's ready + pk_rtsk->tskstat = (Cyg_Thread::self() == p) + ? TTS_RUN // RUN state (we are it) + : TTS_RDY; // READY state + else if ( state & Cyg_Thread::SUSPENDED ) + pk_rtsk->tskstat = + (state & (Cyg_Thread::COUNTSLEEP | Cyg_Thread::SLEEPING)) + ? TTS_WAS // WAIT-SUSPEND state + : TTS_SUS; // SUSPEND state + else + pk_rtsk->tskstat = + (state & (Cyg_Thread::COUNTSLEEP | Cyg_Thread::SLEEPING)) + ? TTS_WAI // WAIT state + : 0; // Not sure what's happening here! +#ifdef CYGIMP_THREAD_PRIORITY + if ( TTS_DMT == pk_rtsk->tskstat ) + pk_rtsk->tskpri = CYG_UITRON_TASK_INITIAL_PRIORITY( tskid ); + else if ( (TTS_RUN == pk_rtsk->tskstat) && + (0 != cyg_uitron_dis_dsp_old_priority) ) + // then we are it and dispatching is disabled, so + // report our "real" priority - it is 0 in the kernel at the moment + pk_rtsk->tskpri = cyg_uitron_dis_dsp_old_priority; + else + pk_rtsk->tskpri = p->get_priority(); +#else + pk_rtsk->tskpri = -1; // Not applicable +#endif + Cyg_Scheduler::unlock(); + return E_OK; +} + +// - Task-Dependent Synchronization Functions + +CYG_UIT_FUNC_INLINE +ER +sus_tsk ( ID tskid ) +{ + Cyg_Thread *p; + ER ret = E_OK; + CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); + CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); + Cyg_Scheduler::lock(); // get an atomic view of the task + if ( (p->get_state() & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || + (Cyg_Thread::EXIT == p->get_wake_reason()) ) + ret = E_OBJ; // task is dormant + else + p->suspend(); + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +rsm_tsk ( ID tskid ) +{ + Cyg_Thread *p; + ER ret = E_OK; + CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); + CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); + Cyg_Scheduler::lock(); // get an atomic view of the task + cyg_uint32 state = p->get_state(); + if ( 0 == (Cyg_Thread::SUSPENDED & state) ) + ret = E_OBJ; // thread is not suspended + else + p->resume(); + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +frsm_tsk ( ID tskid ) +{ + Cyg_Thread *p; + ER ret = E_OK; + CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); + CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); + Cyg_Scheduler::lock(); // get an atomic view of the task + cyg_uint32 state = p->get_state(); + if ( 0 == (Cyg_Thread::SUSPENDED & state) ) + ret = E_OBJ; // thread is not suspended + else + p->force_resume(); + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +slp_tsk ( void ) +{ + Cyg_Thread *self = Cyg_Thread::self(); + CYG_UITRON_CHECK_TASK_CONTEXT_SELF( self ); + CYG_UITRON_CHECK_DISPATCH_ENABLED(); + // do this now for the case when no sleeping actually occurs + self->set_wake_reason( Cyg_Thread::DONE ); + Cyg_Thread::counted_sleep(); + if ( Cyg_Thread::DONE != self->get_wake_reason() ) + CYG_UITRON_FAIL_RETURN_SELF( self ); + return E_OK; +} + +#ifdef CYGFUN_KERNEL_THREADS_TIMER +CYG_UIT_FUNC_INLINE +ER +tslp_tsk ( TMO tmout ) +{ + Cyg_Thread *self = Cyg_Thread::self(); + CYG_UITRON_CHECK_TASK_CONTEXT_SELF( self ); + CYG_UIT_PARAMCHECK( -1 <= tmout, E_PAR ); + CYG_UITRON_CHECK_DISPATCH_ENABLED(); + // do this now for the case when no sleeping actually occurs + self->set_wake_reason( Cyg_Thread::DONE ); + // note that TMO_POL is not treated specially, though it + // happens to work almost as a poll (some sleeping may occur) + if ( TMO_FEVR == tmout ) + Cyg_Thread::counted_sleep(); + else + Cyg_Thread::counted_sleep( + (cyg_tick_count)CYG_UITRON_TIME_UIT_TO_SYS32( tmout ) ); + if ( Cyg_Thread::DONE != self->get_wake_reason() ) + CYG_UITRON_FAIL_RETURN_SELF( self ); + return E_OK; +} +#endif // CYGFUN_KERNEL_THREADS_TIMER + +CYG_UIT_FUNC_INLINE +ER +wup_tsk ( ID tskid ) +{ + Cyg_Thread *p; + ER ret = E_OK; + CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); + CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); + Cyg_Scheduler::lock(); // get an atomic view of the task + if ( (p->get_state() & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || + (Cyg_Thread::EXIT == p->get_wake_reason()) ) + ret = E_OBJ; // task is dormant + else + p->counted_wake(); + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +can_wup ( INT *p_wupcnt, ID tskid ) +{ + Cyg_Thread *p; + ER ret = E_OK; + if ( 0 == tskid ) { + p = Cyg_Thread::self(); + CYG_UITRON_CHECK_TASK_CONTEXT_SELF( p ); + } + else + CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); + CYG_UIT_PARAMCHECK_PTR( p_wupcnt ); + Cyg_Scheduler::lock(); // get an atomic view of the task + if ( (p->get_state() & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || + (Cyg_Thread::EXIT == p->get_wake_reason()) ) + ret = E_OBJ; // task is dormant + else { + cyg_uint32 result = p->cancel_counted_wake(); + *p_wupcnt = result; + } + Cyg_Scheduler::unlock(); + return ret; +} + +// - Synchronization and Communication Functions + +#ifdef CYGPKG_UITRON_SEMAS +#if 0 < CYG_UITRON_NUM( SEMAS ) + +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + +CYG_UITRON_NEWFUNCTION( Cyg_Counting_Semaphore2 ) + +CYG_UIT_FUNC_INLINE +ER +cre_sem ( ID semid, T_CSEM *pk_csem ) +{ + ER ret = E_OK; + CYG_UIT_PARAMCHECK_PTR( pk_csem ); + CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( SEMAS, semid ); + if ( TA_TFIFO != pk_csem->sematr ) + ret = E_RSATR; + else + CYG_UITRON_PTRS( SEMAS )[ semid - 1 ] = + new( &(CYG_UITRON_OBJS( SEMAS )[ semid - 1 ]) ) + Cyg_Counting_Semaphore2( (cyg_count32)pk_csem->isemcnt ); + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +del_sem ( ID semid ) +{ + Cyg_Counting_Semaphore2 *p; + CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); + Cyg_Scheduler::lock(); + // deal with the race condition here + if ( p != CYG_UITRON_PTRS( SEMAS )[ semid - 1 ] ) { + Cyg_Scheduler::unlock(); + return E_NOEXS; + } + CYG_UITRON_PTRS( SEMAS )[ semid - 1 ] = NULL; + p->~Cyg_Counting_Semaphore2(); + Cyg_Scheduler::unlock(); + return E_OK; +} +#endif // CYGPKG_UITRON_SEMAS_CREATE_DELETE + +CYG_UIT_FUNC_INLINE +ER +sig_sem( ID semid ) +{ + Cyg_Counting_Semaphore2 *p; + CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); + p->post(); + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +wai_sem( ID semid ) +{ + Cyg_Counting_Semaphore2 *p; + CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); + CYG_UITRON_CHECK_DISPATCH_ENABLED(); + cyg_bool result = p->wait(); + if ( !result ) + CYG_UITRON_FAIL_RETURN(); + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +preq_sem ( ID semid ) +{ + Cyg_Counting_Semaphore2 *p; + CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); + cyg_bool result = p->trywait(); + if ( !result ) + return E_TMOUT; + return E_OK; +} + +#ifdef CYGFUN_KERNEL_THREADS_TIMER +CYG_UIT_FUNC_INLINE +ER +twai_sem ( ID semid, TMO tmout ) +{ + Cyg_Counting_Semaphore2 *p; + CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); + CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( tmout ); + // do this now for the case when no sleeping actually occurs + Cyg_Thread *self = Cyg_Thread::self(); + self->set_wake_reason( Cyg_Thread::TIMEOUT ); + cyg_bool result; + if ( TMO_FEVR == tmout ) + result = p->wait(); + else if ( TMO_POL == tmout ) + result = p->trywait(); + else + result = p->wait( + Cyg_Clock::real_time_clock->current_value() + + (cyg_tick_count)CYG_UITRON_TIME_UIT_TO_SYS32( tmout ) ); + if ( ! result ) + CYG_UITRON_FAIL_RETURN_SELF( self ); + return E_OK; + +} +#endif // CYGFUN_KERNEL_THREADS_TIMER + +CYG_UIT_FUNC_INLINE +ER +ref_sem ( T_RSEM *pk_rsem, ID semid ) +{ + Cyg_Counting_Semaphore2 *p; + CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); + CYG_UIT_PARAMCHECK_PTR( pk_rsem ); + pk_rsem->exinf = NADR; + pk_rsem->wtsk = p->waiting(); + pk_rsem->semcnt = p->peek(); + return E_OK; +} + +#endif // 0 < CYG_UITRON_NUM( SEMAS ) +#endif // CYGPKG_UITRON_SEMAS + +#ifdef CYGPKG_UITRON_FLAGS +#if 0 < CYG_UITRON_NUM( FLAGS ) + +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + +CYG_UITRON_NEWFUNCTION( Cyg_Flag ) + +CYG_UIT_FUNC_INLINE +ER +cre_flg ( ID flgid, T_CFLG *pk_cflg ) +{ + ER ret = E_OK; + CYG_UIT_PARAMCHECK_PTR( pk_cflg ); + CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( FLAGS, flgid ); + if ( 0 != ((~(TA_WMUL | TA_WSGL)) & pk_cflg->flgatr) ) + ret = E_RSATR; + else + CYG_UITRON_PTRS( FLAGS )[ flgid - 1 ] = + new( &(CYG_UITRON_OBJS( FLAGS )[ flgid - 1 ]) ) + Cyg_Flag( (Cyg_FlagValue) pk_cflg->iflgptn ); + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +del_flg ( ID flgid ) +{ + Cyg_Flag *p; + CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); + Cyg_Scheduler::lock(); + // deal with the race condition here + if ( p != CYG_UITRON_PTRS( FLAGS )[ flgid - 1 ] ) { + Cyg_Scheduler::unlock(); + return E_NOEXS; + } + CYG_UITRON_PTRS( FLAGS )[ flgid - 1 ] = NULL; + p->~Cyg_Flag(); + Cyg_Scheduler::unlock(); + return E_OK; +} +#endif // CYGPKG_UITRON_FLAGS_CREATE_DELETE + +CYG_UIT_FUNC_INLINE +ER +set_flg ( ID flgid, UINT setptn ) +{ + Cyg_Flag *p; + CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); + p->setbits( setptn ); + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +clr_flg ( ID flgid, UINT clrptn ) +{ + Cyg_Flag *p; + CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); + p->maskbits( clrptn ); + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +wai_flg ( UINT *p_flgptn, ID flgid, UINT waiptn, UINT wfmode ) +{ + Cyg_Flag *p; + CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); + CYG_UIT_PARAMCHECK_PTR( p_flgptn ); + CYG_UIT_PARAMCHECK( 0 == (wfmode & ~Cyg_Flag::MASK), E_PAR ); + CYG_UIT_PARAMCHECK( 0 != waiptn, E_PAR ); + CYG_UITRON_CHECK_DISPATCH_ENABLED(); + // check we can use the wfmode value unchanged + CYG_ASSERT( Cyg_Flag::AND == TWF_ANDW, "Flag AND value bad" ); + CYG_ASSERT( Cyg_Flag::OR == TWF_ORW, "Flag OR value bad" ); + CYG_ASSERT( Cyg_Flag::CLR == TWF_CLR, "Flag CLR value bad" ); + + UINT result = p->wait( waiptn, wfmode ); + if ( ! result ) + CYG_UITRON_FAIL_RETURN(); + *p_flgptn = result; + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +pol_flg ( UINT *p_flgptn, ID flgid, UINT waiptn, UINT wfmode ) +{ + Cyg_Flag *p; + CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); + CYG_UIT_PARAMCHECK_PTR( p_flgptn ); + CYG_UIT_PARAMCHECK( 0 == (wfmode & ~Cyg_Flag::MASK), E_PAR ); + CYG_UIT_PARAMCHECK( 0 != waiptn, E_PAR ); + // check we can use the wfmode value unchanged + CYG_ASSERT( Cyg_Flag::AND == TWF_ANDW, "Flag AND value bad" ); + CYG_ASSERT( Cyg_Flag::OR == TWF_ORW, "Flag OR value bad" ); + CYG_ASSERT( Cyg_Flag::CLR == TWF_CLR, "Flag CLR value bad" ); + + UINT result = p->poll( waiptn, wfmode ); + if ( ! result ) + return E_TMOUT; + *p_flgptn = result; + return E_OK; +} + +#ifdef CYGFUN_KERNEL_THREADS_TIMER +CYG_UIT_FUNC_INLINE +ER +twai_flg ( UINT *p_flgptn, ID flgid, UINT waiptn, UINT wfmode, + TMO tmout ) +{ + Cyg_Flag *p; + CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); + CYG_UIT_PARAMCHECK_PTR( p_flgptn ); + CYG_UIT_PARAMCHECK( 0 == (wfmode & ~Cyg_Flag::MASK), E_PAR ); + CYG_UIT_PARAMCHECK( 0 != waiptn, E_PAR ); + CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( tmout ); + // check we can use the wfmode value unchanged + CYG_ASSERT( Cyg_Flag::AND == TWF_ANDW, "Flag AND value bad" ); + CYG_ASSERT( Cyg_Flag::OR == TWF_ORW, "Flag OR value bad" ); + CYG_ASSERT( Cyg_Flag::CLR == TWF_CLR, "Flag CLR value bad" ); + + // do this now for the case when no sleeping actually occurs + Cyg_Thread *self = Cyg_Thread::self(); + self->set_wake_reason( Cyg_Thread::TIMEOUT ); + UINT result; + if ( TMO_FEVR == tmout ) + result = p->wait( waiptn, wfmode ); + else if ( TMO_POL == tmout ) + result = p->poll( waiptn, wfmode ); + else + result = p->wait( waiptn, wfmode, + Cyg_Clock::real_time_clock->current_value() + + (cyg_tick_count)CYG_UITRON_TIME_UIT_TO_SYS32( tmout ) ); + if ( ! result ) + CYG_UITRON_FAIL_RETURN_SELF( self ); + *p_flgptn = result; + return E_OK; +} +#endif // CYGFUN_KERNEL_THREADS_TIMER + +CYG_UIT_FUNC_INLINE +ER +ref_flg ( T_RFLG *pk_rflg, ID flgid ) +{ + Cyg_Flag *p; + CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); + CYG_UIT_PARAMCHECK_PTR( pk_rflg ); + pk_rflg->exinf = NADR; + pk_rflg->wtsk = p->waiting(); + pk_rflg->flgptn = p->peek(); + return E_OK; +} + +#endif // 0 < CYG_UITRON_NUM( FLAGS ) +#endif // CYGPKG_UITRON_FLAGS + +#ifdef CYGPKG_UITRON_MBOXES +#if 0 < CYG_UITRON_NUM( MBOXES ) + +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE +CYG_UITRON_NEWFUNCTION( Cyg_Mbox ) + +CYG_UIT_FUNC_INLINE +ER +cre_mbx ( ID mbxid, T_CMBX* pk_cmbx ) +{ + ER ret = E_OK; + CYG_UIT_PARAMCHECK_PTR( pk_cmbx ); + CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( MBOXES, mbxid ); + if ( ((ATR)(TA_TFIFO + TA_MFIFO)) != pk_cmbx->mbxatr ) + ret = E_RSATR; + else + CYG_UITRON_PTRS( MBOXES )[ mbxid - 1 ] = + new( &(CYG_UITRON_OBJS( MBOXES )[ mbxid - 1 ]) ) + Cyg_Mbox(); + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +del_mbx ( ID mbxid ) +{ + Cyg_Mbox *p; + CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); + Cyg_Scheduler::lock(); + // deal with the race condition here + if ( p != CYG_UITRON_PTRS( MBOXES )[ mbxid - 1 ] ) { + Cyg_Scheduler::unlock(); + return E_NOEXS; + } + CYG_UITRON_PTRS( MBOXES )[ mbxid - 1 ] = NULL; + p->~Cyg_Mbox(); + Cyg_Scheduler::unlock(); + return E_OK; +} +#endif // CYGPKG_UITRON_MBOXES_CREATE_DELETE + +// This bit of unpleasantness is to allow uITRON programs to send a NULL +// message - if permitted by the parameter checking. +// +// NULL is used internally to mean no message; but -1 is fine. So we send +// a NULL as a NADR and if we see a NULL coming back, change it to a NADR. +// +// One hopes that often this will be optimized out, since the one or both +// of these being true has been detected and errored out just above. + +#ifdef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR +// represent a NULL as NADR internally +#define CYG_UIT_TMSG_FIXUP_IN( _p_ ) CYG_MACRO_START \ + if ( NULL == (_p_) ) \ + (_p_) = (T_MSG *)NADR; \ +CYG_MACRO_END + +// we get a NADR back sometimes, meaning NULL +#define CYG_UIT_TMSG_FIXUP_OUT( _p_ ) CYG_MACRO_START \ + if ( NADR == (_p_) ) \ + (_p_) = (T_MSG *)NULL; \ +CYG_MACRO_END + +#else +// NULL is checked for and makes an error +#define CYG_UIT_TMSG_FIXUP_IN( _p_ ) CYG_EMPTY_STATEMENT +#define CYG_UIT_TMSG_FIXUP_OUT( _p_ ) CYG_EMPTY_STATEMENT +#endif + +// and sometimes either in status enquiries +#define CYG_UIT_TMSG_FIXUP_ALL( _p_ ) CYG_MACRO_START \ + if ( NULL == (_p_) ) \ + (_p_) = (T_MSG *)NADR; \ + else if ( NADR == (_p_) ) \ + (_p_) = (T_MSG *)NULL; \ +CYG_MACRO_END + +CYG_UIT_FUNC_INLINE +ER +snd_msg ( ID mbxid, T_MSG *pk_msg ) +{ + Cyg_Mbox *p; + CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); + CYG_UIT_PARAMCHECK_PTR( pk_msg ); + CYG_UIT_TMSG_FIXUP_IN( pk_msg ); + cyg_bool result = p->tryput( (void *)pk_msg ); + if ( ! result ) + return E_QOVR; + return E_OK; +} + + +CYG_UIT_FUNC_INLINE +ER +rcv_msg ( T_MSG **ppk_msg, ID mbxid ) +{ + Cyg_Mbox *p; + CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); + CYG_UIT_PARAMCHECK_PTR( ppk_msg ); + CYG_UITRON_CHECK_DISPATCH_ENABLED(); + T_MSG *result = (T_MSG *)p->get(); + if ( ! result ) + CYG_UITRON_FAIL_RETURN(); + CYG_UIT_TMSG_FIXUP_OUT( result ); + *ppk_msg = result; + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +prcv_msg ( T_MSG **ppk_msg, ID mbxid ) +{ + Cyg_Mbox *p; + CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); + CYG_UIT_PARAMCHECK_PTR( ppk_msg ); + T_MSG *result = (T_MSG *)p->tryget(); + if ( ! result ) + return E_TMOUT; + CYG_UIT_TMSG_FIXUP_OUT( result ); + *ppk_msg = result; + return E_OK; +} + +#ifdef CYGFUN_KERNEL_THREADS_TIMER +CYG_UIT_FUNC_INLINE +ER +trcv_msg ( T_MSG **ppk_msg, ID mbxid, TMO tmout ) +{ + Cyg_Mbox *p; + CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); + CYG_UIT_PARAMCHECK_PTR( ppk_msg ); + CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( tmout ); + // do this now for the case when no sleeping actually occurs + Cyg_Thread *self = Cyg_Thread::self(); + self->set_wake_reason( Cyg_Thread::TIMEOUT ); + T_MSG *result; + if ( TMO_FEVR == tmout ) + result = (T_MSG *)p->get(); + else if ( TMO_POL == tmout ) + result = (T_MSG *)p->tryget(); + else + result = (T_MSG *)p->get( + Cyg_Clock::real_time_clock->current_value() + + (cyg_tick_count)CYG_UITRON_TIME_UIT_TO_SYS32( tmout ) ); + if ( ! result ) + CYG_UITRON_FAIL_RETURN_SELF( self ); + CYG_UIT_TMSG_FIXUP_OUT( result ); + *ppk_msg = result; + return E_OK; +} +#endif // CYGFUN_KERNEL_THREADS_TIMER + +CYG_UIT_FUNC_INLINE +ER +ref_mbx ( T_RMBX *pk_rmbx, ID mbxid ) +{ + Cyg_Mbox *p; + CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); + CYG_UIT_PARAMCHECK_PTR( pk_rmbx ); + pk_rmbx->exinf = NADR; + pk_rmbx->wtsk = p->waiting_to_get(); + pk_rmbx->pk_msg = (T_MSG *)p->peek_item(); + CYG_UIT_TMSG_FIXUP_ALL( pk_rmbx->pk_msg ); + return E_OK; +} + +#undef CYG_UIT_TMSG_FIXUP_IN +#undef CYG_UIT_TMSG_FIXUP_OUT +#undef CYG_UIT_TMSG_FIXUP_ALL + +#endif // 0 < CYG_UITRON_NUM( MBOXES ) +#endif // CYGPKG_UITRON_MBOXES + +// - Extended Synchronization and Communication Functions + +#if 0 // NOT SUPPORTED +ER cre_mbf ( ID mbfid, T_CMBF *pk_cmbf ); +ER del_mbf ( ID mbfid ); +ER snd_mbf ( ID mbfid, VP msg, INT msgsz ); +ER psnd_mbf ( ID mbfid, VP msg, INT msgsz ); +ER tsnd_mbf ( ID mbfid, VP msg, INT msgsz, TMO tmout ); +ER rcv_mbf ( VP msg, INT *p_msgsz, ID mbfid ); +ER prcv_mbf ( VP msg, INT *p_msgsz, ID mbfid ); +ER trcv_mbf ( VP msg, INT *p_msgsz, ID mbfid, TMO tmout ); +ER ref_mbf ( T_RMBF *pk_rmbf, ID mbfid ); +ER cre_por ( ID porid, T_CPOR *pk_cpor ); +ER del_por ( ID porid ); +ER cal_por ( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT + cmsgsz ); +ER pcal_por ( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT + cmsgsz ); +ER tcal_por ( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT + cmsgsz, TMO tmout ); +ER acp_por ( RNO *p_rdvno, VP msg, INT *p_cmsgsz, ID porid, UINT + acpptn ); +ER pacp_por ( RNO *p_rdvno, VP msg, INT *p_cmsgsz, ID porid, UINT + acpptn ); +ER tacp_por ( RNO *p_rdvno, VP msg, INT *p_cmsgsz, ID porid, UINT + acpptn, TMO tmout ); +ER fwd_por ( ID porid, UINT calptn, RNO rdvno, VP msg, INT cmsgsz + ); +ER rpl_rdv ( RNO rdvno, VP msg, INT rmsgsz ); +ER ref_por ( T_RPOR *pk_rpor, ID porid ); +#endif + +// - Interrupt Management Functions + +#if 0 // NOT SUPPORTED +ER def_int ( UINT dintno, T_DINT *pk_dint ); +void ret_wup ( ID tskid ); +#endif + +CYG_UIT_FUNC_INLINE +ER +loc_cpu ( void ) +{ + CYG_UITRON_CHECK_TASK_CONTEXT(); + Cyg_Scheduler::lock(); + // Prevent preemption by going up to prio 0 + if ( 0 == cyg_uitron_dis_dsp_old_priority ) { +#ifdef CYGIMP_THREAD_PRIORITY + Cyg_Thread *p = Cyg_Thread::self(); + cyg_uitron_dis_dsp_old_priority = p->get_priority(); + p->set_priority( 0 ); +#else + cyg_uitron_dis_dsp_old_priority = 1; +#endif + } + Cyg_Interrupt::disable_interrupts(); + Cyg_Scheduler::unlock(); + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +unl_cpu ( void ) +{ + CYG_UITRON_CHECK_TASK_CONTEXT(); + Cyg_Scheduler::lock(); + // Enable dispatching (if disabled) and maybe switch threads + if ( 0 != cyg_uitron_dis_dsp_old_priority ) { + // We had prevented preemption by going up to prio 0 +#ifdef CYGIMP_THREAD_PRIORITY + Cyg_Thread *p = Cyg_Thread::self(); + p->set_priority( cyg_uitron_dis_dsp_old_priority ); +#endif + cyg_uitron_dis_dsp_old_priority = 0; + } + Cyg_Interrupt::enable_interrupts(); + Cyg_Scheduler::unlock(); + CYG_UITRON_CHECK_DISPATCH_ENABLED(); // NB: afterwards! + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +dis_int ( UINT eintno ) +{ + CYG_INTERRUPT_STATE old_ints; + +#if 0 < CYGNUM_HAL_ISR_MIN + CYG_UIT_PARAMCHECK( CYGNUM_HAL_ISR_MIN <= eintno, E_PAR ); +#endif + CYG_UIT_PARAMCHECK( CYGNUM_HAL_ISR_MAX >= eintno, E_PAR ); + HAL_DISABLE_INTERRUPTS(old_ints); + HAL_INTERRUPT_MASK( eintno ); + HAL_RESTORE_INTERRUPTS(old_ints); + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +ena_int ( UINT eintno ) +{ + CYG_INTERRUPT_STATE old_ints; + +#if 0 < CYGNUM_HAL_ISR_MIN + CYG_UIT_PARAMCHECK( CYGNUM_HAL_ISR_MIN <= eintno, E_PAR ); +#endif + CYG_UIT_PARAMCHECK( CYGNUM_HAL_ISR_MAX >= eintno, E_PAR ); + HAL_DISABLE_INTERRUPTS(old_ints); + HAL_INTERRUPT_UNMASK( eintno ); + HAL_RESTORE_INTERRUPTS(old_ints); + return E_OK; +} + +#if 0 // NOT SUPPORTED +ER chg_iXX ( UINT iXXXX ); +ER ref_iXX ( UINT *p_iXXXX ); +#endif + +// - Memorypool Management Functions +#ifdef CYGPKG_UITRON_MEMPOOLVAR +#if 0 < CYG_UITRON_NUM( MEMPOOLVAR ) + +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + +CYG_UITRON_NEWFUNCTION( Cyg_Mempool_Variable ) + +CYG_UIT_FUNC_INLINE +ER +cre_mpl ( ID mplid, T_CMPL *pk_cmpl ) +{ + ER ret = E_OK; + CYG_UIT_PARAMCHECK_PTR( pk_cmpl ); + CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( MEMPOOLVAR, mplid ); + Cyg_Mempool_Variable *p = &(CYG_UITRON_OBJS( MEMPOOLVAR )[ mplid - 1 ]); + Cyg_Mempool_Status stat; + + // preserve the original memory area to use + p->get_status( CYG_MEMPOOL_STAT_ORIGBASE|CYG_MEMPOOL_STAT_ORIGSIZE, stat ); + + if ( stat.origsize < pk_cmpl->mplsz ) + ret = E_NOMEM; + else if ( TA_TFIFO != pk_cmpl->mplatr ) + ret = E_RSATR; + else + CYG_UITRON_PTRS( MEMPOOLVAR )[ mplid - 1 ] = + new( p ) Cyg_Mempool_Variable( + const_cast(stat.origbase), stat.origsize ); + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +del_mpl ( ID mplid ) +{ + Cyg_Mempool_Variable *p; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); + Cyg_Scheduler::lock(); + // deal with the race condition here + if ( p != CYG_UITRON_PTRS( MEMPOOLVAR )[ mplid - 1 ] ) { + Cyg_Scheduler::unlock(); + return E_NOEXS; + } + CYG_UITRON_PTRS( MEMPOOLVAR )[ mplid - 1 ] = NULL; + p->~Cyg_Mempool_Variable(); + Cyg_Scheduler::unlock(); + return E_OK; +} +#endif // CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + +CYG_UIT_FUNC_INLINE +ER +get_blk ( VP *p_blk, ID mplid, INT blksz ) +{ + Cyg_Mempool_Variable *p; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); + CYG_UIT_PARAMCHECK_PTR( p_blk ); + CYG_UIT_PARAMCHECK( blksz > 0, E_PAR ); + CYG_UITRON_CHECK_DISPATCH_ENABLED(); + VP result = (VP)p->alloc(blksz); + if ( ! result ) + CYG_UITRON_FAIL_RETURN(); + *p_blk = result; + return E_OK; +} + + +CYG_UIT_FUNC_INLINE +ER +pget_blk ( VP *p_blk, ID mplid, INT blksz ) +{ + Cyg_Mempool_Variable *p; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); + CYG_UIT_PARAMCHECK_PTR( p_blk ); + CYG_UIT_PARAMCHECK( blksz > 0, E_PAR ); + VP result = (VP)p->try_alloc(blksz); + if ( ! result ) + return E_TMOUT; + *p_blk = result; + return E_OK; +} + +#ifdef CYGFUN_KERNEL_THREADS_TIMER +CYG_UIT_FUNC_INLINE +ER +tget_blk ( VP *p_blk, ID mplid, INT blksz, TMO tmout ) +{ + Cyg_Mempool_Variable *p; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); + CYG_UIT_PARAMCHECK_PTR( p_blk ); + CYG_UIT_PARAMCHECK( blksz > 0, E_PAR ); + CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( tmout ); + // do this now for the case when no sleeping actually occurs + Cyg_Thread *self = Cyg_Thread::self(); + self->set_wake_reason( Cyg_Thread::TIMEOUT ); + VP result; + if ( TMO_FEVR == tmout ) + result = p->alloc(blksz); + else if ( TMO_POL == tmout ) + result = p->try_alloc(blksz); + else + result = p->alloc( blksz, + Cyg_Clock::real_time_clock->current_value() + + (cyg_tick_count)CYG_UITRON_TIME_UIT_TO_SYS32( tmout ) ); + if ( ! result ) + CYG_UITRON_FAIL_RETURN_SELF( self ); + *p_blk = result; + return E_OK; +} +#endif // CYGFUN_KERNEL_THREADS_TIMER + +CYG_UIT_FUNC_INLINE +ER +rel_blk ( ID mplid, VP blk ) +{ + Cyg_Mempool_Variable *p; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); + CYG_UIT_PARAMCHECK_PTR( blk ); + cyg_bool result = p->free( (cyg_uint8 *)blk ); + if ( ! result ) + return E_PAR; + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +ref_mpl ( T_RMPL *pk_rmpl, ID mplid ) +{ + Cyg_Mempool_Variable *p; + Cyg_Mempool_Status stat; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); + CYG_UIT_PARAMCHECK_PTR( pk_rmpl ); + p->get_status( CYG_MEMPOOL_STAT_WAITING| + CYG_MEMPOOL_STAT_TOTALFREE| + CYG_MEMPOOL_STAT_MAXFREE, stat ); + + pk_rmpl->exinf = NADR; + pk_rmpl->wtsk = stat.waiting; + pk_rmpl->frsz = stat.totalfree; + pk_rmpl->maxsz = stat.maxfree; + + return E_OK; +} + +#endif // 0 < CYG_UITRON_NUM( MEMPOOLVAR ) +#endif // CYGPKG_UITRON_MEMPOOLVAR + +#ifdef CYGPKG_UITRON_MEMPOOLFIXED +#if 0 < CYG_UITRON_NUM( MEMPOOLFIXED ) + +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + +CYG_UITRON_NEWFUNCTION( Cyg_Mempool_Fixed ) + +CYG_UIT_FUNC_INLINE +ER +cre_mpf ( ID mpfid, T_CMPF *pk_cmpf ) +{ + ER ret = E_OK; + CYG_UIT_PARAMCHECK_PTR( pk_cmpf ); + CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( MEMPOOLFIXED, mpfid ); + Cyg_Mempool_Fixed *p = &(CYG_UITRON_OBJS( MEMPOOLFIXED )[ mpfid - 1 ]); + Cyg_Mempool_Status stat; + + // preserve the original memory area to use + p->get_status( CYG_MEMPOOL_STAT_ORIGBASE|CYG_MEMPOOL_STAT_ORIGSIZE, stat ); + + if ( stat.origsize < (pk_cmpf->blfsz * (pk_cmpf->mpfcnt + 1)) ) + ret = E_NOMEM; + else if ( TA_TFIFO != pk_cmpf->mpfatr ) + ret = E_RSATR; + else + CYG_UITRON_PTRS( MEMPOOLFIXED )[ mpfid - 1 ] = + new( p ) + Cyg_Mempool_Fixed( const_cast(stat.origbase), + stat.origsize, (CYG_ADDRWORD)pk_cmpf->blfsz ); + Cyg_Scheduler::unlock(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +del_mpf ( ID mpfid ) +{ + Cyg_Mempool_Fixed *p; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); + Cyg_Scheduler::lock(); + // deal with the race condition here + if ( p != CYG_UITRON_PTRS( MEMPOOLFIXED )[ mpfid - 1 ] ) { + Cyg_Scheduler::unlock(); + return E_NOEXS; + } + CYG_UITRON_PTRS( MEMPOOLFIXED )[ mpfid - 1 ] = NULL; + p->~Cyg_Mempool_Fixed(); + Cyg_Scheduler::unlock(); + return E_OK; +} +#endif // CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + +CYG_UIT_FUNC_INLINE +ER +get_blf ( VP *p_blf, ID mpfid ) +{ + Cyg_Mempool_Fixed *p; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); + CYG_UIT_PARAMCHECK_PTR( p_blf ); + CYG_UITRON_CHECK_DISPATCH_ENABLED(); + VP result = (VP)p->alloc(); + if ( ! result ) + CYG_UITRON_FAIL_RETURN(); + *p_blf = result; + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +pget_blf ( VP *p_blf, ID mpfid ) +{ + Cyg_Mempool_Fixed *p; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); + CYG_UIT_PARAMCHECK_PTR( p_blf ); + VP result = (VP)p->try_alloc(); + if ( ! result ) + return E_TMOUT; + *p_blf = result; + return E_OK; +} + +#ifdef CYGFUN_KERNEL_THREADS_TIMER +CYG_UIT_FUNC_INLINE +ER +tget_blf ( VP *p_blf, ID mpfid, TMO tmout ) +{ + Cyg_Mempool_Fixed *p; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); + CYG_UIT_PARAMCHECK_PTR( p_blf ); + CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( tmout ); + // do this now for the case when no sleeping actually occurs + Cyg_Thread *self = Cyg_Thread::self(); + self->set_wake_reason( Cyg_Thread::TIMEOUT ); + VP result; + if ( TMO_FEVR == tmout ) + result = p->alloc(); + else if ( TMO_POL == tmout ) + result = p->try_alloc(); + else + result = p->alloc( + Cyg_Clock::real_time_clock->current_value() + + (cyg_tick_count)CYG_UITRON_TIME_UIT_TO_SYS32( tmout ) ); + if ( ! result ) + CYG_UITRON_FAIL_RETURN_SELF( self ); + *p_blf = result; + return E_OK; +} +#endif // CYGFUN_KERNEL_THREADS_TIMER + +CYG_UIT_FUNC_INLINE +ER +rel_blf ( ID mpfid, VP blf ) +{ + Cyg_Mempool_Fixed *p; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); + CYG_UIT_PARAMCHECK_PTR( blf ); + cyg_bool result = p->free( (cyg_uint8 *)blf ); + if ( ! result ) + return E_PAR; + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +ref_mpf ( T_RMPF *pk_rmpf, ID mpfid ) +{ + Cyg_Mempool_Fixed *p; + Cyg_Mempool_Status stat; + CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); + CYG_UIT_PARAMCHECK_PTR( pk_rmpf ); + + p->get_status( CYG_MEMPOOL_STAT_WAITING| + CYG_MEMPOOL_STAT_TOTALFREE| + CYG_MEMPOOL_STAT_TOTALALLOCATED| + CYG_MEMPOOL_STAT_BLOCKSIZE, stat ); + + pk_rmpf->exinf = NADR; + pk_rmpf->wtsk = stat.waiting; + + pk_rmpf->frbcnt = stat.totalfree / stat.blocksize; + // these two are "implementation dependent" ie. eCos only + pk_rmpf->numbcnt = stat.totalallocated / stat.blocksize; + pk_rmpf->bsize = stat.blocksize; + + return E_OK; +} + +#endif // 0 < CYG_UITRON_NUM( MEMPOOLFIXED ) +#endif // CYGPKG_UITRON_MEMPOOLFIXED + +// - Time Management Functions + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK +CYG_UIT_FUNC_INLINE +ER +set_tim ( SYSTIME *pk_tim ) +{ + CYG_UIT_PARAMCHECK_PTR( pk_tim ); + Cyg_Clock::real_time_clock->set_value( + CYG_UITRON_TIME_UIT_TO_SYS64( *pk_tim ) ); + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +get_tim ( SYSTIME *pk_tim ) +{ + CYG_UIT_PARAMCHECK_PTR( pk_tim ); + *pk_tim = CYG_UITRON_TIME_SYS_TO_UIT64( + Cyg_Clock::real_time_clock->current_value() ); + return E_OK; +} +#endif // CYGVAR_KERNEL_COUNTERS_CLOCK + + +#ifdef CYGFUN_KERNEL_THREADS_TIMER +CYG_UIT_FUNC_INLINE +ER +dly_tsk ( DLYTIME dlytim ) +{ + CYG_UIT_PARAMCHECK( 0 <= dlytim, E_PAR ); + CYG_UITRON_CHECK_DISPATCH_ENABLED(); + if ( 0 >= dlytim ) + return E_OK; + Cyg_Thread *self = Cyg_Thread::self(); + CYG_UITRON_CHECK_TASK_CONTEXT_SELF( self ); + self->delay( CYG_UITRON_TIME_UIT_TO_SYS64( dlytim ) ); + if ( Cyg_Thread::DONE != self->get_wake_reason() ) + CYG_UITRON_FAIL_RETURN_SELF( self ); + return E_OK; +} +#endif // CYGFUN_KERNEL_THREADS_TIMER + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK +#ifdef CYGPKG_UITRON_CYCLICS +#if 0 < CYG_UITRON_NUM( CYCLICS ) +CYG_UIT_FUNC_INLINE +ER +def_cyc ( HNO cycno, T_DCYC *pk_dcyc ) +{ + // pk_dcyc->cycatr is ignored + // The only relevant attribute is TA_HLNG/TA_ASM. + // This can be ignored as assembler routines are defined to be + // more conservative with registers than the procedure call standard. + cyg_tick_count t; + Cyg_Timer *p; + CYG_UITRON_CHECK_AND_GETHDLR( CYCLICS, cycno, p ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + CYG_UIT_PARAMCHECK( NULL != pk_dcyc, E_PAR ); +#endif + if( NADR == pk_dcyc ) { + p->~Cyg_Timer(); + return E_OK; + } + CYG_UIT_PARAMCHECK( 0 == (pk_dcyc->cycact & ~TCY_ON), E_PAR ); + CYG_UIT_PARAMCHECK( 0 < pk_dcyc->cyctim, E_PAR ); + t = CYG_UITRON_TIME_UIT_TO_SYS64( pk_dcyc->cyctim ); + p->initialize( + Cyg_Clock::real_time_clock, + (cyg_alarm_fn *)pk_dcyc->cychdr, + (CYG_ADDRWORD)pk_dcyc->exinf, + Cyg_Clock::real_time_clock->current_value() + t, + t, + pk_dcyc->cycact); + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +act_cyc ( HNO cycno, UINT cycact ) +{ + Cyg_Timer *p; + CYG_UITRON_CHECK_AND_GETHDLR( CYCLICS, cycno, p ); + CYG_UIT_PARAMCHECK( p->is_initialized(), E_NOEXS); + CYG_UIT_PARAMCHECK( 0 == (cycact & ~(TCY_ON | TCY_INI)), E_PAR ); + p->activate(cycact); + return E_OK; +} + + +CYG_UIT_FUNC_INLINE +ER +ref_cyc ( T_RCYC *pk_rcyc, HNO cycno ) +{ + Cyg_Timer *p; + cyg_tick_count t; + CYG_UITRON_CHECK_AND_GETHDLR( CYCLICS, cycno, p ); + CYG_UIT_PARAMCHECK( p->is_initialized(), E_NOEXS); + CYG_UIT_PARAMCHECK_PTR( pk_rcyc ); + + pk_rcyc->exinf = (VP)p->get_data(); + Cyg_Scheduler::lock(); + t = p->get_trigger() - Cyg_Clock::real_time_clock->current_value(); + Cyg_Scheduler::unlock(); + pk_rcyc->lfttim = CYG_UITRON_TIME_SYS_TO_UIT64( t ); + pk_rcyc->cycact = (UINT)p->is_enabled(); + return E_OK; +} +#endif // 0 < CYG_UITRON_NUM( CYCLICS ) +#endif // CYGPKG_UITRON_CYCLICS + +#ifdef CYGPKG_UITRON_ALARMS +#if 0 < CYG_UITRON_NUM( ALARMS ) +CYG_UIT_FUNC_INLINE +ER +def_alm ( HNO almno, T_DALM *pk_dalm ) +{ + Cyg_Timer *p; + cyg_tick_count t, now; + CYG_UITRON_CHECK_AND_GETHDLR( ALARMS, almno, p ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + CYG_UIT_PARAMCHECK( NULL != pk_dalm, E_PAR ); +#endif + if( NADR == pk_dalm ) { + p->~Cyg_Timer(); + return E_OK; + } + + CYG_UIT_PARAMCHECK( 0 == (pk_dalm->tmmode & ~TTM_REL), E_PAR ); + CYG_UIT_PARAMCHECK( 0 < pk_dalm->almtim, E_PAR ); + + // make the time arithmetic safe without locking + now = Cyg_Clock::real_time_clock->current_value(); + t = CYG_UITRON_TIME_UIT_TO_SYS64( pk_dalm->almtim ); + if( TTM_REL & pk_dalm->tmmode ) + t += now; + + CYG_UIT_PARAMCHECK( now < t, E_PAR ); + + p->initialize(Cyg_Clock::real_time_clock, + (cyg_alarm_fn *)pk_dalm->almhdr, + (CYG_ADDRWORD)pk_dalm->exinf, + t, 0, Cyg_Timer::ENABLE); + + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +ref_alm ( T_RALM *pk_ralm, HNO almno ) +{ + Cyg_Timer *p; + cyg_tick_count t; + + CYG_UITRON_CHECK_AND_GETHDLR( ALARMS, almno, p ); + CYG_UIT_PARAMCHECK_PTR( pk_ralm ); + CYG_UIT_PARAMCHECK( p->is_initialized(), E_NOEXS); + + Cyg_Scheduler::lock(); + t = p->get_trigger() - Cyg_Clock::real_time_clock->current_value(); + Cyg_Scheduler::unlock(); + pk_ralm->exinf = (VP)p->get_data(); + pk_ralm->lfttim = CYG_UITRON_TIME_SYS_TO_UIT64( t ); + return E_OK; +} +#endif // 0 < CYG_UITRON_NUM( ALARMS ) +#endif // CYGPKG_UITRON_ALARMS + +#endif // CYGVAR_KERNEL_COUNTERS_CLOCK + +// - System Management Functions + +CYG_UIT_FUNC_INLINE +ER +get_ver ( T_VER *pk_ver ) +{ + CYG_UIT_PARAMCHECK_PTR( pk_ver ); + + pk_ver->maker = CYGNUM_UITRON_VER_MAKER; + pk_ver->id = CYGNUM_UITRON_VER_ID; + pk_ver->spver = CYGNUM_UITRON_VER_SPVER; + pk_ver->prver = CYGNUM_UITRON_VER_PRVER; + pk_ver->prno[0] = CYGNUM_UITRON_VER_PRNO_0; + pk_ver->prno[1] = CYGNUM_UITRON_VER_PRNO_1; + pk_ver->prno[2] = CYGNUM_UITRON_VER_PRNO_2; + pk_ver->prno[3] = CYGNUM_UITRON_VER_PRNO_3; + pk_ver->cpu = CYGNUM_UITRON_VER_CPU; + pk_ver->var = CYGNUM_UITRON_VER_VAR; + + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +ref_sys ( T_RSYS *pk_rsys ) +{ + CYG_UIT_PARAMCHECK_PTR( pk_rsys ); + if ( ! Cyg_Interrupt::interrupts_enabled() ) + // CPU is locked + pk_rsys->sysstat = TSS_LOC; + else + pk_rsys->sysstat = + (0 == cyg_uitron_dis_dsp_old_priority) ? TSS_TSK : TSS_DDSP; + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +ref_cfg ( T_RCFG *pk_rcfg ) +{ + CYG_UIT_PARAMCHECK_PTR( pk_rcfg ); + // no details here yet + return E_OK; +} + +#if 0 // NOT SUPPORTED +ER def_svc ( FN s_fncd, T_DSVC *pk_dsvc ); +ER def_exc ( UINT exckind, T_DEXC *pk_dexc ); +#endif + +// - Network Support Functions + +#if 0 // NOT SUPPORTED +ER nrea_dat ( INT *p_reasz, VP dstadr, NODE srcnode, VP srcadr, + INT datsz ); +ER nwri_dat ( INT *p_wrisz, NODE dstnode, VP dstadr, VP srcadr, + INT datsz ); +ER nget_nod ( NODE *p_node ); +ER nget_ver ( T_VER *pk_ver, NODE node ); +#endif + +// ======================================================================== + +#endif // CYGPKG_UITRON + +#endif // CYGPRI_UITRON_FUNCS_HERE_AND_NOW + +#endif // CYGONCE_COMPAT_UITRON_UIT_FUNC_INL +//EOF uit_func.inl diff --git a/packages/compat/uitron/v2_0/include/uit_ifnc.h b/packages/compat/uitron/v2_0/include/uit_ifnc.h new file mode 100644 index 00000000..d558b47f --- /dev/null +++ b/packages/compat/uitron/v2_0/include/uit_ifnc.h @@ -0,0 +1,182 @@ +#ifndef CYGONCE_COMPAT_UITRON_UIT_IFNC_H +#define CYGONCE_COMPAT_UITRON_UIT_IFNC_H +//=========================================================================== +// +// uit_ifnc.h +// +// uITRON compatibility functions +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1999-08-16 +// Purpose: uITRON compatibility functions +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +// ------------------------------------------------------------------------ +// Source Code Organization +// +// First, see pkgconf/uitron.h for details of applicable configuration +// options. +// +// This file uit_ifnc.h provides prototypes for the task-independent parts +// of the uITRON API, that is functions named ixxx_yyy() for calling in +// ISRs. We also define the uitron helper DSR that is needed to despool +// stored up requests. +// ------------------------------------------------------------------------ + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al + +#ifdef CYGPKG_UITRON + +#include // types; cyg_int32, CYG_ADDRWORD + +#include // uITRON types; ER ID TMO T_MSG +#include // uITRON funcs and control macros. + +// ======================================================================== +// u I T R O N F U N C T I O N S +// The function declarations themselves: + +// ------------------- These functions can be inline if so configured +CYG_UIT_FUNC_EXTERN_BEGIN + +// ****************************************************** +// *** 6.5 C Language Interfaces *** +// ****************************************************** + +// - Task Management Functions + +// (None) + +// - Task-Dependent Synchronization Functions + +//ER irsm_tsk ( ID tskid ); +//ER ifrsm_tsk ( ID tskid ); + +ER iwup_tsk ( ID tskid ); + +// - Synchronization and Communication Functions + +ER isig_sem ( ID semid ); + +ER iset_flg ( ID flgid, UINT setptn ); + +ER isnd_msg ( ID mbxid, T_MSG *pk_msg ); + +// - Extended Synchronization and Communication Functions + +// - Interrupt Management Functions + +// (None) + +// --------------------------------------------------------------- + +#define CYGPRI_UITRON_SET_RETCODE( _z_ ) do { \ + extern volatile int cyg_uit_dsr_actions_head; \ + extern volatile int cyg_uit_dsr_actions_tail; \ + (_z_) = (cyg_uit_dsr_actions_head == cyg_uit_dsr_actions_tail) ? 1 : 3; \ +} while ( 0 ) + +//void ret_wup ( ID tskid ); +// Awaken the task (safely) and return Cyg_Interrupt::CALL_DSR +#define ret_wup( _id_ ) do { \ + register int retcode; \ + (void)iwup_tsk( (_id_) ); \ + CYGPRI_UITRON_SET_RETCODE( retcode ); \ + return retcode; \ +} while ( 0 ) + +// Subsitute a version of ret_int that returns Cyg_Interrupt::CALL_DSR +#undef ret_int +#define ret_int() do { \ + register int retcode; \ + CYGPRI_UITRON_SET_RETCODE( retcode ); \ + return retcode; \ +} while ( 0 ) + + +// - Memorypool Management Functions + +// (None) + +// - Time Management Functions + +// (None) + +// - System Management Functions + +// (None) + +// - Network Support Functions + +// (None) + +CYG_UIT_FUNC_EXTERN_END +// ------------------- End of functions that can be inlined + + +// ======================================================================== +// DSR: use this DSR with the uITRON-type ISR that uses the functions above +// to get delayed/safe execution of the wakeup-type functions above. + +#ifdef __cplusplus +extern "C" +#endif +void cyg_uitron_dsr( unsigned int vector, unsigned int count, unsigned int data ); + + +// ======================================================================== + +#ifdef CYGPRI_UITRON_FUNCS_HERE_AND_NOW +// functions are inline OR we are in the outline implementation, so define +// the functions as inlines or plain functions depending on the value of +// CYG_UIT_FUNC_INLINE from above. +#include +#endif // CYGPRI_UITRON_FUNCS_HERE_AND_NOW + +// ------------------------------------------------------------------------ +#endif // CYGPKG_UITRON + +#endif // CYGONCE_COMPAT_UITRON_UIT_IFNC_H +// EOF uit_ifnc.h diff --git a/packages/compat/uitron/v2_0/include/uit_ifnc.inl b/packages/compat/uitron/v2_0/include/uit_ifnc.inl new file mode 100644 index 00000000..a864b3e8 --- /dev/null +++ b/packages/compat/uitron/v2_0/include/uit_ifnc.inl @@ -0,0 +1,218 @@ +#ifndef CYGONCE_COMPAT_UITRON_UIT_IFNC_INL +#define CYGONCE_COMPAT_UITRON_UIT_IFNC_INL +//=========================================================================== +// +// uit_ifnc.inl +// +// uITRON compatibility functions +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1999-08-16 +// Purpose: uITRON compatibility functions +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#ifdef CYGPKG_UITRON + +#ifdef CYGPRI_UITRON_FUNCS_HERE_AND_NOW + +class Cyg_Uit_Action { +public: + typedef enum { + WUP_TSK, + SIG_SEM, + SET_FLG, + SND_MSG + } action; +}; + +extern volatile int cyg_uit_dsr_actions_head; +extern volatile int cyg_uit_dsr_actions_tail; + +#define CYGNUM_UITRON_ISR_ACTION_QUEUEMASK (CYGNUM_UITRON_ISR_ACTION_QUEUESIZE-1) + +#if ((~CYGNUM_UITRON_ISR_ACTION_QUEUEMASK) & \ + ~((~CYGNUM_UITRON_ISR_ACTION_QUEUEMASK)-1)) \ + != CYGNUM_UITRON_ISR_ACTION_QUEUESIZE +#error CYGNUM_UITRON_ISR_ACTION_QUEUESIZE not a power of 2 +#endif + +extern Cyg_Uit_Action::action +cyg_uit_dsr_actions[ CYGNUM_UITRON_ISR_ACTION_QUEUESIZE ]; + +extern ID +cyg_uit_dsr_act_ids[ CYGNUM_UITRON_ISR_ACTION_QUEUESIZE ]; + +extern CYG_ADDRWORD +cyg_uit_dsr_act_a1s[ CYGNUM_UITRON_ISR_ACTION_QUEUESIZE ]; + +CYG_UIT_FUNC_INLINE +ER +iwup_tsk ( ID tskid ) +{ +#ifdef CYGSEM_UITRON_ISRFUNCS_TRY_IMMEDIATE_EXECUTION + if ( 1 >= Cyg_Scheduler::get_sched_lock() ) { + // then this ISR is the first one, and the sched was locked by the + // interrupt code. So this is safe. + return wup_tsk( tskid ); + } +#endif + + register int i, head; + i = cyg_uit_dsr_actions_head; + head = CYGNUM_UITRON_ISR_ACTION_QUEUEMASK & ( 1 + i ); + // If interrupts can be recursive, then there is a race here where a + // slot may be overwritten by a recursive interrupt, or actions from + // such lost; better though than having a slot contain *mixed* data + // from two intermingled interrupts. + if ( head != cyg_uit_dsr_actions_tail ) { + cyg_uit_dsr_actions_head = head; + cyg_uit_dsr_actions[ i ] = Cyg_Uit_Action::WUP_TSK; + cyg_uit_dsr_act_ids[ i ] = tskid; + } + return E_OK; +} + +#ifdef CYGPKG_UITRON_SEMAS +#if 0 < CYG_UITRON_NUM( SEMAS ) +CYG_UIT_FUNC_INLINE +ER +isig_sem ( ID semid ) +{ +#ifdef CYGSEM_UITRON_ISRFUNCS_TRY_IMMEDIATE_EXECUTION + if ( 1 >= Cyg_Scheduler::get_sched_lock() ) { + // then this ISR is the first one, and the sched was locked by the + // interrupt code. So this is safe. + return sig_sem( semid ); + } +#endif + + register int i, head; + i = cyg_uit_dsr_actions_head; + head = CYGNUM_UITRON_ISR_ACTION_QUEUEMASK & ( 1 + i ); + // If interrupts can be recursive, then there is a race here where a + // slot may be overwritten by a recursive interrupt, or actions from + // such lost; better though than having a slot contain *mixed* data + // from two intermingled interrupts. + if ( head != cyg_uit_dsr_actions_tail ) { + cyg_uit_dsr_actions_head = head; + cyg_uit_dsr_actions[ i ] = Cyg_Uit_Action::SIG_SEM; + cyg_uit_dsr_act_ids[ i ] = semid; + } + return E_OK; +} +#endif // 0 < CYG_UITRON_NUM( SEMAS ) +#endif // CYGPKG_UITRON_SEMAS + +#ifdef CYGPKG_UITRON_FLAGS +#if 0 < CYG_UITRON_NUM( FLAGS ) +CYG_UIT_FUNC_INLINE +ER +iset_flg ( ID flgid, UINT setptn ) +{ +#ifdef CYGSEM_UITRON_ISRFUNCS_TRY_IMMEDIATE_EXECUTION + if ( 1 >= Cyg_Scheduler::get_sched_lock() ) { + // then this ISR is the first one, and the sched was locked by the + // interrupt code. So this is safe. + return set_flg( flgid, setptn ); + } +#endif + + register int i, head; + i = cyg_uit_dsr_actions_head; + head = CYGNUM_UITRON_ISR_ACTION_QUEUEMASK & ( 1 + i ); + // If interrupts can be recursive, then there is a race here where a + // slot may be overwritten by a recursive interrupt, or actions from + // such lost; better though than having a slot contain *mixed* data + // from two intermingled interrupts. + if ( head != cyg_uit_dsr_actions_tail ) { + cyg_uit_dsr_actions_head = head; + cyg_uit_dsr_actions[ i ] = Cyg_Uit_Action::SET_FLG; + cyg_uit_dsr_act_ids[ i ] = flgid; + cyg_uit_dsr_act_a1s[ i ] = (CYG_ADDRWORD)setptn; + } + return E_OK; +} +#endif // 0 < CYG_UITRON_NUM( FLAGS ) +#endif // CYGPKG_UITRON_FLAGS + +#ifdef CYGPKG_UITRON_MBOXES +#if 0 < CYG_UITRON_NUM( MBOXES ) +CYG_UIT_FUNC_INLINE +ER +isnd_msg ( ID mbxid, T_MSG *pk_msg ) +{ +#ifdef CYGSEM_UITRON_ISRFUNCS_TRY_IMMEDIATE_EXECUTION + if ( 1 >= Cyg_Scheduler::get_sched_lock() ) { + // then this ISR is the first one, and the sched was locked by the + // interrupt code. So this is safe. + return snd_msg( mbxid, pk_msg ); + } +#endif + + register int i, head; + i = cyg_uit_dsr_actions_head; + head = CYGNUM_UITRON_ISR_ACTION_QUEUEMASK & ( 1 + i ); + // If interrupts can be recursive, then there is a race here where a + // slot may be overwritten by a recursive interrupt, or actions from + // such lost; better though than having a slot contain *mixed* data + // from two intermingled interrupts. + if ( head != cyg_uit_dsr_actions_tail ) { + cyg_uit_dsr_actions_head = head; + cyg_uit_dsr_actions[ i ] = Cyg_Uit_Action::SND_MSG; + cyg_uit_dsr_act_ids[ i ] = mbxid; + cyg_uit_dsr_act_a1s[ i ] = (CYG_ADDRWORD)pk_msg; + } + return E_OK; +} +#endif // 0 < CYG_UITRON_NUM( MBOXES ) +#endif // CYGPKG_UITRON_MBOXES + +// ======================================================================== + +#endif // CYGPKG_UITRON + +#endif // CYGPRI_UITRON_FUNCS_HERE_AND_NOW + +#endif // CYGONCE_COMPAT_UITRON_UIT_IFNC_INL +//EOF uit_ifnc.inl diff --git a/packages/compat/uitron/v2_0/include/uit_objs.hxx b/packages/compat/uitron/v2_0/include/uit_objs.hxx new file mode 100644 index 00000000..e2efff99 --- /dev/null +++ b/packages/compat/uitron/v2_0/include/uit_objs.hxx @@ -0,0 +1,177 @@ +#ifndef CYGONCE_COMPAT_UITRON_UIT_OBJS_HXX +#define CYGONCE_COMPAT_UITRON_UIT_OBJS_HXX +//=========================================================================== +// +// uit_objs.hxx +// +// uITRON static objects +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON static system objects +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al + +#ifdef CYGPKG_UITRON + +#include // types; cyg_int32, CYG_ADDRWORD + +#include + +#include + +#include // Cyg_Thread +#include // Cyg_Mbox +#include // Cyg_Flag +#include // Cyg_Counting_Semaphore2 +#include // Cyg_Mempool_Fixed +#include // Cyg_Mempool_Variable +#include // Cyg_Timer + +// ------------------------------------------------------------------------ +// Some pasting macros to create names of the config macro and the +// static data resulting: + +#define CYG_UITRON_NUM( _which_ ) (CYGNUM_UITRON_ ## _which_) +#define CYG_UITRON_OBJS( _which_ ) cyg_uitron_ ## _which_ +#define CYG_UITRON_PTRS( _which_ ) cyg_uitron_ ## _which_ ## _ptrs +// ------------------------------------------------------------------------ +// CYG_UITRON_DECL +// +// Macro to declare static uitron static objects; uses the appropriate +// config define for the number of them to have. + +#define CYG_UITRON_OBJS_INIT_PRIORITY CYG_INIT_PRIORITY( COMPAT ) + +#define CYG_UITRON_DECL( _which_ ) \ + CYG_UITRON_OBJS( _which_ ) [ CYG_UITRON_NUM( _which_ ) ] \ + CYG_UITRON_OBJS_INIT_PRIORITY + +// and the array of pointers to them for those with dynamic existence: +#define CYG_UITRON_DECL_PTRS( _which_ ) \ + CYG_UITRON_PTRS( _which_ ) [ CYG_UITRON_NUM( _which_ ) ] + + +// ------------------------------------------------------------------------ +// The external system objects themselves. + +#ifdef CYGPKG_UITRON_SEMAS +extern +Cyg_Counting_Semaphore2 CYG_UITRON_OBJS( SEMAS ) []; +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE +extern +Cyg_Counting_Semaphore2 *CYG_UITRON_PTRS( SEMAS ) []; +#endif +#endif +#ifdef CYGPKG_UITRON_MBOXES +extern +Cyg_Mbox CYG_UITRON_OBJS( MBOXES ) []; +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE +extern +Cyg_Mbox *CYG_UITRON_PTRS( MBOXES ) []; +#endif +#endif +#ifdef CYGPKG_UITRON_FLAGS +extern +Cyg_Flag CYG_UITRON_OBJS( FLAGS ) []; +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE +extern +Cyg_Flag *CYG_UITRON_PTRS( FLAGS ) []; +#endif +#endif +// there must always be tasks +extern +Cyg_Thread CYG_UITRON_OBJS( TASKS ) []; +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE +extern +Cyg_Thread *CYG_UITRON_PTRS( TASKS ) []; +#endif +// no endif +#ifdef CYGPKG_UITRON_MEMPOOLFIXED +extern +Cyg_Mempool_Fixed CYG_UITRON_OBJS( MEMPOOLFIXED ) []; +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE +extern +Cyg_Mempool_Fixed *CYG_UITRON_PTRS( MEMPOOLFIXED )[]; +#endif +#endif +#ifdef CYGPKG_UITRON_MEMPOOLVAR +extern +Cyg_Mempool_Variable CYG_UITRON_OBJS( MEMPOOLVAR ) []; +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE +extern +Cyg_Mempool_Variable *CYG_UITRON_PTRS( MEMPOOLVAR ) []; +#endif +#endif +#ifdef CYGPKG_UITRON_CYCLICS +extern +Cyg_Timer CYG_UITRON_OBJS( CYCLICS ) []; +#endif +#ifdef CYGPKG_UITRON_ALARMS +extern +Cyg_Timer CYG_UITRON_OBJS( ALARMS ) []; +#endif + +// ------------------------------------------------------------------------ +// Ancillary system objects - cleaner than extending the basic class + +#ifdef CYGIMP_THREAD_PRIORITY +// An array of priorities, for resetting back to the "created" prio when a +// task cycles though exit, dormancy, restart. +extern cyg_priority +cyg_uitron_task_initial_priorities[ CYG_UITRON_NUM( TASKS ) ]; +// and an accessor macro, for the addressing of this is naturally +// from 1..N also: +#define CYG_UITRON_TASK_INITIAL_PRIORITY( _tskid_ ) \ + (cyg_uitron_task_initial_priorities[ (_tskid_) - 1 ]) +#endif // CYGIMP_THREAD_PRIORITY + +// ------------------------------------------------------------------------ + +#endif // CYGPKG_UITRON + +#endif // CYGONCE_COMPAT_UITRON_UIT_OBJS_HXX +// EOF uit_objs.hxx diff --git a/packages/compat/uitron/v2_0/include/uit_type.h b/packages/compat/uitron/v2_0/include/uit_type.h new file mode 100644 index 00000000..f79c6a10 --- /dev/null +++ b/packages/compat/uitron/v2_0/include/uit_type.h @@ -0,0 +1,687 @@ +#ifndef CYGONCE_COMPAT_UITRON_UIT_TYPE_H +#define CYGONCE_COMPAT_UITRON_UIT_TYPE_H +//=========================================================================== +// +// uit_type.h +// +// uITRON specific data types as required by the API +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON specific data types as required by the API +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al + +#ifdef CYGPKG_UITRON + +// ------------------------------------------------------------------------ +// uITRON types +// + +// from this section of the uITRON 3.02 manual: +// *********************************************************************** +// *** 6.4 Data Types *** +// *********************************************************************** +// +// *** General-Purpose Data Types *************************************** + +typedef cyg_int8 B; // signed 8-bit integer +typedef cyg_int16 H; // signed 16-bit integer +typedef cyg_int32 W; // signed 32-bit integer +typedef cyg_uint8 UB; // unsigned 8-bit integer +typedef cyg_uint16 UH; // unsigned 16-bit integer +typedef cyg_uint32 UW; // unsigned 32-bit integer + // +typedef cyg_uint32 VW; // unpredictable data type (32-bit size) +typedef cyg_uint16 VH; // unpredictable data type (16-bit size) +typedef cyg_uint8 VB; // unpredictable data type (8-bit size) + +typedef void * VP; // pointer to an unpredictable data type + +typedef CYG_ADDRWORD FP; // program start address + +// * The difference between VB, VH and VW and B, H and W is that only the +// number of bits is known for the former, not the data type of the +// contents. The latter clearly represent integers. +// +// *** Data Types Dependent on ITRON Specification *** +// +// In order to clarify the meanings of certain parameters, the following +// names are used for data types which appear frequently and/or have +// special meanings. + +typedef cyg_int32 INT; // Signed integer (bit width of processor) +typedef cyg_uint32 UINT; // Unsigned integer (bit width of processor) +typedef cyg_int32 BOOL; // Boolean value. TRUE (1) or FALSE (0). +typedef cyg_uint16 FN; // Function code. Signed integer. Maximum 2 bytes. +typedef INT ID; // Object ID number (???id) +typedef INT BOOL_ID;// Boolean value or ID number +typedef INT HNO; // Handler number +typedef INT RNO; // Rendezvous number +typedef INT NODE; // Node Number. Usually a signed integer. +typedef UINT ATR; // Object or handler attribute. An unsigned integer. +typedef INT ER; // Error code. A signed integer. +typedef INT PRI; // Task priority. A signed integer. +typedef UB T_MSG; // Message packet data structure used for mailboxes +typedef INT TMO; // Timeout value. A signed integer. + // TMO_POL = 0 indicates polling, + // while TMO_FEVR = -1 indicates wait forever. + +typedef cyg_uint64 CYGTM; +typedef CYGTM SYSTIME;// Data types used for specifying times. +typedef CYGTM CYCTIME;// Often split into upper and lower sections. +typedef CYGTM ALMTIME;// For details, see the chapter giving system +typedef CYGTM DLYTIME;// call descriptions;. + +// *********************************************************************** +// *** 6.7 Error Codes *** +// *********************************************************************** + +enum { +//------------------------------------------------------ +//Mnemonic Value Description +//------------------------------------------------------ +E_OK = 0, // Normal completion +// - - - - - - - - // - - - - - - - - - - - - - - - - - - +E_SYS = (-5), // System error +// - - - - - - - - // - - - - - - - - - - - - - - - - - - +E_NOMEM = (-10), // Insufficient memory +// - - - - - - - - // - - - - - - - - - - - - - - - - - - +E_NOSPT = (-17), // Feature not supported +E_INOSPT = (-18), // Feature not supported by ITRON/FILE specification +E_RSFN = (-20), // Reserved function code number +E_RSATR = (-24), // Reserved attribute +// - - - - - - - - // - - - - - - - - - - - - - - - - - - +E_PAR = (-33), // Parameter error +E_ID = (-35), // Invalid ID number +// - - - - - - - - // - - - - - - - - - - - - - - - - - - +E_NOEXS = (-52), // Object does not exist +E_OBJ = (-63), // Invalid object state +// - - - - - - - - // - - - - - - - - - - - - - - - - - - +E_MACV = (-65), // Memory access disabled or memory access violation +E_OACV = (-66), // Object access violation +// - - - - - - - - // - - - - - - - - - - - - - - - - - - +E_CTX = (-69), // Context error +// - - - - - - - - // - - - - - - - - - - - - - - - - - - +E_QOVR = (-73), // Queuing or nesting overflow +// - - - - - - - - // - - - - - - - - - - - - - - - - - - +E_DLT = (-81), // Object being waited for was deleted +// - - - - - - - - // - - - - - - - - - - - - - - - - - - +E_TMOUT = (-85), // Polling failure or timeout exceeded +E_RLWAI = (-86), // WAIT state was forcibly released +// - - - - - - - - // - - - - - - - - - - - - - - - - - - - +#if 0 // CONNECTION FUNCTIONS ARE NOT SUPPORTED +EN_NOND = (-113), // Target node does not exist or cannot be accessed +EN_OBJNO = (-114), // Specifies an object number which could not be + // accessed on the target node +EN_PROTO = (-115), // Protocol not supported on target node +EN_RSFN = (-116), // System call or function not supported on target node +EN_COMM = (-117), // No response from target node +EN_RLWAI = (-118), // Connection function response wait state was forcibly + // released +EN_PAR = (-119), // A value outside the range supported by the target + // node and/or transmission packet format was specified + // as a parameter +EN_RPAR = (-120), // A value outside the range supported by the issuing + // node and/or transmission packet format was returned + // as a return parameter +EN_CTXID = (-121), // An object on another node was specified to a system + // call issued from a task in dispatch disabled state + // or from a task-independent portion +EN_EXEC = (-122), // System call could not be executed due to + // insufficient resources on the target node +EN_NOSPT = (-123), // Connection function not supported +#endif // 0 CONNECTION FUNCTIONS ARE NOT SUPPORTED +// - - - - - - - - // - - - - - - - - - - - - - - - - - - - +}; + + +// ******************************************************************* +// *** 6.6 Common Constants and Data Structure Packet Formats *** +// ******************************************************************* + +/* --- overall ----------------------- */ + +/* invalid address or pointer value */ +#define NADR ((void *)(-1)) + +enum { + TRUE = 1, /* true */ + FALSE = 0, /* false */ +}; + +/* TMO tmout: */ +enum { + TMO_POL = 0, /* polling */ + TMO_FEVR = (-1) /* wait forever */ +}; + +/* --- for task management functions ----------------------- */ + +// cre_tsk: + typedef struct t_ctsk { + VP exinf; /* extended information */ + ATR tskatr; /* task attributes */ + FP task; /* task start address */ + PRI itskpri; /* initial task priority */ + INT stksz; /* stack size */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_CTSK; + +// tskatr: +enum { + TA_ASM = 0x00, /* program written in assembly language */ + TA_HLNG = 0x01, /* program written in high-level language */ + TA_COP0 = 0x8000, /* uses coprocessor having ID = 0 */ + TA_COP1 = 0x4000, /* uses coprocessor having ID = 1 */ + TA_COP2 = 0x2000, /* uses coprocessor having ID = 2 */ + TA_COP3 = 0x1000, /* uses coprocessor having ID = 3 */ + TA_COP4 = 0x0800, /* uses coprocessor having ID = 4 */ + TA_COP5 = 0x0400, /* uses coprocessor having ID = 5 */ + TA_COP6 = 0x0200, /* uses coprocessor having ID = 6 */ + TA_COP7 = 0x0100, /* uses coprocessor having ID = 7 */ +}; + +// tskid: +enum { + TSK_SELF = 0, /* task specifies itself */ + /* FALSE = 0, */ /* indicates a task-independent portion (return + parameters only) */ +}; +// tskpri: +enum { + TPRI_INI = 0, /* specifies the initial priority on task startup + (chg_pri) */ + TPRI_RUN = 0, /* specifies the highest priority during execution + (rot_rdq) */ +}; + /* ref_tsk */ + typedef struct t_rtsk { + VP exinf; /* extended information */ + PRI tskpri; /* current priority */ + UINT tskstat; /* task state */ + /* the following are represent extended features of support + [level X] (implementation-dependent) */ +#if 0 // NOT SUPPORTED + UINT tskwait; /* cause of wait */ + ID wid; /* ID of object being waited for */ + INT wupcnt; /* wakeup request count */ + INT suscnt; /* SUSPEND request count */ + ATR tskatr; /* task attributes */ + FP task; /* task start address */ + PRI itskpri; /* initial task priority */ + INT stksz; /* stack size */ + // ... +#endif + } T_RTSK; + +// tskstat: +enum { + TTS_RUN = 0x01, /* RUN */ + TTS_RDY = 0x02, /* READY */ + TTS_WAI = 0x04, /* WAIT */ + TTS_SUS = 0x08, /* SUSPEND */ + TTS_WAS = 0x0C, /* WAIT-SUSPEND */ + TTS_DMT = 0x10, /* DORMANT */ +}; +// tskwait: +enum { + TTW_SLP = 0x0001, /* wait due to slp_tsk or tslp_tsk */ + TTW_DLY = 0x0002, /* wait due to dly_tsk */ + TTW_NOD = 0x0008, /* connection function response wait */ + TTW_FLG = 0x0010, /* wait due to wai_flg or twai_flg */ + TTW_SEM = 0x0020, /* wait due to wai_sem or twai_sem */ + TTW_MBX = 0x0040, /* wait due to rcv_msg or trcv_msg */ + TTW_SMBF = 0x0080, /* wait due to snd_mbf or tsnd_mbf */ + TTW_MBF = 0x0100, /* wait due to rcv_mbf or trcv_mbf */ + TTW_CAL = 0x0200, /* wait for rendezvous call */ + TTW_ACP = 0x0400, /* wait for rendezvous accept */ + TTW_RDV = 0x0800, /* wait for rendezvous completion */ + TTW_MPL = 0x1000, /* wait due to get_blk or tget_blk */ + TTW_MPF = 0x2000, /* wait due to get_blf or tget_blf */ +}; + /* Since the task states given by tskstat and tskwait are expressed + by bit correspondences, they are convenient when looking for OR + conditions (such as whether a task is in WAIT or READY state). + */ + +/* --- for semaphore functions ----------------------- */ + + /* cre_sem */ + typedef struct t_csem { + VP exinf; /* extended information */ + ATR sematr; /* semaphore attributes */ + /* Following is the extended function for [level X]. */ + INT isemcnt; /* initial semaphore count */ + /* INT maxsem; NOT SUPPORTED maximum semaphore count */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_CSEM; + + /* ref_sem */ + typedef struct t_rsem { + VP exinf; /* extended information */ + BOOL_ID wtsk; /* indicates whether or not there is a + waiting task */ + INT semcnt; /* current semaphore count */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_RSEM; + +/* --- for eventflag functions ----------------------- */ + + /* cre_flg */ + typedef struct t_cflg { + VP exinf; /* extended information */ + ATR flgatr; /* eventflag attribute */ + UINT iflgptn; /* initial eventflag */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_CFLG; + +// flgatr: +enum { + TA_WSGL = 0x00, /* multiple tasks are not allowed to wait (Wait + Single Task) */ + TA_WMUL = 0x08, /* multiple tasks are allowed to wait (Wait + Multiple Task) */ +}; +// wfmode: +enum { + TWF_ANDW = 0x00, /* AND wait */ + TWF_ORW = 0x02, /* OR wait */ + TWF_CLR = 0x01, /* clear specification */ +}; + /* ref_flg */ + typedef struct t_rflg { + VP exinf; /* extended information */ + BOOL_ID wtsk; /* indicates whether or not there is a + waiting task */ + UINT flgptn; /* eventflag bit pattern */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_RFLG; + +/* --- for mailbox functions ----------------------- */ + + /* cre_mbx */ + typedef struct t_cmbx { + VP exinf; /* extended information */ + ATR mbxatr; /* mailbox attributes */ + /* Following is implementation-dependent function */ + /* INT bufcnt; NOT SUPPORTED ring buffer size IS FIXED */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_CMBX; + +// mbxatr: +enum { + TA_TFIFO = 0x00, /* waiting tasks are handled by FIFO */ + TA_TPRI = 0x01, /* waiting tasks are handled by priority */ + TA_MFIFO = 0x00, /* messages are handled by FIFO */ + TA_MPRI = 0x02, /* messages are handled by priority */ +}; + + /* ref_mbx */ + typedef struct t_rmbx { + VP exinf; /* extended information */ + BOOL_ID wtsk; /* indicates whether or not there is a + waiting task */ + T_MSG* pk_msg; /* message to be sent next */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_RMBX; + +/* --- for messagebuffer functions ----------------------- */ + +#if 0 // NOT SUPPORTED + /* cre_mbf */ + typedef struct t_cmbf { + VP exinf; /* extended information */ + ATR mbfatr; /* messagebuffer attributes */ + INT bufsz; /* messagebuffer size */ + INT maxmsz; /* maximum size of messages */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_CMBF; + +// mbfatr: +// mbfid: +enum { + TMBF_OS = (-4), /* messagebuffer used for OS error log */ + TMBF_DB = (-3), /* messagebuffer used for debugging */ +}; + /* ref_mbf */ + typedef struct t_rmbf { + VP exinf; /* extended information */ + BOOL_ID wtsk; /* indicates whether or not there is a + task waiting to receive a message */ + BOOL_ID stsk; /* indicates whether or not there is a + task waiting to send a message */ + INT msgsz; /* size of message to be sent next */ + INT frbufsz; /* size of free buffer */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_RMBF; + +#endif +/* --- for port or rendezvous functions ----------------------- */ + +#if 0 // NOT SUPPORTED + + /* cre_por */ + typedef struct t_cpor { + VP exinf; /* extended information */ + ATR poratr; /* port attributes */ + INT maxcmsz; /* maximum call message size */ + INT maxrmsz; /* maximum reply message size */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_CPOR; + +// poratr: +enum { + TA_NULL = 0, /* specifies no particular attributes */ + /* TA_NULL should be used in place of zeroes to turn off all + attribute features. */ +}; + /* ref_por */ + typedef struct t_rpor { + VP exinf; /* extended information */ + BOOL_ID wtsk; /* indicates whether or not there is a task + waiting to call a rendezvous */ + BOOL_ID atsk; /* indicates whether or not there is a task + waiting to accept a rendezvous */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_RPOR; +#endif + +/* --- for interrupt management functions ----------------------- */ + +#if 0 // NOT SUPPORTED + /* def_int */ + typedef struct t_dint { + ATR intatr; /* interrupt handler attributes */ + FP inthdr; /* interrupt handler address */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_DINT; +#endif + +/* --- for memorypool management functions ----------------------- */ + + /* cre_mpl */ + typedef struct t_cmpl { + VP exinf; /* extended information */ + ATR mplatr; /* memorypool attributes */ + INT mplsz; /* memorypool size */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_CMPL; + +// mplatr: +// mplid: +enum { + TMPL_OS = (-4) /* memorypool used by OS */ +}; + /* ref_mpl */ + typedef struct t_rmpl { + VP exinf; /* extended information */ + BOOL_ID wtsk; /* indicates whether or not there are + waiting tasks */ + INT frsz; /* total size of free memory */ + INT maxsz; /* size of largest contiguous memory */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_RMPL; + + /* cre_mpf */ + typedef struct t_cmpf { + VP exinf; /* extended information */ + ATR mpfatr; /* memorypool attributes */ + INT mpfcnt; /* block count for entire memorypool */ + INT blfsz; /* fixed-size memory block size */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_CMPF; + +// mpfatr: + /* ref_mpf */ + typedef struct t_rmpf { + VP exinf; /* extended information */ + BOOL_ID wtsk; /* indicates whether or not there are + waiting tasks */ + INT frbcnt; /* free block count */ + /* additional information may be included depending on the + implementation */ + INT numbcnt; /* total number of blocks */ + INT bsize; /* block size */ + + } T_RMPF; + +/* --- for time management functions ----------------------- */ + +#if 0 // native definition is at head of this file + /* example for 32-bit CPUs */ + typedef struct t_systime { + H utime; /* upper 16 bits */ + UW ltime; /* lower 32 bits */ + } SYSTIME, CYCTIME, ALMTIME; + + /* example for 16-bit CPUs */ + typedef struct t_systime { + H utime; /* upper 16 bits */ + UH mtime; /* middle 16 bits */ + UH ltime; /* lower 16 bits */ + } SYSTIME, CYCTIME, ALMTIME; +#endif + /* Member configuration depends on the bit width of the processor and + on the implementation. A total of 48 bits is recommended. */ + + /* def_cyc */ + typedef struct t_dcyc { + VP exinf; /* extended information */ + ATR cycatr; /* cyclic handler attributes */ + FP cychdr; /* cyclic handler address */ + UINT cycact; /* cyclic handler activation */ + CYCTIME cyctim; /* cyclic startup period */ + } T_DCYC; + +// cycact: +enum { + TCY_OFF = 0x00, /* do not invoke cyclic handler */ + TCY_ON = 0x01, /* invoke cyclic handler */ + TCY_INT = 0x02, /* initialize cycle count */ + /* Following changed from TCY_INT to TCY_INI to match + description in the body of the standard. I assume TCY_INT + is a hypercorrection/typo; keep both */ + TCY_INI = 0x02, /* initialize cycle count */ +}; + /* ref_cyc */ + typedef struct t_rcyc { + VP exinf; /* extended information */ + CYCTIME lfttim; /* time left before next handler startup */ + UINT cycact; /* cyclic handler activation */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_RCYC; + + /* def_alm */ + typedef struct t_dalm { + VP exinf; /* extended information */ + ATR almatr; /* alarm handler attributes */ + FP almhdr; /* alarm handler address */ + UINT tmmode; /* start time specification mode */ + ALMTIME almtim; /* handler startup time */ + } T_DALM; + +// tmmode: +enum { + TTM_ABS = 0x00, /* specified as an absolute time */ + TTM_REL = 0x01, /* specified as a relative time */ +}; + /* ref_alm */ + typedef struct t_ralm { + VP exinf; /* extended information */ + ALMTIME lfttim; /* time left before next handler startup */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_RALM; + +/* --- for system management functions ----------------------- */ + + /* get_ver */ + typedef struct t_ver { + UH maker; /* vendor */ + UH id; /* format number */ + UH spver; /* specification version */ + UH prver; /* product version */ + UH prno[4]; /* product control information */ + UH cpu; /* CPU information */ + UH var; /* variation descriptor */ + } T_VER; + + /* ref_sys */ + typedef struct t_rsys { + INT sysstat; /* system state */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_RSYS; + +// sysstat: +enum { + TSS_TSK = 0, /* normal state in which dispatching is enabled during + task portion execution */ + TSS_DDSP = 1, /* state after dis_dsp has been executed during task + portion execution (dispatch disabled) */ + TSS_LOC = 3, /* state after loc_cpu has been executed during task + portion execution (interrupt and dispatch disabled) + */ + TSS_INDP = 4, /* state during execution of task-independent portions + (interrupt and timer handlers) */ +}; + /* ref_cfg */ + typedef struct t_rcfg { + /* details concerning members are implementation dependent */ + } T_RCFG; + +#if 0 // NOT SUPPORTED + /* def_svc */ + typedef struct t_dsvc { + ATR svcatr; /* extended SVC handler attributes */ + FP svchdr; /* extended SVC handler address */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_DSVC; + + /* def_exc */ + typedef struct t_dexc { + ATR excatr; /* exception handler attributes */ + FP exchdr; /* exception handler address */ + // ... + /* additional information may be included depending on the + implementation */ + // ... + } T_DEXC; +#endif + +/* --- for network management functions ----------------------- */ + +#if 0 // NOT SUPPORTED +// NODE srcnode, dstnode, node: +enum { + TND_SELF = 0, /* specifies the local node */ + TND_OTHR = (-1) /* specifies default remote node */ +}; +#endif +/* ------------------------------------------------------ */ + + + +#endif // CYGPKG_UITRON + +#endif // CYGONCE_COMPAT_UITRON_UIT_TYPE_H +// EOF uit_type.h diff --git a/packages/compat/uitron/v2_0/src/uit_func.cxx b/packages/compat/uitron/v2_0/src/uit_func.cxx new file mode 100644 index 00000000..9c4e9be4 --- /dev/null +++ b/packages/compat/uitron/v2_0/src/uit_func.cxx @@ -0,0 +1,192 @@ +//=========================================================================== +// +// uit_func.cxx +// +// uITRON compatibility functions +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON compatibility functions +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al + +#ifdef CYGPKG_UITRON + +// invoke the inline function definition to create static C linkage +// functions here: +#define CYGPRI_UITRON_FUNCS_HERE_AND_NOW +#include + +cyg_uint32 cyg_uitron_dis_dsp_old_priority = 0; + +// ------------------------------------------------------------------------ +// STARTUP +// this routine is outside the uITRON specification; call it from +// cyg_start(), cyg_package_start(), cyg_prestart() or cyg_user_start() +// to start the uITRON tasks and scheduler. + +#if CYGNUM_UITRON_START_TASKS < 0 +#error CYGNUM_UITRON_START_TASKS should be >= 0 +#endif + +#if CYGNUM_UITRON_START_TASKS == 0 +#define START_TASKS CYGNUM_UITRON_TASKS +#else +#define START_TASKS CYGNUM_UITRON_START_TASKS +#endif + +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE +#if START_TASKS > CYGNUM_UITRON_TASKS_INITIALLY +#undef START_TASKS +#define START_TASKS CYGNUM_UITRON_TASKS_INITIALLY +#endif +#endif + +#if START_TASKS > CYGNUM_UITRON_TASKS +#undef START_TASKS +#define START_TASKS CYGNUM_UITRON_TASKS +#endif + +#if START_TASKS <= 0 +#error Number of uITRON tasks to start initially must be >= 0 +#endif + + +#define SET_UP_PTRS( _which_ ) CYG_MACRO_START \ + for ( i = 0; \ + (i < CYGNUM_UITRON_ ## _which_ ## _INITIALLY) && \ + (i < CYGNUM_UITRON_ ## _which_ ) ; \ + i++ ) { \ + CYG_UITRON_PTRS( _which_ )[ i ] = CYG_UITRON_OBJS( _which_ ) + i; \ + } \ + if ( (CYGNUM_UITRON_ ## _which_ ## _INITIALLY) \ + < (CYGNUM_UITRON_ ## _which_) ) \ + for ( /* i as is */; i < CYGNUM_UITRON_ ## _which_ ; i++ ) { \ + CYG_UITRON_PTRS( _which_ )[ i ] = NULL; \ + } \ +CYG_MACRO_END + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK +#ifdef CYGSEM_UITRON_TIME_IS_MILLISECONDS +Cyg_Clock::converter uit_clock_to_system; +Cyg_Clock::converter uit_clock_from_system; +#endif +#endif + +void cyg_uitron_start( void ) +{ + cyg_int32 i; + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK +#ifdef CYGSEM_UITRON_TIME_IS_MILLISECONDS + // initialize the clock converters + Cyg_Clock::real_time_clock-> + get_other_to_clock_converter( 1000000, &uit_clock_to_system ); + Cyg_Clock::real_time_clock-> + get_clock_to_other_converter( 1000000, &uit_clock_from_system ); +#endif +#endif + + for ( i = 0; i < START_TASKS; i++ ) { +#ifdef CYGIMP_THREAD_PRIORITY + // save the initial priority in our private array + cyg_uitron_task_initial_priorities[ i ] = + cyg_uitron_TASKS[ i ].get_priority(); +#endif + // and awaken the task: + cyg_uitron_TASKS[ i ].resume(); + } + for ( /* i as is */; i < CYGNUM_UITRON_TASKS; i++ ) { +#ifdef CYGIMP_THREAD_PRIORITY + // save the initial priority in our private array + cyg_uitron_task_initial_priorities[ i ] = + cyg_uitron_TASKS[ i ].get_priority(); +#endif + // but ensure the task state is dormant. + cyg_uitron_TASKS[ i ].kill(); + } + +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE + SET_UP_PTRS( TASKS ); +#endif +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + SET_UP_PTRS( SEMAS ); +#endif +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE + SET_UP_PTRS( MBOXES ); +#endif +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + SET_UP_PTRS( FLAGS ); +#endif +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + SET_UP_PTRS( MEMPOOLFIXED ); +#endif +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + SET_UP_PTRS( MEMPOOLVAR ); +#endif +} + +// These allow programs to link when cyg_uitron_start() is called +// (often because of CYGSEM_START_UITRON_COMPATIBILITY from infra, +// though we define these regardless just in case) +// even when there is no interest in uITRON and so the tasks are +// not externally defined; the reference to cyg_uitron_start() +// ensures the tasks array et al are still included... +extern "C" { + void task1( unsigned int arg ) CYGBLD_ATTRIB_WEAK; + void task2( unsigned int arg ) CYGBLD_ATTRIB_WEAK; + void task3( unsigned int arg ) CYGBLD_ATTRIB_WEAK; + void task4( unsigned int arg ) CYGBLD_ATTRIB_WEAK; +} + +void task1( unsigned int arg ) {} +void task2( unsigned int arg ) {} +void task3( unsigned int arg ) {} +void task4( unsigned int arg ) {} + +#endif // CYGPKG_UITRON + +// EOF uit_func.cxx diff --git a/packages/compat/uitron/v2_0/src/uit_ifnc.cxx b/packages/compat/uitron/v2_0/src/uit_ifnc.cxx new file mode 100644 index 00000000..ca5caeed --- /dev/null +++ b/packages/compat/uitron/v2_0/src/uit_ifnc.cxx @@ -0,0 +1,140 @@ +//=========================================================================== +// +// uit_ifnc.cxx +// +// uITRON compatibility functions +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON compatibility functions for use in ISRs +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al + +#ifdef CYGPKG_UITRON + +// invoke the inline function definition to create static C linkage +// functions here: +#define CYGIMP_UITRON_INLINE_FUNCS 1 +#include + +// Now ensure that we create *outline* funcs for the ixxx_yyy() functions +// here, with C names or whatever, as required. + +#undef CYGPRI_UITRON_FUNCS_HERE_AND_NOW +#undef CYGIMP_UITRON_INLINE_FUNCS +#undef CYG_UIT_FUNC_EXTERN_BEGIN +#undef CYG_UIT_FUNC_EXTERN_END + +#ifdef CYGIMP_UITRON_CPP_OUTLINE_FUNCS +#define CYG_UIT_FUNC_EXTERN_BEGIN extern "C++" { +#define CYG_UIT_FUNC_EXTERN_END } +#else +#define CYG_UIT_FUNC_EXTERN_BEGIN extern "C" { +#define CYG_UIT_FUNC_EXTERN_END } +#endif + +// Get extern C prototypes (or whatever uit_func.h above did) +#include + +#undef CYG_UIT_FUNC_INLINE +#define CYG_UIT_FUNC_INLINE /* blank */ +#define CYGPRI_UITRON_FUNCS_HERE_AND_NOW +#include + +volatile int cyg_uit_dsr_actions_head = 0; +volatile int cyg_uit_dsr_actions_tail = 0; + +Cyg_Uit_Action::action +cyg_uit_dsr_actions[ CYGNUM_UITRON_ISR_ACTION_QUEUESIZE ]; + +ID +cyg_uit_dsr_act_ids[ CYGNUM_UITRON_ISR_ACTION_QUEUESIZE ]; + +CYG_ADDRWORD +cyg_uit_dsr_act_a1s[ CYGNUM_UITRON_ISR_ACTION_QUEUESIZE ]; + +void +cyg_uitron_dsr( unsigned int vector, unsigned int count, unsigned int data ) +{ + while ( cyg_uit_dsr_actions_tail != cyg_uit_dsr_actions_head ) { + switch ( cyg_uit_dsr_actions[ cyg_uit_dsr_actions_tail ] ) { + case Cyg_Uit_Action::WUP_TSK: + (void)wup_tsk( cyg_uit_dsr_act_ids[ cyg_uit_dsr_actions_tail ] ); + break; +#ifdef CYGPKG_UITRON_SEMAS +#if 0 < CYG_UITRON_NUM( SEMAS ) + case Cyg_Uit_Action::SIG_SEM: + (void)sig_sem( cyg_uit_dsr_act_ids[ cyg_uit_dsr_actions_tail ] ); + break; +#endif // 0 < CYG_UITRON_NUM( SEMAS ) +#endif // CYGPKG_UITRON_SEMAS +#ifdef CYGPKG_UITRON_FLAGS +#if 0 < CYG_UITRON_NUM( FLAGS ) + case Cyg_Uit_Action::SET_FLG: + (void)set_flg( cyg_uit_dsr_act_ids[ cyg_uit_dsr_actions_tail ], + (UINT)cyg_uit_dsr_act_a1s[ cyg_uit_dsr_actions_tail ] ); + break; +#endif // 0 < CYG_UITRON_NUM( FLAGS ) +#endif // CYGPKG_UITRON_FLAGS +#ifdef CYGPKG_UITRON_MBOXES +#if 0 < CYG_UITRON_NUM( MBOXES ) + case Cyg_Uit_Action::SND_MSG: + (void)snd_msg( cyg_uit_dsr_act_ids[ cyg_uit_dsr_actions_tail ], + (T_MSG *)cyg_uit_dsr_act_a1s[ cyg_uit_dsr_actions_tail ] ); + break; +#endif // 0 < CYG_UITRON_NUM( MBOXES ) +#endif // CYGPKG_UITRON_MBOXES + default: + CYG_FAIL( "enum Cyg_Uit_Action out of range!" ); + } + cyg_uit_dsr_actions_tail = + CYGNUM_UITRON_ISR_ACTION_QUEUEMASK & (1+cyg_uit_dsr_actions_tail); + } +} + +#endif // CYGPKG_UITRON + +// EOF uit_ifnc.cxx diff --git a/packages/compat/uitron/v2_0/src/uit_objs.cxx b/packages/compat/uitron/v2_0/src/uit_objs.cxx new file mode 100644 index 00000000..3d49012e --- /dev/null +++ b/packages/compat/uitron/v2_0/src/uit_objs.cxx @@ -0,0 +1,382 @@ +//=========================================================================== +// +// uit_objs.cxx +// +// uITRON static objects +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON static system objects +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al + +#ifdef CYGPKG_UITRON + +#include + // declarations of the objects + // we define below, and everything + // we need to specify them. + +#include // for CYGNUM_HAL_STACK_SIZE_MINIMUM + +// ------------------------------------------------------------------------ +// Mboxes have no initializer. +#ifdef CYGPKG_UITRON_MBOXES +#if 0 < CYGNUM_UITRON_MBOXES +Cyg_Mbox CYG_UITRON_DECL( MBOXES ); +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE +Cyg_Mbox *CYG_UITRON_DECL_PTRS( MBOXES ); +#endif +#endif +#endif // CYGPKG_UITRON_MBOXES + +// ------------------------------------------------------------------------ +// Flags have no initializer. +#ifdef CYGPKG_UITRON_FLAGS +#if 0 < CYGNUM_UITRON_FLAGS +Cyg_Flag CYG_UITRON_DECL( FLAGS ); +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE +Cyg_Flag *CYG_UITRON_DECL_PTRS( FLAGS ); +#endif +#endif +#endif // CYGPKG_UITRON_FLAGS + +// ------------------------------------------------------------------------ +// Semaphores have an optional initializer. +#ifdef CYGPKG_UITRON_SEMAS +#if (0 < CYGNUM_UITRON_SEMAS) || \ + defined( CYGDAT_UITRON_SEMA_INITIALIZERS ) + +#ifndef CYGNUM_UITRON_SEMAS +#error You must define CYGNUM_UITRON_SEMAS +#endif + +Cyg_Counting_Semaphore2 CYG_UITRON_DECL( SEMAS ) + +#ifdef CYGDAT_UITRON_SEMA_INITIALIZERS +// a Macro to ease the construction: +#define CYG_UIT_SEMA( _count_ ) Cyg_Counting_Semaphore2( (cyg_count32)(_count_) ) +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE +#define CYG_UIT_SEMA_NOEXS Cyg_Counting_Semaphore2( (cyg_count32) 0 ) +#endif + = { + CYGDAT_UITRON_SEMA_INITIALIZERS +} +#undef CYG_UIT_SEMA +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE +#undef CYG_UIT_SEMA_NOEXS +#endif +#endif // do we have initializers? +; // the end of the declaration, with or without initializer + +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE +Cyg_Counting_Semaphore2 *CYG_UITRON_DECL_PTRS( SEMAS ); +#endif +#endif +#endif // CYGPKG_UITRON_SEMAS + +// ------------------------------------------------------------------------ +// tasks MUST be initialized, you must have some. +#ifndef CYGDAT_UITRON_TASK_EXTERNS +#error You must define CYGDAT_UITRON_TASK_EXTERNS +#endif +#ifndef CYGDAT_UITRON_TASK_INITIALIZERS +#error You must define CYGDAT_UITRON_TASK_INITIALIZERS +#endif +#ifndef CYGNUM_UITRON_TASKS +#error You must define CYGNUM_UITRON_TASKS +#endif + +// a Macro to ease the construction: +// "name", priority, proc, stackbase, stacksize +#define CYG_UIT_TASK( _name_, _prio_, _func_, _sb_, _ss_ ) \ + Cyg_Thread( \ + (CYG_ADDRWORD)(_prio_), \ + (_func_), \ + (CYG_ADDRWORD)0, \ + _name_, \ + (CYG_ADDRESS)(_sb_), \ + (cyg_ucount32)(_ss_) ) + +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE +#define CYG_UIT_TASK_NOEXS( _name_, _sb_, _ss_ ) \ + Cyg_Thread( \ + (CYG_ADDRWORD)(CYG_SCHED_DEFAULT_INFO), \ + (cyg_thread_entry *)(0), \ + (CYG_ADDRWORD)0, \ + _name_, \ + (CYG_ADDRESS)(_sb_), \ + (cyg_ucount32)(_ss_) ) +#endif + +// FIXME: Xscale tools currently in use have a preprocessor bug causing +// the below #ifs to be misinterpreted. Therefore a *temporary* +// workaround is included to define a MAX macro, and change +// CYGDAT_UITRON_TASK_EXTERNS and CYGDAT_UITRON_TASK_INITIALISERS in +// the CDL to use it. +#ifdef XSCALECPPFIXEDSOMETIME + +#ifdef CYGNUM_HAL_STACK_SIZE_MINIMUM +# ifdef CYGNUM_UITRON_STACK_SIZE +# if CYGNUM_UITRON_STACK_SIZE < CYGNUM_HAL_STACK_SIZE_MINIMUM + +// then override the configured stack size +# undef CYGNUM_UITRON_STACK_SIZE +# define CYGNUM_UITRON_STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM + +# endif // CYGNUM_UITRON_STACK_SIZE < CYGNUM_HAL_STACK_SIZE_MINIMUM +# endif // CYGNUM_UITRON_STACK_SIZE +#endif // CYGNUM_HAL_STACK_SIZE_MINIMUM + +#else +#define MAX(_x_,_y_) ((_x_) > (_y_) ? (_x_) : (_y_)) +#endif + +// declare the symbols used in the initializer +CYGDAT_UITRON_TASK_EXTERNS + +Cyg_Thread CYG_UITRON_DECL( TASKS ) = +{ + CYGDAT_UITRON_TASK_INITIALIZERS +}; + +#undef CYG_UIT_TASK +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE +#undef CYG_UIT_TASK_NOEXS +#endif + +#ifdef CYGIMP_THREAD_PRIORITY +// An ancillary array of priorities, for managing the "original" prio +cyg_priority +cyg_uitron_task_initial_priorities[ CYG_UITRON_NUM( TASKS ) ]; +#endif + +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE +Cyg_Thread *CYG_UITRON_DECL_PTRS( TASKS ); +#endif + +// ------------------------------------------------------------------------ +// fixed memory pools MUST be initialized, IF you have some. +#ifdef CYGPKG_UITRON_MEMPOOLFIXED +#if (0 < CYGNUM_UITRON_MEMPOOLFIXED) || \ + defined (CYGDAT_UITRON_MEMPOOLFIXED_INITIALIZERS) || \ + defined (CYGDAT_UITRON_MEMPOOLFIXED_EXTERNS) + +#ifndef CYGDAT_UITRON_MEMPOOLFIXED_EXTERNS +#error You must define CYGDAT_UITRON_MEMPOOLFIXED_EXTERNS +#endif +#ifndef CYGDAT_UITRON_MEMPOOLFIXED_INITIALIZERS +#error You must define CYGDAT_UITRON_MEMPOOLFIXED_INITIALIZERS +#endif +#ifndef CYGNUM_UITRON_MEMPOOLFIXED +#error You must define CYGNUM_UITRON_MEMPOOLFIXED +#endif + +// declare the symbols used in the initializer +CYGDAT_UITRON_MEMPOOLFIXED_EXTERNS + +// a Macro to ease the construction: addr, size, blocksize +#define CYG_UIT_MEMPOOLFIXED( _a_, _s_, _bs_ ) Cyg_Mempool_Fixed( \ + (cyg_uint8 *)(_a_), (cyg_int32)(_s_), (CYG_ADDRWORD)(_bs_) ) +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE +// note that this just picks a suitable size for the initialization, which +// should not be too inefficient +#define CYG_UIT_MEMPOOLFIXED_NOEXS( _a_, _s_ ) Cyg_Mempool_Fixed( \ + (cyg_uint8 *)(_a_), (cyg_int32)(_s_), (CYG_ADDRWORD) ((~7)&((_s_)/2)) ) +#endif + +Cyg_Mempool_Fixed CYG_UITRON_DECL( MEMPOOLFIXED ) = +{ + CYGDAT_UITRON_MEMPOOLFIXED_INITIALIZERS +}; +#undef CYG_UIT_MEMPOOLFIXED +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE +#undef CYG_UIT_MEMPOOLFIXED_NOEXS +#endif + +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE +Cyg_Mempool_Fixed *CYG_UITRON_DECL_PTRS( MEMPOOLFIXED ); +#endif +#endif // do we have fixed memory pools at all? +#endif // CYGPKG_UITRON_MEMPOOLFIXED + +// ------------------------------------------------------------------------ +// variable memory pools MUST be initialized, IF you have some. +#ifdef CYGPKG_UITRON_MEMPOOLVAR +#if (0 < CYGNUM_UITRON_MEMPOOLVAR) || \ + defined (CYGDAT_UITRON_MEMPOOLVAR_INITIALIZERS) || \ + defined (CYGDAT_UITRON_MEMPOOLVAR_EXTERNS) + +#ifndef CYGDAT_UITRON_MEMPOOLVAR_EXTERNS +#error You must define CYGDAT_UITRON_MEMPOOLVAR_EXTERNS +#endif +#ifndef CYGDAT_UITRON_MEMPOOLVAR_INITIALIZERS +#error You must define CYGDAT_UITRON_MEMPOOLVAR_INITIALIZERS +#endif +#ifndef CYGNUM_UITRON_MEMPOOLVAR +#error You must define CYGNUM_UITRON_MEMPOOLVAR +#endif + +// declare the symbols used in the initializer +CYGDAT_UITRON_MEMPOOLVAR_EXTERNS + +// a Macro to ease the construction: addr, size +#define CYG_UIT_MEMPOOLVAR( _a_, _s_ ) Cyg_Mempool_Variable( \ + (cyg_uint8 *)(_a_),(cyg_int32)(_s_)) +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE +#define CYG_UIT_MEMPOOLVAR_NOEXS( _a_, _s_ ) Cyg_Mempool_Variable( \ + (cyg_uint8 *)(_a_),(cyg_int32)(_s_)) +#endif + +Cyg_Mempool_Variable CYG_UITRON_DECL( MEMPOOLVAR ) = +{ + CYGDAT_UITRON_MEMPOOLVAR_INITIALIZERS +}; +#undef CYG_UIT_MEMPOOLVAR +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE +#undef CYG_UIT_MEMPOOLVAR_NOEXS +#endif + +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE +Cyg_Mempool_Variable *CYG_UITRON_DECL_PTRS( MEMPOOLVAR ); +#endif +#endif // do we have variable memory pools at all? +#endif // CYGPKG_UITRON_MEMPOOLVAR + +// ------------------------------------------------------------------------ +// Cyclic alarm handlers might be initialized, if you have some. +// +#ifdef CYGPKG_UITRON_CYCLICS +#if (0 < CYGNUM_UITRON_CYCLICS) || \ + defined( CYGDAT_UITRON_CYCLIC_EXTERNS ) || \ + defined( CYGDAT_UITRON_CYCLIC_INITIALIZERS ) + +#ifndef CYGNUM_UITRON_CYCLICS +#error You must define CYGNUM_UITRON_CYCLICS +#endif + +#if defined( CYGDAT_UITRON_CYCLIC_INITIALIZERS ) || \ + defined( CYGDAT_UITRON_CYCLIC_EXTERNS ) + +#ifndef CYGDAT_UITRON_CYCLIC_INITIALIZERS +#error You must define CYGDAT_UITRON_CYCLIC_INITIALIZERS +#endif +#ifndef CYGDAT_UITRON_CYCLIC_EXTERNS +#error You must define CYGDAT_UITRON_CYCLIC_EXTERNS +#endif + +// declare the symbols used in the initializer +CYGDAT_UITRON_CYCLIC_EXTERNS + +#endif // have externs or initializers + +Cyg_Timer CYG_UITRON_DECL( CYCLICS ) + +#ifdef CYGDAT_UITRON_CYCLIC_INITIALIZERS + +#error *** CYCLIC INITIALIZERS ARE NOT SUPPORTED IN THIS RELEASE*** + +// a Macro to ease the construction: proc, arg, time +#define CYG_UIT_CYCLIC( ... ) Cyg_Timer() + = { + CYGDAT_UITRON_CYCLIC_INITIALIZERS +} +#undef CYG_UIT_CYCLIC +#endif // do we have initializers? +; // the end of the declaration, with or without initializer + +#endif // do we have cyclic alarms at all? +#endif // CYGPKG_UITRON_CYCLICS + +// ------------------------------------------------------------------------ +// Oneshot alarm handlers might be initialized, if you have some. +// +#ifdef CYGPKG_UITRON_ALARMS +#if (0 < CYGNUM_UITRON_ALARMS) || \ + defined( CYGDAT_UITRON_ALARM_EXTERNS ) || \ + defined( CYGDAT_UITRON_ALARM_INITIALIZERS ) + +#ifndef CYGNUM_UITRON_ALARMS +#error You must define CYGNUM_UITRON_ALARMS +#endif + +#if defined( CYGDAT_UITRON_ALARM_INITIALIZERS ) || \ + defined( CYGDAT_UITRON_ALARM_EXTERNS ) + +#ifndef CYGDAT_UITRON_ALARM_INITIALIZERS +#error You must define CYGDAT_UITRON_ALARM_INITIALIZERS +#endif +#ifndef CYGDAT_UITRON_ALARM_EXTERNS +#error You must define CYGDAT_UITRON_ALARM_EXTERNS +#endif + +// declare the symbols used in the initializer +CYGDAT_UITRON_ALARM_EXTERNS + +#endif // have externs or initializers + +Cyg_Timer CYG_UITRON_DECL( ALARMS ) + +#ifdef CYGDAT_UITRON_ALARM_INITIALIZERS + +#error *** ALARM INITIALIZERS ARE NOT SUPPORTED IN THIS RELEASE*** + +// a Macro to ease the construction: proc, arg, time +#define CYG_UIT_ALARM( ... ) Cyg_Timer() + = { + CYGDAT_UITRON_ALARM_INITIALIZERS +} +#undef CYG_UIT_ALARM +#endif // do we have initializers? +; // the end of the declaration, with or without initializer + +#endif // do we have oneshot alarms at all? +#endif // CYGPKG_UITRON_ALARMS + +// ------------------------------------------------------------------------ +#endif // CYGPKG_UITRON + +// EOF uit_objs.cxx diff --git a/packages/compat/uitron/v2_0/tests/test1.c b/packages/compat/uitron/v2_0/tests/test1.c new file mode 100644 index 00000000..bf1228a7 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/test1.c @@ -0,0 +1,815 @@ +//=========================================================================== +// +// test1.c +// +// uITRON "C" test program one +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +volatile int intercom = 0; +volatile int intercount = 0; +INT scratch = 0; + +#ifndef CYGSEM_KERNEL_SCHED_TIMESLICE +#define TIMESLICEMSG "Assuming no kernel timeslicing" +#define TSGO() (1) +#define TSRELEASE() CYG_EMPTY_STATEMENT +#define TSSTOP() CYG_EMPTY_STATEMENT +#define TSLOCK() CYG_EMPTY_STATEMENT +#define TSUNLOCK() CYG_EMPTY_STATEMENT +#define ICWAIT( _i_ ) CYG_EMPTY_STATEMENT + +#else +// Now follow some nasty bodges to control the scheduling when basically it +// isn't controlled ie. timeslicing is on. It's bodgy because we're +// testing normal synchronization methods, so we shouldn't rely on them for +// comms between threads here. Instead there's a mixture of communicating +// via a flag (ts_interlock) which stops the "controlled" thread running +// away, and waiting for the controlled thread to run enough for us. +// +// Tasks 3 and 4 are waited for by the control task: task 3 locks the +// scheduler so is immediately descheduled when it unlocks it, task 4 does +// waiting-type operations, so we must give it chance to run by yielding a +// few times ourselves. Note the plain constant in ICWAIT() below. + +#define TIMESLICEMSG "Assuming kernel timeslicing ENABLED" +volatile int ts_interlock = 0; +#define TSGO() (ts_interlock) +#define TSRELEASE() ts_interlock = 1 +#define TSSTOP() ts_interlock = 0 + +#define TSLOCK() CYG_MACRO_START \ + ER ercd2 = dis_dsp(); \ + CYG_TEST_CHECK( E_OK == ercd2, "dis_dsp (TSLOCK) bad ercd2" ); \ +CYG_MACRO_END + +#define TSUNLOCK() CYG_MACRO_START \ + ER ercd3 = ena_dsp(); \ + CYG_TEST_CHECK( E_OK == ercd3, "ena_dsp (TSUNLOCK) bad ercd3" ); \ +CYG_MACRO_END + +#define ICWAIT( _i_ ) CYG_MACRO_START \ + int loops; \ + for ( loops = 3; (0 < loops) || ((_i_) > intercount); loops-- ) { \ + ER ercd4 = rot_rdq( 0 ); /* yield */ \ + CYG_TEST_CHECK( E_OK == ercd4, "rot_rdq (ICWAIT) bad ercd4" ); \ + } \ +CYG_MACRO_END +#endif // CYGSEM_KERNEL_SCHED_TIMESLICE + +/* +#define IC() \ +CYG_MACRO_START \ + static char *msgs[] = { "ZERO", "ONE", "TWO", "THREE", "FOUR", "LOTS" }; \ + CYG_TEST_INFO( msgs[ intercount > 5 ? 5 : intercount ] ); \ +CYG_MACRO_END +*/ + +// #define CYG_TEST_UITRON_TEST1_LOOPING 1 + +void task1( unsigned int arg ) +{ + ER ercd; + T_RTSK ref_tskd; + +#ifdef CYG_TEST_UITRON_TEST1_LOOPING + while ( 1 ) { +#endif // CYG_TEST_UITRON_TEST1_LOOPING + + CYG_TEST_INFO( "Task 1 running" ); + CYG_TEST_INFO( TIMESLICEMSG ); + + intercom = 0; + intercount = 0; + + CYG_TEST_INFO( "Testing get_tid and ref_tsk" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 1 == scratch, "tid not 1" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = get_tid( NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "get_tid bad ercd !E_PAR" ); +#endif + ercd = get_tid( NADR ); + CYG_TEST_CHECK( E_PAR == ercd, "get_tid bad ercd !E_PAR" ); + ercd = ref_tsk( &ref_tskd, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_tsk bad ercd !E_ID" ); + ercd = ref_tsk( &ref_tskd, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_tsk bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_tsk( NULL, 1 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_tsk bad ercd !E_PAR" ); +#endif + ercd = ref_tsk( NADR, 1 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_tsk bad ercd !E_PAR" ); +#endif // we can test bad param error returns + ercd = ref_tsk( &ref_tskd, 1 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_RUN == ref_tskd.tskstat, "Bad task status 1" ); + ercd = ref_tsk( &ref_tskd, 0 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_RUN == ref_tskd.tskstat, "Bad task status 0" ); + ercd = ref_tsk( &ref_tskd, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_DMT == ref_tskd.tskstat, "Bad task status 2" ); + CYG_TEST_CHECK( 2 == ref_tskd.tskpri, "Bad task prio 2" ); + + ercd = rsm_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rsm_tsk DMT bad ercd !E_OBJ" ); + ercd = frsm_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "frsm_tsk DMT bad ercd !E_OBJ" ); + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai DMT bad ercd !E_OBJ" ); + ercd = sus_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "sus_tsk DMT bad ercd !E_OBJ" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "wup_tsk DMT bad ercd !E_OBJ" ); + ercd = can_wup( &scratch, 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "can_wup DMT bad ercd !E_OBJ" ); + + CYG_TEST_PASS( "get_tid, ref_tsk" ); + + CYG_TEST_INFO( "Testing prio change and start task" ); + ercd = sta_tsk( 2, 99 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + + // drop pri of task 2 + ercd = chg_pri( 2, 4 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ref_tsk( &ref_tskd, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_RDY == ref_tskd.tskstat, "Bad task status 2" ); + CYG_TEST_CHECK( 4 == ref_tskd.tskpri, "Bad task prio 2" ); + + // drop our pri below task 2 + ercd = chg_pri( 0, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + + ercd = ref_tsk( &ref_tskd, 1 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( 5 == ref_tskd.tskpri, "Bad task prio 1" ); + ercd = ref_tsk( &ref_tskd, 0 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( 5 == ref_tskd.tskpri, "Bad task prio 0" ); + ercd = ref_tsk( &ref_tskd, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + // it will have run to completion and regained its original prio + CYG_TEST_CHECK( 2 == ref_tskd.tskpri, "Bad task prio 2" ); + CYG_TEST_CHECK( TTS_DMT == ref_tskd.tskstat, "Bad task status 2" ); + + // retest these now that the task has executed once + ercd = rsm_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rsm_tsk DMT bad ercd !E_OBJ" ); + ercd = frsm_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "frsm_tsk DMT bad ercd !E_OBJ" ); + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai DMT bad ercd !E_OBJ" ); + ercd = sus_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "sus_tsk DMT bad ercd !E_OBJ" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "wup_tsk DMT bad ercd !E_OBJ" ); + ercd = can_wup( &scratch, 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "can_wup DMT bad ercd !E_OBJ" ); + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = chg_pri( -6, 9 ); + CYG_TEST_CHECK( E_ID == ercd, "chg_pri bad ercd !E_ID" ); + ercd = chg_pri( 99, 9 ); + CYG_TEST_CHECK( E_ID == ercd, "chg_pri bad ercd !E_ID" ); + ercd = sta_tsk( -6, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "sta_tsk bad ercd !E_ID" ); + ercd = sta_tsk( 99, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "sta_tsk bad ercd !E_ID" ); +#endif // we can test bad param error returns + + CYG_TEST_PASS( "sta_tsk, chg_pri" ); + + CYG_TEST_INFO( "Testing delay and dispatch disabling" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_CTX == ercd, "dly_tsk bad ercd !E_CTX" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_CTX == ercd, "dly_tsk bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + CYG_TEST_PASS( "dly_tsk, ena_dsp, dis_dsp" ); + + CYG_TEST_INFO( "Testing ready queue manipulation" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ercd = rot_rdq( 4 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ercd = rot_rdq( 5 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rot_rdq( -6 ); + CYG_TEST_CHECK( E_PAR == ercd, "rot_rdq bad ercd !E_PAR" ); + ercd = rot_rdq( 99 ); + CYG_TEST_CHECK( E_PAR == ercd, "rot_rdq bad ercd !E_PAR" ); +#endif // we can test bad param error returns + + CYG_TEST_PASS( "rot_rdq" ); + + CYG_TEST_INFO( "Testing suspend/resume" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = sus_tsk( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "sus_tsk bad ercd !E_ID" ); + ercd = sus_tsk( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "sus_tsk bad ercd !E_ID" ); + ercd = rsm_tsk( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "rsm_tsk bad ercd !E_ID" ); + ercd = rsm_tsk( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "rsm_tsk bad ercd !E_ID" ); + ercd = frsm_tsk( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "frsm_tsk bad ercd !E_ID" ); + ercd = frsm_tsk( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "frsm_tsk bad ercd !E_ID" ); +#endif // we can test bad param error returns + // drop task 3 pri to same as us + CYG_TEST_CHECK( 0 == intercount, "intercount != 0" ); + + intercom = 3; // tell T3 to loop + TSRELEASE(); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 3, 66 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 3, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 1 ); + CYG_TEST_CHECK( 1 == intercount, "intercount != 1" ); + ercd = sus_tsk( 3 ); + TSRELEASE(); + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + intercom = 0; // bad data to T3 + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 1 == intercount, "intercount != 1" ); + intercom = 3; // tell T3 to loop + TSRELEASE(); + ercd = rsm_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "rsm_tsk bad ercd" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 2 ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + + CYG_TEST_INFO( "Command task 3 inner loop stop" ); + intercom = 2 + 4; + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + + ercd = sus_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + intercom = 0; // bad data to T3 + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ercd = sus_tsk( 3 ); // suspend AGAIN + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + ercd = sus_tsk( 3 ); // AND AGAIN + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + ercd = rsm_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "rsm_tsk bad ercd" ); + ercd = rsm_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "rsm_tsk bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + intercom = 3; // tell T3 to loop + TSRELEASE(); + ercd = rsm_tsk( 3 ); // expect restart this time + CYG_TEST_CHECK( E_OK == ercd, "rsm_tsk bad ercd" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 3 ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + + CYG_TEST_INFO( "Command task 3 inner loop stop 2" ); + intercom = 2 + 4; + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + + ercd = sus_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + intercom = 0; // bad data to T3 + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + ercd = sus_tsk( 3 ); // suspend AGAIN + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + ercd = sus_tsk( 3 ); // AND AGAIN + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + intercom = 3; // tell T3 to loop + TSRELEASE(); + ercd = frsm_tsk( 3 ); // expect restart this time + CYG_TEST_CHECK( E_OK == ercd, "frsm_tsk bad ercd" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 4 ); + CYG_TEST_CHECK( 4 == intercount, "intercount != 4" ); + + TSRELEASE(); + ercd = rsm_tsk( 3 ); // try it again + CYG_TEST_CHECK( E_OBJ == ercd, "rsm_tsk bad ercd !E_OBJ" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 5 ); + CYG_TEST_CHECK( 5 == intercount, "intercount != 5" ); + + TSRELEASE(); + ercd = frsm_tsk( 3 ); // try it again + CYG_TEST_CHECK( E_OBJ == ercd, "frsm_tsk bad ercd !E_OBJ" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 6 ); + CYG_TEST_CHECK( 6 == intercount, "intercount != 6" ); + + CYG_TEST_INFO( "Command task 3 all loops stop" ); + intercom = 4 + 8; + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 6 == intercount, "intercount != 6" ); + + intercom = intercount = 0; + + CYG_TEST_PASS( "sus_tsk, rsm_tsk, frsm_tsk" ); + + CYG_TEST_INFO( "Testing sleep/wakeup stuff" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = wup_tsk( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "wup_tsk bad ercd !E_ID" ); + ercd = wup_tsk( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "wup_tsk bad ercd !E_ID" ); + ercd = can_wup( &scratch, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "can_wup bad ercd !E_ID" ); + ercd = can_wup( &scratch, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "can_wup bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = can_wup( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "can_wup bad ercd !E_PAR" ); +#endif + ercd = can_wup( NADR, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "can_wup bad ercd !E_PAR" ); + + ercd = wup_tsk( 0 ); // not ourself + CYG_TEST_CHECK( E_ID == ercd, "wup_tsk bad ercd !E_ID" ); + ercd = wup_tsk( 1 ); // ourself + CYG_TEST_CHECK( E_OBJ == ercd, "wup_tsk bad ercd !E_OBJ" ); +#endif // we can test bad param error returns + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = tslp_tsk( -6 ); + CYG_TEST_CHECK( E_PAR == ercd, "tslp_tsk bad ercd !E_PAR" ); +#endif // we can test bad param error returns + ercd = tslp_tsk( TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tslp_tsk bad ercd !E_TMOUT" ); + ercd = tslp_tsk( 5 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tslp_tsk bad ercd !E_TMOUT" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = tslp_tsk( TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "tslp_tsk bad ercd !E_CTX" ); + ercd = tslp_tsk( TMO_POL ); + CYG_TEST_CHECK( E_CTX == ercd, "tslp_tsk bad ercd !E_CTX" ); + ercd = tslp_tsk( 5 ); + CYG_TEST_CHECK( E_CTX == ercd, "tslp_tsk bad ercd !E_CTX" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = tslp_tsk( -6 ); + CYG_TEST_CHECK( E_PAR == ercd, "tslp_tsk bad ercd !E_PAR" ); +#endif // we can test bad param error returns + ercd = tslp_tsk( TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tslp_tsk bad ercd !E_TMOUT" ); + ercd = tslp_tsk( 5 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tslp_tsk bad ercd !E_TMOUT" ); + + // drop task 4 pri to same as us + intercount = 0; + intercom = 1; // test plain slp_tsk + TSRELEASE(); + ercd = chg_pri( 4, 5 ); + CYG_TEST_CHECK( E_OBJ == ercd, "chg_pri bad ercd" ); + + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 4, 77 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 4, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + + ercd = wup_tsk( 4 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 1 ); + CYG_TEST_CHECK( 1 == intercount, "intercount != 1" ); + intercom = 2; // test tslp_tsk + TSRELEASE(); + ercd = wup_tsk( 4 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 2 ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + intercom = 3; // test tslp_tsk + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + intercom = 1; // test slp_tsk next... + ercd = dly_tsk( 20 ); // without a wup + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ICWAIT( 3 ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + + intercom = 1; // ...test slp_tsk + TSRELEASE(); + ercd = dly_tsk( 20 ); // without a wup (yet) + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + TSRELEASE(); + ercd = tslp_tsk( 20 ); // yield again + CYG_TEST_CHECK( E_TMOUT == ercd, "tslp_tsk bad ercd !E_TMOUT" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); // and again + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + TSRELEASE(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rot_rdq( 0 ); // and yield + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 4 ); + CYG_TEST_CHECK( 4 == intercount, "intercount != 4" ); + + intercom = 1; // test slp_tsk + TSRELEASE(); + ercd = dly_tsk( 20 ); // without a wup (yet) + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 4 == intercount, "intercount != 4" ); + + // this wup will restart it when we yield: + TSLOCK(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + // these will count up: + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + scratch = -1; + ercd = can_wup( &scratch, 4 ); + CYG_TEST_CHECK( E_OK == ercd, "can_wup bad ercd" ); + CYG_TEST_CHECK( 2 == scratch, "Cancelled wups not 2" ); + CYG_TEST_CHECK( 4 == intercount, "intercount != 4" ); + TSUNLOCK(); + + intercom = 4; // do nothing + TSRELEASE(); + ercd = rot_rdq( 0 ); // and yield + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 5 ); + CYG_TEST_CHECK( 5 == intercount, "intercount != 5" ); + TSRELEASE(); + ercd = dly_tsk( 20 ); // let it do nothing + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + TSRELEASE(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + TSRELEASE(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + TSRELEASE(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + TSRELEASE(); + ercd = dly_tsk( 20 ); // lots of wups but no sleep + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 5 == intercount, "intercount != 5" ); + scratch = -1; + ercd = can_wup( &scratch, 4 ); + CYG_TEST_CHECK( E_OK == ercd, "can_wup bad ercd" ); + CYG_TEST_CHECK( 3 == scratch, "Cancelled wups not 3" ); + // now check that they are cancelled by doing a wait again + intercom = 1; // test slp_tsk + TSRELEASE(); + ercd = rot_rdq( 0 ); // still without a wup + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); // still without a wup + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + intercom = 4; // do nothing next + TSRELEASE(); + ICWAIT( 6 ); + CYG_TEST_CHECK( 6 == intercount, "intercount != 6" ); + ercd = rot_rdq( 0 ); // still without a wup + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 6 == intercount, "intercount != 6" ); + TSRELEASE(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rot_rdq( 0 ); // it will run now + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); // it will run now + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 7 ); + CYG_TEST_CHECK( 7 == intercount, "intercount != 7" ); + + TSRELEASE(); + intercom = 99; // exit, all done + ercd = rot_rdq( 0 ); // let it run + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 8 ); + CYG_TEST_CHECK( 8 == intercount, "intercount != 8" ); + + TSRELEASE(); + ercd = rot_rdq( 0 ); // let it run + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 8 == intercount, "intercount != 8" ); + + CYG_TEST_PASS( "wup_tsk, can_wup, slp_tsk, tslp_tsk" ); + +#ifdef CYG_TEST_UITRON_TEST1_LOOPING + chg_pri( 1, 1 ); + rot_rdq( 0 ); + ter_tsk( 2 ); + rot_rdq( 0 ); + ter_tsk( 3 ); + rot_rdq( 0 ); + ter_tsk( 4 ); + rot_rdq( 0 ); + } +#endif // CYG_TEST_UITRON_TEST1_LOOPING + + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + CYG_TEST_PASS( "Task 2 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == scratch, "tid not 2" ); + if ( 99 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 99" ); + ext_tsk(); + CYG_TEST_FAIL( "Task 2 failed to exit" ); +} + +void task3( unsigned int arg ) +{ + ER ercd; + TSLOCK(); + CYG_TEST_PASS("Task3 running"); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 3 == scratch, "tid not 3" ); + if ( 66 != arg ) + CYG_TEST_FAIL( "Task 3 arg not 66" ); + + while ( 2 & intercom ) { + while ( 1 & intercom ) { + intercount++; + TSSTOP(); + do { + TSUNLOCK(); + ercd = rot_rdq( 0 ); // yield() + TSLOCK(); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq 1 (task3) bad ercd" ); + } while ( !TSGO() ); + } + CYG_TEST_CHECK( 4 & intercom, "should not have got here yet 1" ); + TSSTOP(); + do { + TSUNLOCK(); + ercd = rot_rdq( 0 ); // yield() + TSLOCK(); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq 2 (task3) bad ercd" ); + } while ( !TSGO() ); + } + CYG_TEST_CHECK( 8 & intercom, "should not have got here yet 2" ); + + TSUNLOCK(); + ext_tsk(); + CYG_TEST_FAIL( "Task 3 failed to exit" ); +} + +void task4( unsigned int arg ) +{ + ER ercd; + CYG_TEST_PASS("Task4 running"); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 4 == scratch, "tid not 4" ); + if ( 77 != arg ) + CYG_TEST_FAIL( "Task 4 arg not 77" ); + while ( 1 ) { + switch ( intercom ) { + case 1: + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk (task4) bad ercd" ); + break; + case 2: + ercd = tslp_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk (task4) bad ercd" ); + break; + case 3: + ercd = tslp_tsk( 10 ); + CYG_TEST_CHECK( E_TMOUT == ercd, + "slp_tsk (task4) bad ercd !E_TMOUT" ); + break; + case 4: + // busily do nothing + while ( 4 == intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, + "rot_rdq (task4 idle) bad ercd" ); + } + break; + case 99: + goto out; + default: + CYG_TEST_FAIL( "Task 4 bad intercom" ); + goto out; + } + intercount++; + TSSTOP(); + do { + ercd = rot_rdq( 0 ); // yield() + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq (task4) bad ercd" ); + } while ( !TSGO() ); + } +out: + ext_tsk(); + CYG_TEST_FAIL( "Task 4 failed to exit" ); +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF test1.c diff --git a/packages/compat/uitron/v2_0/tests/test2.c b/packages/compat/uitron/v2_0/tests/test2.c new file mode 100644 index 00000000..ff7c556d --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/test2.c @@ -0,0 +1,970 @@ +//=========================================================================== +// +// test2.c +// +// uITRON "C" test program two +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough flag objects */ \ + defined( CYGPKG_UITRON_FLAGS ) && \ + (CYGNUM_UITRON_FLAGS >= 3) && \ + (CYGNUM_UITRON_FLAGS < 90) && \ + ( !defined(CYGPKG_UITRON_FLAGS_CREATE_DELETE) || \ + CYGNUM_UITRON_FLAGS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough message boxes */ \ + defined( CYGPKG_UITRON_MBOXES ) && \ + (CYGNUM_UITRON_MBOXES >= 3) && \ + (CYGNUM_UITRON_MBOXES < 90) && \ + ( !defined(CYGPKG_UITRON_MBOXES_CREATE_DELETE) || \ + CYGNUM_UITRON_MBOXES_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough fixed memory pools */ \ + defined( CYGPKG_UITRON_MEMPOOLFIXED ) && \ + (CYGNUM_UITRON_MEMPOOLFIXED >= 3) && \ + (CYGNUM_UITRON_MEMPOOLFIXED < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLFIXED_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough variable mempools */ \ + defined( CYGPKG_UITRON_MEMPOOLVAR ) && \ + (CYGNUM_UITRON_MEMPOOLVAR >= 3) && \ + (CYGNUM_UITRON_MEMPOOLVAR < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLVAR_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +int intercom = 0; +int intercount = 0; +INT scratch = 0; + +void task1( unsigned int arg ) +{ + ER ercd; + + T_RSEM sem_info; + T_RFLG flg_info; + T_RMBX mbx_info; + T_RMPF mpf_info; + T_RMPL mpl_info; + UINT flagptn; + static char foo[] = "Test message"; + T_MSG *msgptr = (T_MSG *)foo; + T_MSG *rxptr = NULL; + VP blfptr = (VP)foo; + VP blkptr = (VP)foo; + + int delay = 10; + if (cyg_test_is_simulator) + delay = 3; + + CYG_TEST_INFO( "Task 1 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 1 == scratch, "tid not 1" ); + + // start a lower prio task to interact with + intercom = 1; + ercd = sta_tsk( 2, 222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + // Semaphores; all the illegal argument combinations first + CYG_TEST_INFO( "Testing semaphore ops" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = sig_sem( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "sig_sem bad ercd !E_ID" ); + ercd = sig_sem( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "sig_sem bad ercd !E_ID" ); + ercd = wai_sem( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "wai_sem bad ercd !E_ID" ); + ercd = wai_sem( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "wai_sem bad ercd !E_ID" ); + ercd = preq_sem( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "preq_sem bad ercd !E_ID" ); + ercd = preq_sem( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "preq_sem bad ercd !E_ID" ); + ercd = twai_sem( -6, delay ); + CYG_TEST_CHECK( E_ID == ercd, "twai_sem bad ercd !E_ID" ); + ercd = twai_sem( 99, delay ); + CYG_TEST_CHECK( E_ID == ercd, "twai_sem bad ercd !E_ID" ); + ercd = twai_sem( 2, -999 ); + CYG_TEST_CHECK( E_PAR == ercd, "twai_sem bad ercd !E_PAR" ); + ercd = ref_sem( &sem_info, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_sem bad ercd !E_ID" ); + ercd = ref_sem( &sem_info, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_sem bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_sem( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_sem bad ercd !E_PAR" ); +#endif + ercd = ref_sem( NADR, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_sem bad ercd !E_PAR" ); + CYG_TEST_PASS( "bad calls: sig_sem, [t]wai_sem, preq_sem, ref_sem" ); +#endif // we can test bad param error returns + + // check the waitable functions versus dispatch disable + ercd = preq_sem( 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "preq_sem bad ercd !E_TMOUT" ); + ercd = twai_sem( 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem bad ercd !E_TMOUT" ); + ercd = twai_sem( 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem(POL) bad ercd !E_TMOUT" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = wai_sem( 2 ); + CYG_TEST_CHECK( E_CTX == ercd, "wai_sem bad ercd !E_CTX" ); + ercd = twai_sem( 2, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "twai_sem bad ercd !E_CTX" ); + ercd = twai_sem( 2, TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "twai_sem(FEVR) bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = twai_sem( 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem(POL) bad ercd !E_TMOUT" ); + ercd = preq_sem( 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "preq_sem bad ercd !E_TMOUT" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = preq_sem( 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "preq_sem bad ercd !E_TMOUT" ); + ercd = twai_sem( 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem bad ercd !E_TMOUT" ); + ercd = twai_sem( 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem(POL) bad ercd !E_TMOUT" ); + CYG_TEST_PASS( "bad calls: wai_sem, twai_sem with dis_dsp" ); + + // check ref_sem with various states + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 1 == sem_info.semcnt, "semcnt should be 1" ); + ercd = preq_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 2 == sem_info.semcnt, "semcnt should be 2" ); + ercd = wai_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 1 == sem_info.semcnt, "semcnt should be 1" ); + ercd = twai_sem( 2, delay ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + intercom = 0; + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + intercom = 1; + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 != sem_info.wtsk, "sem.wtsk should be non0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be non0" ); +#if 1 + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); +#else // old, non-uITRON semantics + CYG_TEST_CHECK( 1 == sem_info.semcnt, "semcnt should be 1" ); +#endif + ercd = dly_tsk( delay ); // let task 2 pick up the signal + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + CYG_TEST_PASS( "good calls: sig_sem, [t]wai,preq_sem with ref_sem" ); + + // Flags; all the illegal argument combinations first + CYG_TEST_INFO( "Testing flag ops" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = set_flg( -6, 1 ); + CYG_TEST_CHECK( E_ID == ercd, "set_flg bad ercd !E_ID" ); + ercd = set_flg( 99, 1 ); + CYG_TEST_CHECK( E_ID == ercd, "set_flg bad ercd !E_ID" ); + ercd = clr_flg( -6, 1 ); + CYG_TEST_CHECK( E_ID == ercd, "clr_flg bad ercd !E_ID" ); + ercd = clr_flg( 99, 1 ); + CYG_TEST_CHECK( E_ID == ercd, "sig_flg bad ercd !E_ID" ); + ercd = wai_flg( &flagptn, -6, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_ID == ercd, "wai_flg bad ercd !E_ID" ); + ercd = wai_flg( &flagptn, 99, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_ID == ercd, "wai_flg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = wai_flg( NULL, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_PAR == ercd, "wai_flg bad ercd !E_PAR" ); +#endif + ercd = wai_flg( NADR, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_PAR == ercd, "wai_flg bad ercd !E_PAR" ); + ercd = wai_flg( &flagptn, 2, 7, 34657 ); + CYG_TEST_CHECK( E_PAR == ercd, "wai_flg bad ercd !E_PAR" ); + ercd = wai_flg( &flagptn, 2, 0, TWF_ANDW ); + CYG_TEST_CHECK( E_PAR == ercd, "wai_flg bad ercd !E_PAR" ); + ercd = pol_flg( &flagptn, -6, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_ID == ercd, "pol_flg bad ercd !E_ID" ); + ercd = pol_flg( &flagptn, 99, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_ID == ercd, "pol_flg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = pol_flg( NULL, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_PAR == ercd, "pol_flg bad ercd !E_PAR" ); +#endif + ercd = pol_flg( NADR, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_PAR == ercd, "pol_flg bad ercd !E_PAR" ); + ercd = pol_flg( &flagptn, 2, 7, 34657 ); + CYG_TEST_CHECK( E_PAR == ercd, "pol_flg bad ercd !E_PAR" ); + ercd = pol_flg( &flagptn, 2, 0, TWF_ANDW ); + CYG_TEST_CHECK( E_PAR == ercd, "pol_flg bad ercd !E_PAR" ); + ercd = twai_flg( &flagptn, -6, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_ID == ercd, "twai_flg bad ercd !E_ID" ); + ercd = twai_flg( &flagptn, 99, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_ID == ercd, "twai_flg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = twai_flg( NULL, 2, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "twai_flg bad ercd !E_PAR" ); +#endif + ercd = twai_flg( NADR, 2, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "twai_flg bad ercd !E_PAR" ); + ercd = twai_flg( &flagptn, 2, 7, 34657, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "twai_flg bad ercd !E_PAR" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, -999 ); + CYG_TEST_CHECK( E_PAR == ercd, "twai_flg bad ercd !E_PAR" ); + ercd = twai_flg( &flagptn, 2, 0, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "twai_flg bad ercd !E_PAR" ); + ercd = ref_flg( &flg_info, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_flg bad ercd !E_ID" ); + ercd = ref_flg( &flg_info, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_flg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_flg( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_flg bad ercd !E_PAR" ); +#endif + ercd = ref_flg( NADR, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_flg bad ercd !E_PAR" ); + CYG_TEST_PASS( "bad calls: set_flg, clr_flg, [t]wai,pol_flg, ref_flg" ); +#endif // we can test bad param error returns + + // check the waitable functions versus dispatch disable + ercd = pol_flg( &flagptn, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pol_flg bad ercd !E_TMOUT" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg bad ercd !E_TMOUT" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg(POL) bad ercd !E_TMOUT" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = wai_flg( &flagptn, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_CTX == ercd, "wai_flg bad ercd !E_CTX" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "twai_flg bad ercd !E_CTX" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "twai_flg(FEVR) bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg(POL) bad ercd !E_TMOUT" ); + ercd = pol_flg( &flagptn, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pol_flg bad ercd !E_TMOUT" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = pol_flg( &flagptn, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pol_flg bad ercd !E_TMOUT" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg bad ercd !E_TMOUT" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg(POL) bad ercd !E_TMOUT" ); + CYG_TEST_PASS( "bad calls: wai_flg, twai_flg with dis_dsp" ); + + // check ref_flg with various states + ercd = ref_flg( &flg_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 == flg_info.wtsk, "flg.wtsk should be non0" ); + CYG_TEST_CHECK( 0 == flg_info.flgptn, "flgptn should be 0" ); + intercom = 0; + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + intercom = 1; + ercd = ref_flg( &flg_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 != flg_info.wtsk, "flg.wtsk should be non0" ); + CYG_TEST_CHECK( 0 == flg_info.flgptn, "flgptn should be 0" ); + ercd = set_flg( 2, 0x5555 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_flg bad ercd" ); + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_flg( &flg_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 != flg_info.wtsk, "flg.wtsk should be non0" ); + CYG_TEST_CHECK( 0x5555 == flg_info.flgptn, "flgptn should be 0x5555" ); + ercd = clr_flg( 2, 0xF0F0 ); + CYG_TEST_CHECK( E_OK == ercd, "clr_flg bad ercd" ); + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_flg( &flg_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 != flg_info.wtsk, "flg.wtsk should be non0" ); + CYG_TEST_CHECK( 0x5050 == flg_info.flgptn, "flgptn should be 0x5050" ); + ercd = set_flg( 2, 0xFFFF ); + CYG_TEST_CHECK( E_OK == ercd, "sig_flg bad ercd" ); + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_flg( &flg_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 == flg_info.wtsk, "flg.wtsk should be 0" ); + CYG_TEST_CHECK( 0xFFFF == flg_info.flgptn, "flgptn should be 0xFFFF" ); + CYG_TEST_PASS( "good calls: clr_flg, set_flg, wai_flg with ref_flg" ); + + // Mailboxes; all the illegal argument combinations first + CYG_TEST_INFO( "Testing mailbox ops" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = snd_msg( -6, msgptr ); + CYG_TEST_CHECK( E_ID == ercd, "snd_msg bad ercd !E_ID" ); + ercd = snd_msg( 99, msgptr ); + CYG_TEST_CHECK( E_ID == ercd, "snd_msg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = snd_msg( 2, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "snd_msg bad ercd !E_PAR" ); +#endif + ercd = snd_msg( 2, NADR ); + CYG_TEST_CHECK( E_PAR == ercd, "snd_msg bad ercd !E_PAR" ); + ercd = rcv_msg( &rxptr, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "rcv_msg bad ercd !E_ID" ); + ercd = rcv_msg( &rxptr, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "rcv_msg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = rcv_msg( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "rcv_msg bad ercd !E_PAR" ); +#endif + ercd = rcv_msg( NADR, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "rcv_msg bad ercd !E_PAR" ); + ercd = prcv_msg( &rxptr, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "prcv_msg bad ercd !E_ID" ); + ercd = prcv_msg( &rxptr, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "prcv_msg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = prcv_msg( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "prcv_msg bad ercd !E_PAR" ); +#endif + ercd = prcv_msg( NADR, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "prcv_msg bad ercd !E_PAR" ); + ercd = trcv_msg( &rxptr, -6, delay ); + CYG_TEST_CHECK( E_ID == ercd, "trcv_msg bad ercd !E_ID" ); + ercd = trcv_msg( &rxptr, 99, delay ); + CYG_TEST_CHECK( E_ID == ercd, "trcv_msg bad ercd !E_ID" ); + ercd = trcv_msg( &rxptr, 2, -999 ); + CYG_TEST_CHECK( E_PAR == ercd, "trcv_msg bad ercd !E_PAR" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = trcv_msg( NULL, 2, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "trcv_msg bad ercd !E_PAR" ); +#endif + ercd = trcv_msg( NADR, 2, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "trcv_msg bad ercd !E_PAR" ); + ercd = ref_mbx( &mbx_info, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mbx bad ercd !E_ID" ); + ercd = ref_mbx( &mbx_info, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mbx bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_mbx( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_mbx bad ercd !E_PAR" ); +#endif + ercd = ref_mbx( NADR, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_mbx bad ercd !E_PAR" ); + CYG_TEST_PASS( "bad calls: snd_msg, [pt]rcv_msg, ref_mbx" ); +#endif // we can test bad param error returns + + // check the waitable functions versus dispatch disable + ercd = prcv_msg( &rxptr, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "prcv_msg bad ercd !E_TMOUT" ); + ercd = trcv_msg( &rxptr, 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg bad ercd !E_TMOUT" ); + ercd = trcv_msg( &rxptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg(POL) bad ercd !E_TMOUT" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rcv_msg( &rxptr, 2 ); + CYG_TEST_CHECK( E_CTX == ercd, "rcv_msg bad ercd !E_CTX" ); + ercd = trcv_msg( &rxptr, 2, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "trcv_msg bad ercd !E_CTX" ); + ercd = trcv_msg( &rxptr, 2, TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "trcv_msg(FEVR) bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = trcv_msg( &rxptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg(POL) bad ercd !E_TMOUT" ); + ercd = prcv_msg( &rxptr, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "prcv_msg bad ercd !E_TMOUT" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = prcv_msg( &rxptr, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "prcv_msg bad ercd !E_TMOUT" ); + ercd = trcv_msg( &rxptr, 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg bad ercd !E_TMOUT" ); + ercd = trcv_msg( &rxptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg(POL) bad ercd !E_TMOUT" ); + CYG_TEST_PASS( "bad calls: rcv_msg, trcv_msg with dis_dsp" ); + + // check ref_mbx with various states + ercd = ref_mbx( &mbx_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mbx bad ercd" ); + CYG_TEST_CHECK( 0 == mbx_info.wtsk, "mbx.wtsk should be 0" ); + CYG_TEST_CHECK( NADR == mbx_info.pk_msg, "mbx peek should be NADR" ); + intercom = 0; + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + intercom = 1; + ercd = ref_mbx( &mbx_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mbx bad ercd" ); + CYG_TEST_CHECK( 0 != mbx_info.wtsk, "mbx.wtsk should be non0" ); + CYG_TEST_CHECK( NADR == mbx_info.pk_msg, "mbx peek should be NADR" ); + ercd = snd_msg( 2, msgptr ); + CYG_TEST_CHECK( E_OK == ercd, "snd_msg bad ercd" ); + ercd = ref_mbx( &mbx_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mbx bad ercd" ); + CYG_TEST_CHECK( 0 == mbx_info.wtsk, "mbx.wtsk should be 0" ); +#if 1 + CYG_TEST_CHECK( NADR == mbx_info.pk_msg, "mbx peek should be NADR" ); +#else // old, non-uITRON semantics + CYG_TEST_CHECK( msgptr == mbx_info.pk_msg, "mbx peek should be msgptr" ); +#endif + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_mbx( &mbx_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mbx bad ercd" ); + CYG_TEST_CHECK( 0 == mbx_info.wtsk, "mbx.wtsk should be 0" ); + CYG_TEST_CHECK( NADR == mbx_info.pk_msg, "mbx peek should be NADR" ); + // fill the message box, expect E_QOVR + for ( scratch = 0 ; scratch < 100 ; scratch++ ) { + if ( E_OK != ( ercd = snd_msg( 2, msgptr ) ) ) + break; + } + CYG_TEST_CHECK( (100 == scratch) || (E_QOVR == ercd), + "snd_msg bad ercd !E_QOVR/E_OK" ); + // empty the message box, expect the right number and E_TMOUT + for ( ; 1 ; scratch-- ) { + if ( E_OK != ( ercd = prcv_msg( &rxptr, 2 ) ) ) + break; + } + CYG_TEST_CHECK( 0 == scratch, "rcv_msg count bad scratch!=0" ); + CYG_TEST_CHECK( E_TMOUT == ercd, "rcv_msg bad ercd !E_TMOUT" ); + + CYG_TEST_PASS( "good calls: rcv_msg, snd_msg with ref_msg" ); + + // Fixed block memory pools: all the illegal argument combinations first + CYG_TEST_INFO( "Testing fixed block memory ops" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rel_blf( -6, blfptr ); + CYG_TEST_CHECK( E_ID == ercd, "rel_blf bad ercd !E_ID" ); + ercd = rel_blf( 99, blfptr ); + CYG_TEST_CHECK( E_ID == ercd, "rel_blf bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = rel_blf( 2, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "rel_blf bad ercd !E_PAR" ); +#endif + ercd = rel_blf( 2, NADR ); + CYG_TEST_CHECK( E_PAR == ercd, "rel_blf bad ercd !E_PAR" ); +#endif // we can test bad param error returns + ercd = rel_blf( 2, blfptr ); // it did not come from a mpf + CYG_TEST_CHECK( E_PAR == ercd, "rel_blf bad ercd !E_PAR" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blf( &blfptr, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "get_blf bad ercd !E_ID" ); + ercd = get_blf( &blfptr, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "get_blf bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = get_blf( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "get_blf bad ercd !E_PAR" ); +#endif + ercd = get_blf( NADR, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "get_blf bad ercd !E_PAR" ); + ercd = pget_blf( &blfptr, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "pget_blf bad ercd !E_ID" ); + ercd = pget_blf( &blfptr, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "pget_blf bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = pget_blf( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "pget_blf bad ercd !E_PAR" ); +#endif + ercd = pget_blf( NADR, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "pget_blf bad ercd !E_PAR" ); + ercd = tget_blf( &blfptr, -6, delay ); + CYG_TEST_CHECK( E_ID == ercd, "tget_blf bad ercd !E_ID" ); + ercd = tget_blf( &blfptr, 99, delay ); + CYG_TEST_CHECK( E_ID == ercd, "tget_blf bad ercd !E_ID" ); + ercd = tget_blf( &blfptr, 2, -999 ); + CYG_TEST_CHECK( E_PAR == ercd, "tget_blf bad ercd !E_PAR" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = tget_blf( NULL, 2, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "tget_blf bad ercd !E_PAR" ); +#endif + ercd = tget_blf( NADR, 2, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "tget_blf bad ercd !E_PAR" ); + ercd = ref_mpf( &mpf_info, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mpf bad ercd !E_ID" ); + ercd = ref_mpf( &mpf_info, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mpf bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_mpf( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_mpf bad ercd !E_PAR" ); +#endif + ercd = ref_mpf( NADR, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_mpf bad ercd !E_PAR" ); + CYG_TEST_PASS( "bad calls: rel_blf, [pt]get_blf, ref_mpf " ); +#endif // we can test bad param error returns + + // check the waitable functions versus dispatch disable + ercd = pget_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blf bad ercd" ); + ercd = rel_blf( 2, blfptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blf bad ercd" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = rel_blf( 2, blfptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_CTX == ercd, "get_blf bad ercd !E_CTX" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blf bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = pget_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blf bad ercd" ); + ercd = rel_blf( 2, blfptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blf bad ercd" ); + ercd = rel_blf( 2, blfptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + // consume the whole thing then do it again, expecting E_TMOUT + while ( E_OK == (ercd = pget_blf( &blfptr, 2 ) ) ) + continue; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + ercd = pget_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf bad ercd !E_TMOUT" ); + ercd = tget_blf( &blfptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf(POL) bad ercd !E_TMOUT" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_CTX == ercd, "get_blf bad ercd !E_CTX" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blf bad ercd !E_CTX" ); + ercd = tget_blf( &blfptr, 2, TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blf(FEVR) bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = tget_blf( &blfptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf(POL) bad ercd !E_TMOUT" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = pget_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + ercd = tget_blf( &blfptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf(POL) bad ercd !E_TMOUT" ); + CYG_TEST_PASS( "bad calls: rel_blf, [pt]get_blf with ena_dsp" ); + + // check ref_mpf with various states + ercd = ref_mpf( &mpf_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpf bad ercd" ); + CYG_TEST_CHECK( 0 == mpf_info.wtsk, "mpf.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == mpf_info.frbcnt, "mpf.frbcnt should be 0" ); + intercom = 0; + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + intercom = 1; + ercd = ref_mpf( &mpf_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpf bad ercd" ); + CYG_TEST_CHECK( 0 != mpf_info.wtsk, "mpf.wtsk should be non0" ); + CYG_TEST_CHECK( 0 == mpf_info.frbcnt, "mpf.frbcnt should be 0" ); + ercd = rel_blf( 2, blfptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + ercd = ref_mpf( &mpf_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpf bad ercd" ); + CYG_TEST_CHECK( 0 == mpf_info.wtsk, "mpf.wtsk should be 0" ); +#if 1 + CYG_TEST_CHECK( 0 == mpf_info.frbcnt, "mpf.frbcnt should be 0" ); +#else // old, non-uITRON semantics + CYG_TEST_CHECK( 0 != mpf_info.frbcnt, "mpf.frbcnt should be non0" ); +#endif + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_mpf( &mpf_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpf bad ercd" ); + CYG_TEST_CHECK( 0 == mpf_info.wtsk, "mpf.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == mpf_info.frbcnt, "mpf.frbcnt should be 0" ); + CYG_TEST_PASS( "good calls: rel_blf, get_blf with ref_mpf" ); + + // Variable block memory pools; illegal arguments + CYG_TEST_INFO( "Testing variable block memory ops" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rel_blk( -6, blkptr ); + CYG_TEST_CHECK( E_ID == ercd, "rel_blk bad ercd !E_ID" ); + ercd = rel_blk( 99, blkptr ); + CYG_TEST_CHECK( E_ID == ercd, "rel_blk bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = rel_blk( 2, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "rel_blk bad ercd !E_PAR" ); +#endif + ercd = rel_blk( 2, NADR ); + CYG_TEST_CHECK( E_PAR == ercd, "rel_blk bad ercd !E_PAR" ); +#endif // we can test bad param error returns + ercd = rel_blk( 2, blkptr ); // it did not come from a mpl + CYG_TEST_CHECK( E_PAR == ercd, "rel_blk bad ercd !E_PAR" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blk( &blkptr, -6, 100 ); + CYG_TEST_CHECK( E_ID == ercd, "get_blk bad ercd !E_ID" ); + ercd = get_blk( &blkptr, 99, 100 ); + CYG_TEST_CHECK( E_ID == ercd, "get_blk bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = get_blk( NULL, 2, 100 ); + CYG_TEST_CHECK( E_PAR == ercd, "get_blk bad ercd !E_PAR" ); +#endif + ercd = get_blk( NADR, 2, 100 ); + CYG_TEST_CHECK( E_PAR == ercd, "get_blk bad ercd !E_PAR" ); + ercd = pget_blk( &blkptr, -6, 100 ); + CYG_TEST_CHECK( E_ID == ercd, "pget_blk bad ercd !E_ID" ); + ercd = pget_blk( &blkptr, 99, 100 ); + CYG_TEST_CHECK( E_ID == ercd, "pget_blk bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = pget_blk( NULL, 2, 100 ); + CYG_TEST_CHECK( E_PAR == ercd, "pget_blk bad ercd !E_PAR" ); +#endif + ercd = pget_blk( NADR, 2, 100 ); + CYG_TEST_CHECK( E_PAR == ercd, "pget_blk bad ercd !E_PAR" ); + ercd = tget_blk( &blkptr, -6, 100, delay ); + CYG_TEST_CHECK( E_ID == ercd, "tget_blk bad ercd !E_ID" ); + ercd = tget_blk( &blkptr, 99, 100, delay ); + CYG_TEST_CHECK( E_ID == ercd, "tget_blk bad ercd !E_ID" ); + ercd = tget_blk( &blkptr, 2, 100, -999 ); + CYG_TEST_CHECK( E_PAR == ercd, "tget_blk bad ercd !E_PAR" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = tget_blk( NULL, 2, 100, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "tget_blk bad ercd !E_PAR" ); +#endif + ercd = tget_blk( NADR, 2, 100, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "tget_blk bad ercd !E_PAR" ); + ercd = ref_mpl( &mpl_info, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mpl bad ercd !E_ID" ); + ercd = ref_mpl( &mpl_info, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mpl bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_mpl( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_mpl bad ercd !E_PAR" ); +#endif + ercd = ref_mpl( NADR, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_mpl bad ercd !E_PAR" ); + CYG_TEST_PASS( "bad calls: rel_blk, [pt]get_blk, ref_mpl " ); +#endif // we can test bad param error returns + + // check the waitable functions versus dispatch disable + ercd = pget_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blk bad ercd" ); + ercd = rel_blk( 2, blkptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blk bad ercd" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = rel_blk( 2, blkptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_CTX == ercd, "get_blk bad ercd !E_CTX" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blk bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = pget_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blk bad ercd" ); + ercd = rel_blk( 2, blkptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blk bad ercd" ); + ercd = rel_blk( 2, blkptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + // consume the whole thing then do it again, expecting E_TMOUT + while ( E_OK == (ercd = pget_blk( &blkptr, 2, 100 ) ) ) + continue; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + ercd = pget_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk bad ercd !E_TMOUT" ); + ercd = tget_blk( &blkptr, 2, 100, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk(POL) bad ercd !E_TMOUT" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_CTX == ercd, "get_blk bad ercd !E_CTX" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blk bad ercd !E_CTX" ); + ercd = tget_blk( &blkptr, 2, 100, TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blk(FEVR) bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = tget_blk( &blkptr, 2, 100, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk(POL) bad ercd !E_TMOUT" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = pget_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + ercd = tget_blk( &blkptr, 2, 100, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk(POL) bad ercd !E_TMOUT" ); + CYG_TEST_PASS( "bad calls: rel_blk, [pt]get_blk with ena_dsp" ); + + // check ref_mpl with various states + ercd = ref_mpl( &mpl_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpl bad ercd" ); + CYG_TEST_CHECK( 0 == mpl_info.wtsk, "mpl.wtsk should be 0" ); + CYG_TEST_CHECK( mpl_info.maxsz <= mpl_info.frsz, + "mpl.maxsz not < mpl.frsz" ); + intercom = 0; + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + intercom = 1; + ercd = ref_mpl( &mpl_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpl bad ercd" ); + CYG_TEST_CHECK( 0 != mpl_info.wtsk, "mpl.wtsk should be non0" ); + ercd = rel_blk( 2, blkptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + ercd = ref_mpl( &mpl_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpl bad ercd" ); + CYG_TEST_CHECK( 0 == mpl_info.wtsk, "mpl.wtsk should be 0" ); + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_mpl( &mpl_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpl bad ercd" ); + CYG_TEST_CHECK( 0 == mpl_info.wtsk, "mpl.wtsk should be 0" ); + CYG_TEST_PASS( "good calls: rel_blk, get_blk with ref_mpl" ); + + // all done + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + T_MSG *msgp = NULL; + UINT flgval = 0; + VP blfp = NULL; + VP blkp = NULL; + + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == scratch, "tid not 2" ); + if ( 222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 222" ); + + while ( intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + } + ercd = wai_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + while ( intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + } + ercd = wai_flg( &flgval, 2, 99, TWF_ANDW ); + CYG_TEST_CHECK( E_OK == ercd, "wai_flg bad ercd" ); + CYG_TEST_CHECK( 99 == (99 & flgval), "flg value no good" ); + while ( intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + } + ercd = rcv_msg( &msgp, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "rcv_msg bad ercd" ); + CYG_TEST_CHECK( NULL != msgp, "no msg received" ); + CYG_TEST_CHECK( NADR != msgp, "no msg received" ); + while ( intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + } + ercd = get_blf( &blfp, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "get_blf bad ercd" ); + CYG_TEST_CHECK( NULL != blfp, "no blf allocated" ); + CYG_TEST_CHECK( NADR != blfp, "no blf allocated" ); + while ( intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + } + ercd = get_blk( &blkp, 2, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "get_blk bad ercd" ); + CYG_TEST_CHECK( NULL != blkp, "no blk allocated" ); + CYG_TEST_CHECK( NADR != blkp, "no blk allocated" ); + + ext_tsk(); + CYG_TEST_FAIL( "Task 2 failed to exit" ); +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF test2.c diff --git a/packages/compat/uitron/v2_0/tests/test3.c b/packages/compat/uitron/v2_0/tests/test3.c new file mode 100644 index 00000000..69eb06ea --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/test3.c @@ -0,0 +1,255 @@ +//=========================================================================== +// +// test3.c +// +// uITRON "C" test program three +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +int t2done = 0; +int t3done = 0; +int t4done = 0; + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +void task1( unsigned int arg ) +{ + ER ercd; + INT scratch; + + CYG_TEST_INFO( "Task 1 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 1 == scratch, "tid not 1" ); + + // start lower prio tasks to interact with + ercd = sta_tsk( 2, 222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = sta_tsk( 3, 333 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = sta_tsk( 4, 444 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + + // now start the test + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + CYG_TEST_INFO( "T1 awoken" ); + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + CYG_TEST_INFO( "T1 signalled" ); + + // let the others complete, so we get the status back + ercd = dly_tsk( 50 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + CYG_TEST_CHECK( t2done, "t2 not done" ); + CYG_TEST_CHECK( t3done, "t3 not done" ); + CYG_TEST_CHECK( t4done, "t4 not done" ); + + CYG_TEST_PASS( "Immediate-dispatch producer/consumer test OK" ); + + // all done + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + INT scratch; + + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == scratch, "tid not 2" ); + if ( 222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 222" ); + + // now start the test + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + CYG_TEST_INFO( "T2 awoken" ); + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = wup_tsk( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + + CYG_TEST_INFO( "T2 completing" ); + t2done++; + + ercd = slp_tsk(); + CYG_TEST_FAIL( "Task 2 sleep came back" ); +} + +void task3( unsigned int arg ) +{ + ER ercd; + INT scratch; + + CYG_TEST_INFO( "Task 3 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 3 == scratch, "tid not 3" ); + if ( 333 != arg ) + CYG_TEST_FAIL( "Task 3 arg not 333" ); + + // now start the test + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + CYG_TEST_INFO( "T3 awoken" ); + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + + CYG_TEST_INFO( "T3 completing" ); + t3done++; + + ercd = slp_tsk(); + CYG_TEST_FAIL( "Task 3 sleep came back" ); +} + +void task4( unsigned int arg ) +{ + ER ercd; + INT scratch; + + CYG_TEST_INFO( "Task 4 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 4 == scratch, "tid not 4" ); + if ( 444 != arg ) + CYG_TEST_FAIL( "Task 4 arg not 444" ); + + // now start the test + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + + CYG_TEST_INFO( "T4 completing" ); + t4done++; + + ercd = slp_tsk(); + CYG_TEST_FAIL( "Task 4 sleep came back" ); +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF test3.c diff --git a/packages/compat/uitron/v2_0/tests/test4.c b/packages/compat/uitron/v2_0/tests/test4.c new file mode 100644 index 00000000..a5896238 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/test4.c @@ -0,0 +1,403 @@ +//=========================================================================== +// +// test4.c +// +// uITRON "C" test program four +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dsm +// Contributors: dsm +// Date: 1998-06-12 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough cyclic handlers */ \ + defined( CYGPKG_UITRON_CYCLICS ) && \ + (CYGNUM_UITRON_CYCLICS >= 3) && \ + (CYGNUM_UITRON_CYCLICS < 90) && \ + \ + /* test configuration for enough alarm handlers */ \ + defined( CYGPKG_UITRON_ALARMS ) && \ + (CYGNUM_UITRON_ALARMS >= 3) && \ + (CYGNUM_UITRON_ALARMS < 90) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +volatile int intercount = 0; +INT scratch; + +void hand1(void) +{ + CYG_TEST_INFO("Handler 1 called"); + intercount++; +} + +void hand2(void) +{ + CYG_TEST_CHECK( 2 == intercount, "handler out of sync" ); + CYG_TEST_INFO("Handler 2 called"); + intercount++; +} + +void task1( unsigned int arg ) +{ + ER ercd; + + T_DCYC dcyc; + T_DALM dalm; + T_RCYC rcyc; + T_RALM ralm; + + unsigned int tm; + + static char foo[] = "Test message"; + VP info = (VP)foo; + + // Increase times when running on HW since overhead of GDB packet + // acknowledgements may cause tests of timing to fail. + if (cyg_test_is_simulator) + tm = 1; + else + tm = 4; + + CYG_TEST_INFO( "Task 1 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 1 == scratch, "tid not 1" ); + + dcyc.exinf = (VP)info; + dcyc.cycatr = TA_HLNG; + dcyc.cychdr = (FP)&hand1; + dcyc.cycact = TCY_INI; // bad + dcyc.cyctim = 2; + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = def_cyc(3, &dcyc); + CYG_TEST_CHECK( E_PAR == ercd, "def_cyc bad ercd !E_PAR" ); +#endif // we can test bad param error returns + + dcyc.cycact = TCY_OFF; // make good + dcyc.cyctim = 0; // bad + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = def_cyc(3, &dcyc); + CYG_TEST_CHECK( E_PAR == ercd, "def_cyc bad ercd !E_PAR" ); +#endif // we can test bad param error returns + + dcyc.cyctim = 1; // make good + + ercd = def_cyc(3, &dcyc); + CYG_TEST_CHECK( E_OK == ercd, "def_cyc bad ercd" ); + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = def_cyc(-6, &dcyc); + CYG_TEST_CHECK( E_PAR == ercd, "def_cyc bad ercd !E_PAR" ); + ercd = def_cyc(99, &dcyc); + CYG_TEST_CHECK( E_PAR == ercd, "def_cyc bad ercd !E_PAR" ); + + ercd = act_cyc(-6, TCY_OFF); + CYG_TEST_CHECK( E_PAR == ercd, "act_cyc bad ercd !E_PAR" ); + ercd = act_cyc(99, TCY_OFF); + CYG_TEST_CHECK( E_PAR == ercd, "act_cyc bad ercd !E_PAR" ); + ercd = act_cyc( 3, ~0); + CYG_TEST_CHECK( E_PAR == ercd, "act_cyc bad ercd !E_PAR" ); + + ercd = ref_cyc(&rcyc, -6); + CYG_TEST_CHECK( E_PAR == ercd, "ref_cyc bad ercd !E_PAR" ); + ercd = ref_cyc(&rcyc, 99); + CYG_TEST_CHECK( E_PAR == ercd, "ref_cyc bad ercd !E_PAR" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_cyc(NULL, 3); + CYG_TEST_CHECK( E_PAR == ercd, "ref_cyc bad ercd !E_PAR" ); +#endif + ercd = ref_cyc(NADR, 3); + CYG_TEST_CHECK( E_PAR == ercd, "ref_cyc bad ercd !E_PAR" ); +#endif // we can test bad param error returns + + ercd = def_cyc(3, (T_DCYC *)NADR); + CYG_TEST_CHECK( E_OK == ercd, "def_cyc bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_cyc bad ercd !E_NOEXS" ); +#endif // we can test bad param error returns + + CYG_TEST_PASS( "bad calls: def_cyc, act_cyc, ref_cyc" ); + + dalm.exinf = (VP)info; + dalm.almatr = TA_HLNG; + dalm.almhdr = (FP)&hand2; + dalm.tmmode = ~0; // bad + dalm.almtim = 20; + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = def_alm(3, &dalm); + CYG_TEST_CHECK( E_PAR == ercd, "def_alm bad ercd !E_PAR" ); +#endif // we can test bad param error returns + + dalm.tmmode = TTM_REL; // make good + dalm.almtim = 0; // bad + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = def_alm(3, &dalm); + CYG_TEST_CHECK( E_PAR == ercd, "def_alm bad ercd !E_PAR" ); +#endif // we can test bad param error returns + + dalm.almtim = 1000; // make good + + ercd = def_alm(3, &dalm); + CYG_TEST_CHECK( E_OK == ercd, "def_alm bad ercd" ); + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = ref_alm(&ralm, -6); + CYG_TEST_CHECK( E_PAR == ercd, "ref_alm bad ercd !E_PAR" ); + ercd = ref_alm(&ralm, 99); + CYG_TEST_CHECK( E_PAR == ercd, "ref_alm bad ercd !E_PAR" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_alm(NULL, 3); + CYG_TEST_CHECK( E_PAR == ercd, "ref_alm bad ercd !E_PAR" ); +#endif + ercd = ref_alm(NADR, 3); + CYG_TEST_CHECK( E_PAR == ercd, "ref_alm bad ercd !E_PAR" ); + +#endif // we can test bad param error returns + ercd = def_alm(3, (T_DALM *)NADR); + CYG_TEST_CHECK( E_OK == ercd, "def_cyc bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = ref_alm(&ralm, 3); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_cyc bad ercd !E_NOEXS" ); +#endif // we can test bad param error returns + + CYG_TEST_PASS( "bad calls: def_alm, act_alm, ref_alm" ); + + dcyc.exinf = (VP)info; + dcyc.cycatr = TA_HLNG; + dcyc.cychdr = (FP)&hand1; + dcyc.cycact = TCY_ON; + dcyc.cyctim = 50*tm; + + ercd = def_cyc(3, &dcyc); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 45*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 50*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_ON == rcyc.cycact, "rcyc.cycact should be TCY_ON" ); + ercd = act_cyc(3, TCY_OFF); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 45*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 50*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_OFF == rcyc.cycact, "rcyc.cycact should be TCY_OFF" ); + ercd = act_cyc(3, TCY_ON); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc bad ercd" ); + + CYG_TEST_PASS("good calls: def_cyc, act_cyc, ref_cyc"); + + dalm.exinf = (VP)info; + dalm.almatr = TA_HLNG; + dalm.almhdr = (FP)&hand2; + dalm.tmmode = TTM_REL; + dalm.almtim = 120*tm; + + ercd = def_alm(3, &dalm); + CYG_TEST_CHECK( E_OK == ercd, "def_alm bad ercd" ); + ercd = ref_alm(&ralm, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_alm bad ercd" ); + CYG_TEST_CHECK( info == ralm.exinf, "ralm.exinf should be info" ); + CYG_TEST_CHECK( 115*tm < ralm.lfttim, "ralm.lfttim too small" ); + CYG_TEST_CHECK( ralm.lfttim <= 120*tm, "ralm.lfttim too big" ); + + // Expect handlers to be called at approximate times + // time intercount + // tm*50 hand1 0 + // tm*100 hand1 1 + // tm*120 hand2 2 + // tm*150 hand1 3 + + ercd = dly_tsk(160*tm); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 4 == intercount, "handlers not both called" ); + + ercd = act_cyc(3, TCY_OFF); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc(off) bad ercd" ); + + ercd = dly_tsk(60*tm); // enough for at least one tick + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 4 == intercount, "cyclic not disabled" ); + + // approx time now 220, so we expect a cycle in about 30 ticks + ercd = act_cyc(3, TCY_ON); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc(on) bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 25*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 35*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_ON == rcyc.cycact, "rcyc.cycact should be TCY_ON" ); + + // now resynchronize with right now: + ercd = act_cyc(3, TCY_ON|TCY_INI); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc(on) bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 45*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 50*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_ON == rcyc.cycact, "rcyc.cycact should be TCY_ON" ); + + // wait a bit and check that time marches on, or even down + ercd = dly_tsk(10*tm); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 35*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 45*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_ON == rcyc.cycact, "rcyc.cycact should be TCY_ON" ); + + // now turn it off and re-synch with right now: + ercd = act_cyc(3, TCY_OFF|TCY_INI); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc(on) bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 45*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 50*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_OFF == rcyc.cycact, "rcyc.cycact should be TCY_OFF" ); + + ercd = act_cyc(3, TCY_OFF); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc(on) bad ercd" ); + + CYG_TEST_PASS("good calls: def_cyc, act_cyc, ref_cyc, def_alm, ref_alm"); + + // all done + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF test4.c diff --git a/packages/compat/uitron/v2_0/tests/test5.c b/packages/compat/uitron/v2_0/tests/test5.c new file mode 100644 index 00000000..4a86cc05 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/test5.c @@ -0,0 +1,353 @@ +//=========================================================================== +// +// test5.c +// +// uITRON "C" test program five +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dsm +// Contributors: dsm +// Date: 1998-06-12 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough flag objects */ \ + defined( CYGPKG_UITRON_FLAGS ) && \ + (CYGNUM_UITRON_FLAGS >= 3) && \ + (CYGNUM_UITRON_FLAGS < 90) && \ + ( !defined(CYGPKG_UITRON_FLAGS_CREATE_DELETE) || \ + CYGNUM_UITRON_FLAGS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough message boxes */ \ + defined( CYGPKG_UITRON_MBOXES ) && \ + (CYGNUM_UITRON_MBOXES >= 3) && \ + (CYGNUM_UITRON_MBOXES < 90) && \ + ( !defined(CYGPKG_UITRON_MBOXES_CREATE_DELETE) || \ + CYGNUM_UITRON_MBOXES_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough fixed memory pools */ \ + defined( CYGPKG_UITRON_MEMPOOLFIXED ) && \ + (CYGNUM_UITRON_MEMPOOLFIXED >= 3) && \ + (CYGNUM_UITRON_MEMPOOLFIXED < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLFIXED_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough variable mempools */ \ + defined( CYGPKG_UITRON_MEMPOOLVAR ) && \ + (CYGNUM_UITRON_MEMPOOLVAR >= 3) && \ + (CYGNUM_UITRON_MEMPOOLVAR < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLVAR_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +volatile int intercount = 0; +UINT scratch; +T_MSG *t_msg; +VP vp; + +void task1( unsigned int arg ) +{ + ER ercd; + int i; + T_RSYS rsys; + + CYG_TEST_INFO( "Task 1 running" ); + + // check initial state + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_TSK == rsys.sysstat, "system state not TSS_TSK" ); + // disable intrs and check state + ercd = loc_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "loc_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_LOC == rsys.sysstat, "system state not TSS_LOC" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // try an illegal op + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_CTX == ercd, "dly_tsk bad ercd !E_CTX" ); +#endif // CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // enable intrs and check state and a legal sleep + ercd = unl_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "unl_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_TSK == rsys.sysstat, "system state not TSS_TSK" ); + ercd = dly_tsk( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + // disable intrs and try scheduler illegal ops + ercd = loc_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "loc_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_LOC == rsys.sysstat, "system state not TSS_LOC" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = dis_dsp(); + CYG_TEST_CHECK( E_CTX == ercd, "dis_dsp bad ercd !E_CTX" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_CTX == ercd, "ena_dsp bad ercd !E_CTX" ); +#endif // CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // enable again and check state + ercd = unl_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "unl_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_TSK == rsys.sysstat, "system state not TSS_TSK" ); + // disable the scheduler and check state + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_DDSP == rsys.sysstat, "system state not TSS_DDSP" ); + // disable intrs and check state + ercd = loc_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "loc_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_LOC == rsys.sysstat, "system state not TSS_LOC" ); + // then unlock and check state + ercd = unl_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "unl_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_TSK == rsys.sysstat, "system state not TSS_TSK" ); + + CYG_TEST_PASS( "Interrupt dis/enabling and interactions" ); + + // and now we can do the rest of the test + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai bad ercd !E_OBJ" ); + ercd = rel_wai( 1 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai(me) bad ercd !E_OBJ" ); + ercd = rel_wai( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "rel_wai bad ercd !E_ID" ); + ercd = rel_wai( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "rel_wai bad ercd !E_ID" ); +#endif // we can test bad param error returns + + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 2, 22222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 2, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai bad ercd !E_OBJ" ); + ercd = rel_wai( 1 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai(me) bad ercd !E_OBJ" ); +#endif // we can test bad param error returns + + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "wai_sem bad ercd !E_RLWAI" ); + + ercd = twai_sem( 1, 20 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "twai_sem bad ercd !E_RLWAI" ); + + ercd = wai_flg( &scratch, 1, 9999, 0 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "wai_flg bad ercd !E_RLWAI" ); + + ercd = twai_flg( &scratch, 1, 9999, 0, 10 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "twai_flg bad ercd !E_RLWAI" ); + + ercd = rcv_msg( &t_msg, 1 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "rcv_msg bad ercd !E_RLWAI" ); + + ercd = trcv_msg( &t_msg, 1, 10 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "trcv_msg bad ercd !E_RLWAI" ); + + // these are loops so as to consume the whole of the mempool + // in order to wait at the end + for ( i = 0; i < 10; i++ ) + if ( E_OK != (ercd = get_blf( &vp, 3 ) ) ) + break; + CYG_TEST_CHECK( E_RLWAI == ercd, "get_blf bad ercd !E_RLWAI" ); + + for ( i = 0; i < 10; i++ ) + if ( E_OK != (ercd = tget_blf( &vp, 3, 10 ) ) ) + break; + CYG_TEST_CHECK( E_RLWAI == ercd, "tget_blf bad ercd !E_RLWAI" ); + + for ( i = 0; i < 10; i++ ) + if ( E_OK != (ercd = get_blk( &vp, 1, 1000 ) ) ) + break; + CYG_TEST_CHECK( E_RLWAI == ercd, "get_blk bad ercd !E_RLWAI" ); + + for ( i = 0; i < 10; i++ ) + if ( E_OK != (ercd = tget_blk( &vp, 1, 1000, 10 ) ) ) + break; + CYG_TEST_CHECK( E_RLWAI == ercd, "tget_blk bad ercd !E_RLWAI" ); + + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "dly_tsk bad ercd !E_RLWAI" ); + + ercd = tslp_tsk( 10 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "tslp_tsk bad ercd !E_RLWAI" ); + + ercd = slp_tsk(); + CYG_TEST_CHECK( E_RLWAI == ercd, "slp_tsk bad ercd !E_RLWAI" ); + + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + CYG_TEST_PASS("release wait: various waiting calls"); + + // all done + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + int i; + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &i ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == i, "tid not 2" ); + if ( 22222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 22222" ); + + for ( i = 0 ; i < 100; i++ ) { + ercd = rel_wai( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_wai bad ercd" ); + } + // we expect task2 to be killed here + CYG_TEST_FAIL( "Task 2 ran to completion!" ); +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF test5.c diff --git a/packages/compat/uitron/v2_0/tests/test6.c b/packages/compat/uitron/v2_0/tests/test6.c new file mode 100644 index 00000000..c026d66d --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/test6.c @@ -0,0 +1,599 @@ +//=========================================================================== +// +// test6.c +// +// uITRON "C" test program six +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-10-01 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough flag objects */ \ + defined( CYGPKG_UITRON_FLAGS ) && \ + (CYGNUM_UITRON_FLAGS >= 3) && \ + (CYGNUM_UITRON_FLAGS < 90) && \ + ( !defined(CYGPKG_UITRON_FLAGS_CREATE_DELETE) || \ + CYGNUM_UITRON_FLAGS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough message boxes */ \ + defined( CYGPKG_UITRON_MBOXES ) && \ + (CYGNUM_UITRON_MBOXES >= 3) && \ + (CYGNUM_UITRON_MBOXES < 90) && \ + ( !defined(CYGPKG_UITRON_MBOXES_CREATE_DELETE) || \ + CYGNUM_UITRON_MBOXES_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +volatile int intercount = 0; +UINT scratch; +T_MSG *t_msg = (T_MSG *)&scratch; +T_MSG *msg; +VP vp; + +T_CSEM t_csem = { NULL, 0, 0 }; +T_CMBX t_cmbx = { NULL, 0 }; +T_CFLG t_cflg = { NULL, 0, 0 }; +T_RSEM t_rsem; +T_RMBX t_rmbx; +T_RFLG t_rflg; + + +void task1( unsigned int arg ) +{ + ER ercd; + int tests = 0; + + CYG_TEST_INFO( "Task 1 running" ); + + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 2, 22222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 2, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + tests++; +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_sem( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_sem bad ercd !E_ID" ); + ercd = del_sem( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_sem bad ercd !E_ID" ); + ercd = cre_sem( -6, &t_csem ); + CYG_TEST_CHECK( E_ID == ercd, "cre_sem bad ercd !E_ID" ); + ercd = cre_sem( 99, &t_csem ); + CYG_TEST_CHECK( E_ID == ercd, "cre_sem bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + ercd = cre_sem( 3, &t_csem ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_sem bad ercd !E_OBJ" ); + // delete it so we can play + ercd = del_sem( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); + // check it is deleted + ercd = sig_sem( 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sig_sem bad ercd !E_NOEXS" ); + ercd = preq_sem( 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "preq_sem bad ercd !E_NOEXS" ); + ercd = twai_sem( 3, 10 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "twai_sem bad ercd !E_NOEXS" ); + ercd = wai_sem( 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "wai_sem bad ercd !E_NOEXS" ); + ercd = ref_sem( &t_rsem, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_sem bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_sem( 3, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_sem bad ercd !E_PAR" ); +#endif + ercd = cre_sem( 3, NADR ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_sem bad ercd !E_PAR" ); + t_csem.sematr = 0xfff; + ercd = cre_sem( 3, &t_csem ); + CYG_TEST_CHECK( E_RSATR == ercd, "cre_sem bad ercd !E_RSATR" ); + t_csem.sematr = 0; +#endif // we can test bad param error returns + ercd = cre_sem( 3, &t_csem ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); + // and check we can use it + ercd = sig_sem( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = wai_sem( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + ercd = preq_sem( 3 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "preq_sem bad ercd !E_TMOUT" ); + ercd = twai_sem( 3, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem bad ercd !E_TMOUT" ); + ercd = ref_sem( &t_rsem, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_sem bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = twai_sem( 2, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_sem bad ercd !E_DLT" ); + + // check they are deleted + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sig_sem bad ercd !E_NOEXS" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sig_sem bad ercd !E_NOEXS" ); + // re-create and do it again + ercd = cre_sem( 1, &t_csem ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); + ercd = cre_sem( 2, &t_csem ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); + + // now wait while task 2 deletes the wait objects again + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_sem bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = twai_sem( 2, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_sem bad ercd !E_DLT" ); + + // check they are deleted + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sig_sem bad ercd !E_NOEXS" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sig_sem bad ercd !E_NOEXS" ); + + CYG_TEST_PASS("create/delete semaphores"); +#endif // CYGPKG_UITRON_SEMAS_CREATE_DELETE + + +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + tests++; +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_flg( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_flg bad ercd !E_ID" ); + ercd = del_flg( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_flg bad ercd !E_ID" ); + ercd = cre_flg( -6, &t_cflg ); + CYG_TEST_CHECK( E_ID == ercd, "cre_flg bad ercd !E_ID" ); + ercd = cre_flg( 99, &t_cflg ); + CYG_TEST_CHECK( E_ID == ercd, "cre_flg bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + ercd = cre_flg( 3, &t_cflg ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_flg bad ercd !E_OBJ" ); + // delete it so we can play + ercd = del_flg( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + // check it is deleted + ercd = set_flg( 3, 0x6789 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "set_flg bad ercd !E_NOEXS" ); + ercd = clr_flg( 3, 0x9876 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "clr_flg bad ercd !E_NOEXS" ); + ercd = pol_flg( &scratch, 3, 0xdddd, TWF_ANDW ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pol_flg bad ercd !E_NOEXS" ); + ercd = twai_flg( &scratch, 3, 0x4444, TWF_ORW, 10 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "twai_flg bad ercd !E_NOEXS" ); + ercd = wai_flg( &scratch, 3, 0xbbbb, TWF_ANDW | TWF_CLR ); + CYG_TEST_CHECK( E_NOEXS == ercd, "wai_flg bad ercd !E_NOEXS" ); + ercd = ref_flg( &t_rflg, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_flg bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_flg( 3, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_flg bad ercd !E_PAR" ); +#endif + ercd = cre_flg( 3, NADR ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_flg bad ercd !E_PAR" ); + t_cflg.flgatr = 0xfff; + ercd = cre_flg( 3, &t_cflg ); + CYG_TEST_CHECK( E_RSATR == ercd, "cre_flg bad ercd !E_RSATR" ); +#endif // we can test bad param error returns + // now create it well + t_cflg.flgatr = 0; + t_cflg.iflgptn = 0; + ercd = cre_flg( 3, &t_cflg ); + CYG_TEST_CHECK( E_OK == ercd, "cre_flg bad ercd" ); + // and check we can use it + ercd = clr_flg( 3, 0x7256 ); + CYG_TEST_CHECK( E_OK == ercd, "clr_flg bad ercd" ); + ercd = set_flg( 3, 0xff ); + CYG_TEST_CHECK( E_OK == ercd, "set_flg bad ercd" ); + ercd = wai_flg( &scratch, 3, 0xaa, TWF_ANDW | TWF_CLR ); + CYG_TEST_CHECK( E_OK == ercd, "wai_flg bad ercd" ); + ercd = pol_flg( &scratch, 3, 0xaa, TWF_ANDW | TWF_CLR ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pol_flg bad ercd !E_TMOUT" ); + ercd = twai_flg( &scratch, 3, 0xaa, TWF_ANDW | TWF_CLR, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg bad ercd !E_TMOUT" ); + ercd = ref_flg( &t_rflg, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 == t_rflg.flgptn, "ref_flg bad ercd" ); + // now create it again with a preset pattern and check that we can + // detect that pattern: + ercd = del_flg( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + t_cflg.flgatr = 0; + t_cflg.iflgptn = 0x1234; + ercd = cre_flg( 3, &t_cflg ); + CYG_TEST_CHECK( E_OK == ercd, "cre_flg bad ercd" ); + // and check we can use it + ercd = wai_flg( &scratch, 3, 0x1200, TWF_ANDW ); + CYG_TEST_CHECK( E_OK == ercd, "wai_flg bad ercd" ); + ercd = pol_flg( &scratch, 3, 0x0034, TWF_ANDW ); + CYG_TEST_CHECK( E_OK == ercd, "pol_flg bad ercd" ); + ercd = twai_flg( &scratch, 3, 0x1004, TWF_ANDW, 10 ); + CYG_TEST_CHECK( E_OK == ercd, "twai_flg bad ercd" ); + ercd = pol_flg( &scratch, 3, 0xffedcb, TWF_ORW ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pol_flg bad ercd !E_TMOUT" ); + ercd = ref_flg( &t_rflg, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0x1234 == t_rflg.flgptn, "ref_flg bad ercd" ); + ercd = clr_flg( 3, 0 ); + ercd = ref_flg( &t_rflg, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 == t_rflg.flgptn, "ref_flg bad ercd" ); + + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = wai_flg( &scratch, 1, 0xaa, TWF_ANDW ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_flg bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = twai_flg( &scratch, 2, 0x55, TWF_ANDW, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_flg bad ercd !E_DLT" ); + + // check they are deleted + ercd = set_flg( 1, 0x22 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "set_flg bad ercd !E_NOEXS" ); + ercd = clr_flg( 2, 0xdd ); + CYG_TEST_CHECK( E_NOEXS == ercd, "clr_flg bad ercd !E_NOEXS" ); + // re-create and do it again + t_cflg.iflgptn = 0x5555; + ercd = cre_flg( 1, &t_cflg ); + CYG_TEST_CHECK( E_OK == ercd, "cre_flg bad ercd" ); + t_cflg.iflgptn = 0; + ercd = cre_flg( 2, &t_cflg ); + CYG_TEST_CHECK( E_OK == ercd, "cre_flg bad ercd" ); + + // now wait while task 2 deletes the wait objects again + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = wai_flg( &scratch, 1, 0xaaaa, TWF_ORW | TWF_CLR ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_flg bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = twai_flg( &scratch, 2, 0xffff, TWF_ORW, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_flg bad ercd !E_DLT" ); + + // check they are deleted + ercd = clr_flg( 1, 0xd00d ); + CYG_TEST_CHECK( E_NOEXS == ercd, "clr_flg bad ercd !E_NOEXS" ); + ercd = set_flg( 2, 0xfff00 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "set_flg bad ercd !E_NOEXS" ); + + CYG_TEST_PASS("create/delete flags"); +#endif // CYGPKG_UITRON_FLAGS_CREATE_DELETE + +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE + tests++; +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_mbx( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mbx bad ercd !E_ID" ); + ercd = del_mbx( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mbx bad ercd !E_ID" ); + ercd = cre_mbx( -6, &t_cmbx ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mbx bad ercd !E_ID" ); + ercd = cre_mbx( 99, &t_cmbx ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mbx bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + ercd = cre_mbx( 3, &t_cmbx ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_mbx bad ercd !E_OBJ" ); + // delete it so we can play + ercd = del_mbx( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); + // check it is deleted + ercd = snd_msg( 3, t_msg ); + CYG_TEST_CHECK( E_NOEXS == ercd, "snd_msg bad ercd !E_NOEXS" ); + ercd = rcv_msg( &msg, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "rcv_msg bad ercd !E_NOEXS" ); + ercd = trcv_msg( &msg, 3, 10 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "trcv_msg bad ercd !E_NOEXS" ); + ercd = prcv_msg( &msg, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "prcv_msg bad ercd !E_NOEXS" ); + ercd = ref_mbx( &t_rmbx, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_mbx bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_mbx( 3, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_mbx bad ercd !E_PAR" ); +#endif + ercd = cre_mbx( 3, NADR ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_mbx bad ercd !E_PAR" ); + t_cmbx.mbxatr = 0xfff; + ercd = cre_mbx( 3, &t_cmbx ); + CYG_TEST_CHECK( E_RSATR == ercd, "cre_mbx bad ercd !E_RSATR" ); + t_cmbx.mbxatr = 0; +#endif // we can test bad param error returns + ercd = cre_mbx( 3, &t_cmbx ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mbx bad ercd" ); + // and check we can use it + ercd = snd_msg( 3, t_msg ); + CYG_TEST_CHECK( E_OK == ercd, "snd_msg bad ercd" ); + ercd = rcv_msg( &msg, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "rcv_msg bad ercd" ); + ercd = trcv_msg( &msg, 3, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg bad ercd !E_TMOUT" ); + ercd = prcv_msg( &msg, 3 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "prcv_msg bad ercd !E_TMOUT" ); + ercd = ref_mbx( &t_rmbx, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mbx bad ercd" ); + + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rcv_msg( &msg, 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_mbx bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = trcv_msg( &msg, 2, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_mbx bad ercd !E_DLT" ); + + // check they are deleted + ercd = snd_msg( 1, t_msg ); + CYG_TEST_CHECK( E_NOEXS == ercd, "snd_msg bad ercd !E_NOEXS" ); + ercd = snd_msg( 2, t_msg ); + CYG_TEST_CHECK( E_NOEXS == ercd, "snd_msg bad ercd !E_NOEXS" ); + // re-create and do it again + ercd = cre_mbx( 1, &t_cmbx ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mbx bad ercd" ); + ercd = cre_mbx( 2, &t_cmbx ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mbx bad ercd" ); + + // now wait while task 2 deletes the wait objects again + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rcv_msg( &msg, 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_mbx bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = trcv_msg( &msg, 2, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_mbx bad ercd !E_DLT" ); + + // check they are deleted + ercd = snd_msg( 1, t_msg ); + CYG_TEST_CHECK( E_NOEXS == ercd, "snd_msg bad ercd !E_NOEXS" ); + ercd = snd_msg( 2, t_msg ); + CYG_TEST_CHECK( E_NOEXS == ercd, "snd_msg bad ercd !E_NOEXS" ); + + CYG_TEST_PASS("create/delete mboxes"); +#endif // CYGPKG_UITRON_MBOXES_CREATE_DELETE + + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + ercd = dly_tsk( 5 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + // all done + if ( 0 == tests ) { + CYG_TEST_NA( "No objects have create/delete enabled" ); + } + else { + CYG_TEST_EXIT( "All done" ); + } + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + int i; + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &i ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == i, "tid not 2" ); + if ( 22222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 22222" ); + + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + ercd = del_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); +#endif // CYGPKG_UITRON_SEMAS_CREATE_DELETE + +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + ercd = del_flg( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_flg( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_flg( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_flg( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); +#endif // CYGPKG_UITRON_FLAGS_CREATE_DELETE + +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE + ercd = del_mbx( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mbx( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mbx( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mbx( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); +#endif // CYGPKG_UITRON_MBOXES_CREATE_DELETE + + // we expect task2 to be killed here + CYG_TEST_FAIL( "Task 2 ran to completion!" ); +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF test6.c diff --git a/packages/compat/uitron/v2_0/tests/test7.c b/packages/compat/uitron/v2_0/tests/test7.c new file mode 100644 index 00000000..7cd2724c --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/test7.c @@ -0,0 +1,1013 @@ +//=========================================================================== +// +// test7.c +// +// uITRON "C" test program seven +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-10-01 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough flag objects */ \ + defined( CYGPKG_UITRON_FLAGS ) && \ + (CYGNUM_UITRON_FLAGS >= 3) && \ + (CYGNUM_UITRON_FLAGS < 90) && \ + ( !defined(CYGPKG_UITRON_FLAGS_CREATE_DELETE) || \ + CYGNUM_UITRON_FLAGS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough message boxes */ \ + defined( CYGPKG_UITRON_MBOXES ) && \ + (CYGNUM_UITRON_MBOXES >= 3) && \ + (CYGNUM_UITRON_MBOXES < 90) && \ + ( !defined(CYGPKG_UITRON_MBOXES_CREATE_DELETE) || \ + CYGNUM_UITRON_MBOXES_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough fixed memory pools */ \ + defined( CYGPKG_UITRON_MEMPOOLFIXED ) && \ + (CYGNUM_UITRON_MEMPOOLFIXED >= 3) && \ + (CYGNUM_UITRON_MEMPOOLFIXED < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLFIXED_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough variable mempools */ \ + defined( CYGPKG_UITRON_MEMPOOLVAR ) && \ + (CYGNUM_UITRON_MEMPOOLVAR >= 3) && \ + (CYGNUM_UITRON_MEMPOOLVAR < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLVAR_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +// ======================================================================== + +typedef enum { + START_WAITOP = 0, + SLEEP = 0, + DELAY, + SEMGET, + FLAGWAIT, + MSGGET, + MEMFIXEDGET, + MEMVARGET, + DONE_WAITOP +} WAITOP; + +typedef enum { + START_TYPE = 0, + PLAIN = 0, + TIMED = 1, + DONE_TYPE +} WAITTYPE; + +typedef enum { + START_KILLOP = 0, + + // These are the 5 ways out of a wait that we perm + // with other circumstances: + SIGNAL = 0, // do the appropriate producer op + TIMEOUT, // wait for the timeout to fire + RELEASE, // do a rel_wai() + DELETE, // delete the object; del_xxx() + KILL, // do a ter_tsk() on the waiter + + SUSPEND_SIGNAL_RESUME, + SUSPEND_TIMEOUT_RESUME, + SUSPEND_RELEASE_RESUME, + SUSPEND_DELETE_RESUME, + SUSPEND_KILL, // resume not applicable + + SUSPEND_SIGNAL_KILL, + SUSPEND_TIMEOUT_KILL, + SUSPEND_RELEASE_KILL, + SUSPEND_DELETE_KILL, + // SUSPEND_KILL_KILL not applicable + +#if 0 + // support these later if _really_ keen. + SUSPEND_SIGNAL_DELETE_RESUME, + SUSPEND_TIMEOUT_DELETE_RESUME, + SUSPEND_RELEASE_DELETE_RESUME, + // SUSPEND_DELETE_DELETE_RESUME not applicable + // SUSPEND_KILL_DELETE_RESUME not applicable + + SUSPEND_SIGNAL_DELETE_KILL, + SUSPEND_TIMEOUT_DELETE_KILL, + SUSPEND_RELEASE_DELETE_KILL, + // SUSPEND_DELETE_DELETE_KILL, + SUSPEND_KILL_DELETE // 2nd kill not applicable +#endif + + DONE_KILLOP +} KILLOP; + +// ======================================================================== + +char * waitstrings[] = +{ "Sleep ", "Delay ", "Sema ", "Flag ", "Mbox ", "MemFix", "MemVar" }; + +char * typestrings[] = +{ " (Plain) : ", " (Timed) : " }; + +char * killstrings[] = +{ "Signal", + "Wait-for-timeout", + "Release-wait", + "Delete-object", + "Kill-task", + + "Suspend/Signal/Resume", + "Suspend/Wait-for-timeout/Resume", + "Suspend/Release-wait/Resume", + "Suspend/Delete-object/Resume", + "Suspend/Kill-task", + + "Suspend/Signal/Kill-task", + "Suspend/Wait-for-timeout/Kill-task", + "Suspend/Release-wait/Kill-task", + "Suspend/Delete-object/Kill-task", + + +}; + +// ======================================================================== + +inline int task2arg( WAITOP wait, WAITTYPE waittype, KILLOP kill ) +{ + return waittype + (wait << 1) + (kill << 8); +} + +inline void decodearg( int arg, WAITOP *pwait, WAITTYPE *pwaittype, KILLOP *pkill ) +{ + *pwaittype = (arg & 1) ? TIMED : PLAIN; + *pwait = (arg >> 1) & 0x7f; + *pkill = (arg >> 8); +} + +static char *strdog( char *p, char *q ) +{ + while ( 0 != (*p++ = *q++) ); + return p - 1; +} + +static char * +makemsg( char *z, WAITOP wait, WAITTYPE waittype, KILLOP kill ) +{ + static char buf[ 1000 ]; + char *p = buf; + p = strdog( p, z ); + p = strdog( p, waitstrings[ wait ] ); + p = strdog( p, typestrings[ waittype ] ); + p = strdog( p, killstrings[ kill ] ); + *p = 0; + return buf; +} + +// ======================================================================== + +volatile int intercom = 0; + +// ======================================================================== + +T_RTSK rtsk; + +void +do_suspend( void ) +{ + ER ercd; + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_WAI == rtsk.tskstat, "bad tskstat !TTS_WAI" ); + ercd = sus_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_WAS == rtsk.tskstat, "bad tskstat !TTS_WAS" ); +} + +void +do_resume( void ) +{ + ER ercd; + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_SUS == rtsk.tskstat, "bad tskstat !TTS_SUS" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = rsm_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "rsm_tsk bad ercd" ); + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_RDY == rtsk.tskstat, "bad tskstat !TTS_RDY" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); +} + +// ======================================================================== + +#define T1_WAIT (7) +#define T2_WAIT (5) + +#define T1_MALLOC (110) +#ifdef CYGSEM_KERNEL_MEMORY_COALESCE +#define T2_MALLOC (100) +#else +#define T2_MALLOC T1_MALLOC +#endif + +VP vptmp; +VP vp = NULL; +VP vp1 = NULL; +VP t2vp = NULL; +VP t2vp_backup = NULL; + +UINT scratch; + +T_MSG *msg = (T_MSG *)&scratch; +T_MSG *msg1; + +void +do_prep( WAITOP wait ) +{ + ER ercd; + switch ( wait ) { + case SLEEP: + case DELAY: + case SEMGET: + case FLAGWAIT: + case MSGGET: + // do nothing for all of those + break; + case MEMFIXEDGET: + // allocate all the memory in the pool; remember a couple + // for freeing as the signalling operation: + t2vp = NULL; + vp = vptmp = NULL; + do { + vp1 = vptmp; + vptmp = vp; + ercd = pget_blf( &vp, 1 ); + } while ( E_OK == ercd ); + CYG_TEST_CHECK( E_TMOUT == ercd, "get_blf bad ercd" ); + CYG_TEST_CHECK( NULL != vp, "no allocated block to free" ); + CYG_TEST_CHECK( NULL != vp1, "no allocated block to free1" ); + break; + case MEMVARGET: + // allocate all the memory in the pool; remember a couple + // for freeing as the signalling operation: + t2vp = NULL; + vp = vptmp = NULL; + do { + vp1 = vptmp; + vptmp = vp; + ercd = pget_blk( &vp, 1, T1_MALLOC ); + } while ( E_OK == ercd ); + CYG_TEST_CHECK( E_TMOUT == ercd, "get_blk bad ercd" ); + CYG_TEST_CHECK( NULL != vp, "no allocated block to free" ); + CYG_TEST_CHECK( NULL != vp1, "no allocated block to free1" ); + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } +} + +void +do_tidyup( WAITOP wait ) +{ + ER ercd; + switch ( wait ) { + case SLEEP: + case DELAY: + case SEMGET: + case MSGGET: + // do nothing for all of those + break; + case FLAGWAIT: + // clear the flag variable + ercd = clr_flg( 1, 0 ); + CYG_TEST_CHECK( E_OK == ercd, "clr_flg bad ercd, tidy vp" ); + break; + case MEMFIXEDGET: + if ( NULL != vp ) { + ercd = rel_blf( 1, vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd, tidy vp" ); + } + if ( NULL != vp1 ) { + ercd = rel_blf( 1, vp1 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd, tidy vp1" ); + } + if ( NULL != t2vp ) { + ercd = rel_blf( 1, t2vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd, tidy t2vp" ); + } + break; + case MEMVARGET: + if ( NULL != vp ) { + ercd = rel_blk( 1, vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd, tidy vp" ); + } + if ( NULL != vp1 ) { + ercd = rel_blk( 1, vp1 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd, tidy vp1" ); + } + if ( NULL != t2vp ) { + ercd = rel_blk( 1, t2vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd, tidy t2vp" ); + } + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } +} + +void +do_recreate( WAITOP wait ) +{ +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + static T_CSEM t_csem = { NULL, 0, 0 }; +#endif +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE + static T_CMBX t_cmbx = { NULL, 0 }; +#endif +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + static T_CFLG t_cflg = { NULL, 0, 0 }; +#endif +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + static T_CMPF t_cmpf = { NULL, 0, 20, 95 }; +#endif +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + static T_CMPL t_cmpl = { NULL, 0, 2000 }; +#endif + ER ercd = E_OK; + switch ( wait ) { + case SLEEP: + case DELAY: + // do nothing for all of those + break; + case SEMGET: +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + // create the semaphore + ercd = cre_sem( 1, &t_csem ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_recreate SEMGET" ); +#endif + break; + case FLAGWAIT: +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + // create the flag + ercd = cre_flg( 1, &t_cflg ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_recreate FLAGWAIT" ); +#endif + break; + case MSGGET: +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE + // create the mbox + ercd = cre_mbx( 1, &t_cmbx ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_recreate MSGGET" ); +#endif + break; + case MEMFIXEDGET: +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + // create the mempool + ercd = cre_mpf( 1, &t_cmpf ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_recreate MEMFIXEDGET" ); +#endif + break; + case MEMVARGET: +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + // create the mempool + ercd = cre_mpl( 1, &t_cmpl ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_recreate MEMVARGET" ); +#endif + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } + // this is just to use ercd to prevent warnings + CYG_TEST_CHECK( E_OK == ercd, " bad ercd" ); +} + + + +void +do_signal( WAITOP wait ) +{ + ER ercd; + switch ( wait ) { + case SLEEP: + // send a wakeup + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + break; + case DELAY: + // simply wait for task 2's delay to complete + ercd = dly_tsk( T1_WAIT ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + break; + case SEMGET: + // signal the semaphore + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + break; + case FLAGWAIT: + // set the flag bits + ercd = set_flg( 1, 0xff ); + CYG_TEST_CHECK( E_OK == ercd, "set_flg bad ercd" ); + break; + case MSGGET: + // send a message + ercd = snd_msg( 1, msg ); + CYG_TEST_CHECK( E_OK == ercd, "snd_msg bad ercd" ); + break; + case MEMFIXEDGET: + // release a couple of blocks we allocated earlier. I hope. + CYG_TEST_CHECK( NULL != vp, "no allocated block to free" ); + CYG_TEST_CHECK( NULL != vp1, "no allocated block to free1" ); + ercd = rel_blf( 1, vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + vp = NULL; + ercd = rel_blf( 1, vp1 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd1" ); + vp1 = NULL; + break; + case MEMVARGET: + // release a couple of blocks we allocated earlier. I hope. + CYG_TEST_CHECK( NULL != vp, "no allocated block to free" ); + CYG_TEST_CHECK( NULL != vp1, "no allocated block to free1" ); + ercd = rel_blk( 1, vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + vp = NULL; + ercd = rel_blk( 1, vp1 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd1" ); + vp1 = NULL; + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } +} + +void +do_delete( WAITOP wait ) +{ + ER ercd = E_OK; + switch ( wait ) { + case SLEEP: + case DELAY: + CYG_TEST_FAIL( "bad call to do_delete( SLEEP or DELAY )" ); + break; + case SEMGET: +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + // delete the semaphore + ercd = del_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_delete( SEMGET )" ); +#endif + break; + case FLAGWAIT: +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + // delete the flag + ercd = del_flg( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_delete( FLAGWAIT )" ); +#endif + break; + case MSGGET: +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE + // delete the mbox + ercd = del_mbx( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_delete( MSGGET )" ); +#endif + break; + case MEMFIXEDGET: +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + // delete the mempool + ercd = del_mpf( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_delete( MEMFIXEDGET )" ); +#endif + break; + case MEMVARGET: +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + // delete the mempool + ercd = del_mpl( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_delete( MEMVARGET )" ); +#endif + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } + // this is just to use ercd to prevent warnings + CYG_TEST_CHECK( E_OK == ercd, " bad ercd" ); +} + + + +ER +do_wait( WAITOP wait, WAITTYPE type ) +{ + switch ( wait ) { + case SLEEP: + return ( PLAIN == type ) ? slp_tsk() : tslp_tsk( T2_WAIT ); + case DELAY: + return dly_tsk( T2_WAIT ); // forget the type + case SEMGET: + return ( PLAIN == type ) ? wai_sem( 1 ) : twai_sem( 1, T2_WAIT ); + case FLAGWAIT: + return ( PLAIN == type ) ? + wai_flg( &scratch, 1, 0x55, TWF_ANDW ) : + twai_flg( &scratch, 1, 0xaa, TWF_ANDW, T2_WAIT ); + case MSGGET: + return ( PLAIN == type ) ? + rcv_msg( &msg1, 1 ) : + trcv_msg( &msg1, 1, T2_WAIT ); + case MEMFIXEDGET: + return ( PLAIN == type ) ? + get_blf( &t2vp, 1 ) : + tget_blf( &t2vp, 1, T2_WAIT ); + case MEMVARGET: + return ( PLAIN == type ) ? + get_blk( &t2vp, 1, T2_MALLOC ) : + tget_blk( &t2vp, 1, T2_MALLOC, T2_WAIT ); + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } + CYG_TEST_FAIL( "Bad wait in do_wait" ); + return E_SYS; +} + +// ======================================================================== +void task1( unsigned int arg ) +{ + ER ercd; + WAITOP wait; + WAITTYPE type; + KILLOP kill; + + CYG_TEST_INFO( "Task 1 running" ); + + ercd = chg_pri( 1, 8 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + + for ( wait = START_WAITOP; wait < DONE_WAITOP ; wait++) { + for ( type = START_TYPE; type < DONE_TYPE ; type++ ) { + for ( kill = START_KILLOP; kill < DONE_KILLOP ; kill++ ) { + + // These clauses deal with a couple of special cases: + // [doing it this way helps keep the rest of the code + // nicely general and orthogonal] + // + // 1) DELAY: dly_tsk(): when this times out, the retcode is + // E_OK rather than E_TMOUT, and it always times out. The + // "signalling" method here is just to wait yourself. So we + // do not test DELAY with TIMED type. + // + // 2) PLAIN tests with TIMEOUT kill operations: a PLAIN test + // will not time out, it'll wait forever, so waiting for it + // so to do is pointless; further, we would check for the + // wrong error code. So we do not test PLAIN tests with + // TIMOUT kill operations. + // + // 3) SLEEP or DELAY tests with DELETE operations: there is + // no synchronization to delete in those cases. + // 3a) Individual object types are tested for delete support, + // and if there is none, the test is skipped. + + if ( DELAY == wait && TIMED == type ) + continue; + + if ( PLAIN == type && + ( ( TIMEOUT == kill) || + (SUSPEND_TIMEOUT_RESUME == kill) || + (SUSPEND_TIMEOUT_KILL == kill) ) ) + continue; + + if ( ( +#ifndef CYGPKG_UITRON_SEMAS_CREATE_DELETE + (SEMGET == wait) || +#endif +#ifndef CYGPKG_UITRON_FLAGS_CREATE_DELETE + (FLAGWAIT == wait) || +#endif +#ifndef CYGPKG_UITRON_MBOXES_CREATE_DELETE + (MSGGET == wait) || +#endif +#ifndef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + (MEMFIXEDGET == wait) || +#endif +#ifndef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + (MEMVARGET == wait) || +#endif + (SLEEP == wait) || + (DELAY == wait) + ) && + ((DELETE == kill) || + (SUSPEND_DELETE_RESUME == kill) || + (SUSPEND_DELETE_KILL == kill)) ) + continue; + + + CYG_TEST_INFO( makemsg( "T1: ", wait, type, kill ) ); + + intercom = 0; + + // prepare the synchronization objects + // (actually, just empty the mempools) + do_prep( wait ); + + // start task 2 at a higher priority than myself + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 2, task2arg( wait, type, kill ) ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 2, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + // task 2 should run now, until it waits. + + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_WAI == rtsk.tskstat, "bad tskstat" ); + CYG_TEST_CHECK( 5 == rtsk.tskpri, "bad tskpri" ); + + switch ( kill ) { + case SIGNAL: + // signal the task appropriately + do_signal( wait ); + // it should now have run to completion + break; + case TIMEOUT: + // wait for the timeout to occur + ercd = dly_tsk( T1_WAIT ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + // it should now have run to completion + break; + case RELEASE: + // hit the task with a release-wait + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_wai bad ercd" ); + // it should now have run to completion + break; + case DELETE: + // delete the object appropriately + do_delete( wait ); + // it should now have run to completion + break; + case KILL: + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + case SUSPEND_SIGNAL_RESUME: + // suspend the task + do_suspend(); + // signal the task appropriately + do_signal( wait ); + // resume the task + do_resume(); + // it should now have run to completion + break; + case SUSPEND_TIMEOUT_RESUME: + // suspend the task + do_suspend(); + // wait for the timeout to occur + ercd = dly_tsk( T1_WAIT ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + // resume the task + do_resume(); + // it should now have run to completion + break; + case SUSPEND_RELEASE_RESUME: + // suspend the task + do_suspend(); + // hit the task with a release-wait + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_wai bad ercd" ); + // resume the task + do_resume(); + // it should now have run to completion + break; + case SUSPEND_DELETE_RESUME: + // suspend the task + do_suspend(); + // delete the object appropriately + do_delete( wait ); + // resume the task + do_resume(); + // it should now have run to completion + break; + case SUSPEND_KILL: + // suspend the task + do_suspend(); + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + case SUSPEND_SIGNAL_KILL: + // suspend the task + do_suspend(); + // signal the task appropriately + do_signal( wait ); + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + case SUSPEND_TIMEOUT_KILL: + // suspend the task + do_suspend(); + // wait for the timeout to occur + ercd = dly_tsk( T1_WAIT ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + case SUSPEND_RELEASE_KILL: + // suspend the task + do_suspend(); + // hit the task with a release-wait + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_wai bad ercd" ); + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + case SUSPEND_DELETE_KILL: + // suspend the task + do_suspend(); + // delete the object appropriately + do_delete( wait ); + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } + + // task 2 should be dormant now, however it got there + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_DMT == rtsk.tskstat, "bad tskstat" ); + + if ( (SUSPEND_SIGNAL_KILL == kill) && + ((MEMFIXEDGET == wait) || (MEMVARGET == wait)) ) { + // it was a killed successful memory alloc, so we have + // lost the pointer to memory allocated; there is an + // implicit storeleak problem when the task trying + // to allocate is signalled then killed. + // Recreate the pointer from an old version: + CYG_TEST_CHECK( NULL == t2vp, "t2vp WAS allocated!" ); + t2vp = t2vp_backup; + } + + switch ( kill ) { + case KILL: + case SUSPEND_KILL: + case SUSPEND_SIGNAL_KILL: + case SUSPEND_TIMEOUT_KILL: + case SUSPEND_RELEASE_KILL: + case SUSPEND_DELETE_KILL: + // if task 2 was killed, expect only one increment + CYG_TEST_CHECK( 1 == intercom, "intercom bad value !1" ); + break; + default: + // otherwise expect two increments + CYG_TEST_CHECK( 2 == intercom, "intercom bad value !2" ); + break; + } + + // tidy up or recreate the synchronization objects + if ( (DELETE == kill) || + (SUSPEND_DELETE_RESUME == kill) || + (SUSPEND_DELETE_KILL == kill) ) + do_recreate( wait ); + else + do_tidyup( wait ); + } + } + } + CYG_TEST_PASS("synchronization interaction tests"); + + // all done + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + WAITOP wait; + WAITTYPE waittype; + KILLOP kill; + + decodearg( arg, &wait, &waittype, &kill ); + +// CYG_TEST_INFO( makemsg( " 2: ", wait, waittype, kill ) ); + + intercom++; + ercd = do_wait( wait, waittype ); + intercom++; + + switch ( kill ) { + case SIGNAL: + case SUSPEND_SIGNAL_RESUME: + // we expect to have been signalled correctly + CYG_TEST_CHECK( E_OK == ercd, "T2 wait bad ercd" ); + // here we know that the op completed OK + if ( (MEMFIXEDGET == wait) || (MEMVARGET == wait) ) { + // it was a successful memory alloc of whichever type, + // so we can save away a copy of t2vp for working round an + // implicit storeleak problem when the task trying to allocate + // is signalled then killed: + CYG_TEST_CHECK( NULL != t2vp, "No t2vp allocated!" ); + t2vp_backup = t2vp; + } + break; + case TIMEOUT: + case SUSPEND_TIMEOUT_RESUME: + // we expect to have timed out - if it's a timeout op. + CYG_TEST_CHECK( E_TMOUT == ercd, "T2 timeout bad ercd, !E_TMOUT" ); + break; + case RELEASE: + case SUSPEND_RELEASE_RESUME: + // we expect to have suffered a release wait. + CYG_TEST_CHECK( E_RLWAI == ercd, "T2 release bad ercd, !E_RLWAI" ); + break; + case DELETE: + case SUSPEND_DELETE_RESUME: + // we expect to be told the object is gone + CYG_TEST_CHECK( E_DLT == ercd, "T2 release bad ercd, !E_DLT" ); + break; + case KILL: + case SUSPEND_KILL: + case SUSPEND_SIGNAL_KILL: + case SUSPEND_TIMEOUT_KILL: + case SUSPEND_RELEASE_KILL: + case SUSPEND_DELETE_KILL: + // we expect to have been killed here, ie. this won't execute! + CYG_TEST_FAIL( "Task 2 ran to completion!" ); + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF test7.c diff --git a/packages/compat/uitron/v2_0/tests/test8.c b/packages/compat/uitron/v2_0/tests/test8.c new file mode 100644 index 00000000..408ed6f0 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/test8.c @@ -0,0 +1,393 @@ +//=========================================================================== +// +// test8.c +// +// uITRON "C" test program eight +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-10-12 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +volatile int intercount = 0; +INT scratch; + +void newtask( unsigned int arg ); +void task2( unsigned int arg ); +void task3( unsigned int arg ); +void task4( unsigned int arg ); + +T_CTSK t_ctsk = { NULL, 0, (FP)&newtask, 1, CYGNUM_UITRON_STACK_SIZE }; +T_RTSK t_rtsk; + +void task1( unsigned int arg ) +{ + ER ercd; + + CYG_TEST_INFO( "Task 1 running" ); + + // change us to prio 3 for flexibility + ercd = chg_pri( 0, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE + // first, check that we can delete a task: +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_tsk( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_tsk bad ercd !E_ID" ); + ercd = del_tsk( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_tsk bad ercd !E_ID" ); + ercd = cre_tsk( -6, &t_ctsk ); + CYG_TEST_CHECK( E_ID == ercd, "cre_tsk bad ercd !E_ID" ); + ercd = cre_tsk( 99, &t_ctsk ); + CYG_TEST_CHECK( E_ID == ercd, "cre_tsk bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + ercd = cre_tsk( 2, &t_ctsk ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_tsk bad ercd !E_OBJ" ); + // try a pre-existing object - ourselves! + ercd = cre_tsk( 1, &t_ctsk ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_tsk bad ercd !E_OBJ" ); + // try deleting an active task + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 2, 22222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 2, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + // Task 2 is now ready-to-run, lower prio than us + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "del_tsk bad ercd !E_OBJ" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + // Task 2 is now sleeping + CYG_TEST_CHECK( 1 == intercount, "bad intercount !1" ); + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "del_tsk bad ercd !E_OBJ" ); + // try deleting a running task - ourselves! + ercd = del_tsk( 1 ); + CYG_TEST_CHECK( E_OBJ == ercd, "del_tsk bad ercd !E_OBJ" ); + // terminate task 2; should then be OK to delete it + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + CYG_TEST_CHECK( 1 == intercount, "bad intercount !1" ); + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_tsk bad ercd" ); + CYG_TEST_CHECK( 1 == intercount, "bad intercount !1" ); + // and check it is deleted + ercd = sta_tsk( 2, 99 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sta_tsk bad ercd !E_NOEXS" ); + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ter_tsk bad ercd !E_NOEXS" ); + ercd = chg_pri( 2, 6 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "chg_pri bad ercd !E_NOEXS" ); + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "rel_wai bad ercd !E_NOEXS" ); + ercd = sus_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sus_tsk bad ercd !E_NOEXS" ); + ercd = rsm_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "rsm_tsk bad ercd !E_NOEXS" ); + ercd = frsm_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "frsm_tsk bad ercd !E_NOEXS" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "wup_tsk bad ercd !E_NOEXS" ); + ercd = can_wup( &scratch, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "can_wup bad ercd !E_NOEXS" ); + ercd = ref_tsk( &t_rtsk, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_tsk bad ercd !E_NOEXS" ); + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "del_tsk bad ercd !E_NOEXS" ); + // recreate task2, with the same function + t_ctsk.task = (FP)&task2; + t_ctsk.itskpri = 7; + ercd = cre_tsk( 2, &t_ctsk ); + CYG_TEST_CHECK( E_OK == ercd, "cre_tsk bad ercd" ); + ercd = ref_tsk( &t_rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( 7 == t_rtsk.tskpri, "Bad tskpri in new task2 !7" ); + CYG_TEST_CHECK( TTS_DMT == t_rtsk.tskstat, + "Bad tskstat in new task2 !TTS_DMT" ); + CYG_TEST_CHECK( 1 == intercount, "bad intercount !1" ); + // now start the task and do the same lot again... + ercd = cre_tsk( 2, &t_ctsk ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_tsk bad ercd !E_OBJ" ); + // try deleting an active task + ercd = sta_tsk( 2, 22222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + // Task 2 is now ready-to-run, lower prio than us + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "del_tsk bad ercd !E_OBJ" ); + CYG_TEST_CHECK( 1 == intercount, "bad intercount !1" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 2 == intercount, "bad intercount !2" ); + // Task 2 is now sleeping + ercd = ref_tsk( &t_rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( 7 == t_rtsk.tskpri, "Bad tskpri in new task2 !7" ); + CYG_TEST_CHECK( TTS_WAI == t_rtsk.tskstat, + "Bad tskstat in new task2 !TTS_WAI" ); + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "del_tsk bad ercd !E_OBJ" ); + // up its priority + ercd = chg_pri( 2, 1 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + // awaken task 2; it will then exit-and-delete itself: + CYG_TEST_CHECK( 2 == intercount, "bad intercount !2" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "bad intercount !3" ); + // and check it is deleted + ercd = sta_tsk( 2, 99 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sta_tsk bad ercd !E_NOEXS" ); + CYG_TEST_CHECK( 3 == intercount, "bad intercount !3" ); + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ter_tsk bad ercd !E_NOEXS" ); + ercd = chg_pri( 2, 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "chg_pri bad ercd !E_NOEXS" ); + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "rel_wai bad ercd !E_NOEXS" ); + ercd = sus_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sus_tsk bad ercd !E_NOEXS" ); + ercd = rsm_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "rsm_tsk bad ercd !E_NOEXS" ); + ercd = frsm_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "frsm_tsk bad ercd !E_NOEXS" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "wup_tsk bad ercd !E_NOEXS" ); + ercd = can_wup( &scratch, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "can_wup bad ercd !E_NOEXS" ); + ercd = ref_tsk( &t_rtsk, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_tsk bad ercd !E_NOEXS" ); + CYG_TEST_CHECK( 3 == intercount, "bad intercount !3" ); + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "del_tsk bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_tsk( 2, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_tsk bad ercd !E_PAR" ); +#endif + ercd = cre_tsk( 2, NADR ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_tsk bad ercd !E_PAR" ); + t_ctsk.stksz = 0x40000000; + ercd = cre_tsk( 2, &t_ctsk ); + CYG_TEST_CHECK( E_NOMEM == ercd, "cre_tsk bad ercd !E_NOMEM" ); + t_ctsk.stksz = CYGNUM_UITRON_STACK_SIZE; + CYG_TEST_CHECK( 3 == intercount, "bad intercount !3" ); +#endif // we can test bad param error returns + + ercd = del_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_tsk bad ercd" ); + t_ctsk.task = (FP)&task4; + t_ctsk.itskpri = 9; + ercd = cre_tsk( 3, &t_ctsk ); + CYG_TEST_CHECK( E_OK == ercd, "cre_tsk bad ercd" ); + // check we can delete it again immediately + ercd = del_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_tsk bad ercd" ); + ercd = ref_tsk( &t_rtsk, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_tsk bad ercd !E_NOEXS" ); + t_ctsk.task = (FP)&newtask; + t_ctsk.itskpri = 1; + ercd = cre_tsk( 3, &t_ctsk ); + CYG_TEST_CHECK( E_OK == ercd, "cre_tsk bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "bad intercount !3" ); + ercd = sta_tsk( 3, 999 ); + CYG_TEST_CHECK( E_OK == ercd, "cre_tsk bad ercd" ); + // it should have run now, and exited + CYG_TEST_CHECK( 5 == intercount, "bad intercount !5" ); + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + // and check that it will just run again... + ercd = sta_tsk( 3, 999 ); + CYG_TEST_CHECK( E_OK == ercd, "cre_tsk bad ercd" ); + // it should have run now, and exited + CYG_TEST_CHECK( 7 == intercount, "bad intercount !7" ); + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + // all done. + + CYG_TEST_PASS("create/delete tasks"); + + // all done + CYG_TEST_EXIT( "All done" ); +#else // ! CYGPKG_UITRON_TASKS_CREATE_DELETE + CYG_TEST_NA( "Tasks do not have create/delete enabled" ); +#endif // ! CYGPKG_UITRON_TASKS_CREATE_DELETE + ext_tsk(); +} + + + +void newtask( unsigned int arg ) +{ + ER ercd; + int i; + CYG_TEST_INFO( "Newtask running" ); + CYG_TEST_CHECK( 999 == arg, "Bad arg to newtask() !999" ); + ercd = get_tid( &i ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 3 == i, "tid not 3" ); + intercount++; + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + intercount++; + // and just return +} + +void task2( unsigned int arg ) +{ + ER ercd; + int i; + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &i ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == i, "tid not 2" ); + if ( 22222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 22222" ); + + intercount++; + + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + + intercount++; + + exd_tsk(); // if we are not killed first + + intercount++; // shouldn't happen +} + +void task3( unsigned int arg ) +{ + CYG_TEST_FAIL( "How come I'm being run?" ); +} + +void task4( unsigned int arg ) +{ + CYG_TEST_FAIL( "How come I'm being run?" ); +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF test8.c diff --git a/packages/compat/uitron/v2_0/tests/test9.c b/packages/compat/uitron/v2_0/tests/test9.c new file mode 100644 index 00000000..7d62b5dd --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/test9.c @@ -0,0 +1,489 @@ +//=========================================================================== +// +// test9.c +// +// uITRON "C" test program nine +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-10-16 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough fixed memory pools */ \ + defined( CYGPKG_UITRON_MEMPOOLFIXED ) && \ + (CYGNUM_UITRON_MEMPOOLFIXED >= 3) && \ + (CYGNUM_UITRON_MEMPOOLFIXED < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLFIXED_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough variable mempools */ \ + defined( CYGPKG_UITRON_MEMPOOLVAR ) && \ + (CYGNUM_UITRON_MEMPOOLVAR >= 3) && \ + (CYGNUM_UITRON_MEMPOOLVAR < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLVAR_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +VP vp; + +T_CMPL t_cmpl = { NULL, 0, 1000 }; +T_RMPL t_rmpl; +T_CMPF t_cmpf = { NULL, 0, 10, 100 }; +T_RMPF t_rmpf; + + +void task1( unsigned int arg ) +{ + ER ercd; + int tests = 0; + + CYG_TEST_INFO( "Task 1 running" ); + + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 2, 22222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 2, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + tests++; +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_mpf( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mpf bad ercd !E_ID" ); + ercd = del_mpf( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mpf bad ercd !E_ID" ); + ercd = cre_mpf( -6, &t_cmpf ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mpf bad ercd !E_ID" ); + ercd = cre_mpf( 99, &t_cmpf ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mpf bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + // [first get a valid block from it for the freeing test later] + ercd = pget_blf( &vp, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blf bad ercd" ); + ercd = cre_mpf( 3, &t_cmpf ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_mpf bad ercd !E_OBJ" ); + // delete it so we can play + ercd = del_mpf( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); + // check it is deleted + ercd = rel_blf( 3, vp ); // vp did come from this pool + CYG_TEST_CHECK( E_NOEXS == ercd, "rel_blf bad ercd !E_NOEXS" ); + ercd = pget_blf( &vp, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blf bad ercd !E_NOEXS" ); + ercd = tget_blf( &vp, 3, 10 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "tget_blf bad ercd !E_NOEXS" ); + ercd = get_blf( &vp, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blf bad ercd !E_NOEXS" ); + ercd = ref_mpf( &t_rmpf, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_mpf bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_mpf( 3, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_mpf bad ercd !E_PAR" ); +#endif + ercd = cre_mpf( 3, NADR ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_mpf bad ercd !E_PAR" ); + t_cmpf.mpfatr = 0xfff; + ercd = cre_mpf( 3, &t_cmpf ); + CYG_TEST_CHECK( E_RSATR == ercd, "cre_mpf bad ercd !E_RSATR" ); +#endif // we can test bad param error returns + t_cmpf.mpfatr = 0; + t_cmpf.mpfcnt = 10000; + t_cmpf.blfsz = 100; + ercd = cre_mpf( 3, &t_cmpf ); + CYG_TEST_CHECK( E_NOMEM == ercd, "cre_mpf bad ercd" ); + t_cmpf.mpfcnt = 100; + t_cmpf.blfsz = 100000; + ercd = cre_mpf( 3, &t_cmpf ); + CYG_TEST_CHECK( E_NOMEM == ercd, "cre_mpf bad ercd" ); + // now create it well + t_cmpf.mpfatr = 0; + t_cmpf.mpfcnt = 10; + t_cmpf.blfsz = 100; + ercd = cre_mpf( 3, &t_cmpf ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpf bad ercd" ); + // and check we can use it + ercd = pget_blf( &vp, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blf bad ercd" ); + ercd = tget_blf( &vp, 3, 10 ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blf bad ercd" ); + ercd = get_blf( &vp, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "get_blf bad ercd" ); + ercd = rel_blf( 3, vp ); // vp did come from new pool + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + ercd = rel_blf( 3, vp ); // vp already freed + CYG_TEST_CHECK( E_PAR == ercd, "rel_blf bad ercd !E_PAR" ); + ercd = ref_mpf( &t_rmpf, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpf bad ercd" ); + + // In order to wait on the pools, we must first consume all they have: + while ( E_OK == (ercd = pget_blf( &vp, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + while ( E_OK == (ercd = tget_blf( &vp, 2, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf bad ercd !E_TMOUT" ); + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = get_blf( &vp, 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "get_blf bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = tget_blf( &vp, 2, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "tget_blf bad ercd !E_DLT" ); + // check they are deleted + ercd = get_blf( &vp, 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blf bad ercd !E_NOEXS" ); + ercd = pget_blf( &vp, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blf bad ercd !E_NOEXS" ); + + // re-create and do it again + t_cmpf.mpfcnt = 90; + t_cmpf.blfsz = 20; + ercd = cre_mpf( 1, &t_cmpf ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpf bad ercd" ); + t_cmpf.mpfcnt = 5; + t_cmpf.blfsz = 200; + ercd = cre_mpf( 2, &t_cmpf ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpf bad ercd" ); + + // In order to wait on the pools, we must first consume all they have: + while ( E_OK == (ercd = pget_blf( &vp, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + while ( E_OK == (ercd = tget_blf( &vp, 2, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf bad ercd !E_TMOUT" ); + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = get_blf( &vp, 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "get_blf bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = tget_blf( &vp, 2, 10 ); + CYG_TEST_CHECK( E_DLT == ercd, "tget_blf bad ercd !E_DLT" ); + // check they are deleted + ercd = tget_blf( &vp, 1, 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blf bad ercd !E_NOEXS" ); + ercd = get_blf( &vp, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blf bad ercd !E_NOEXS" ); + + CYG_TEST_PASS("create/delete fixed mempools"); +#endif // CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + tests++; +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_mpl( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mpl bad ercd !E_ID" ); + ercd = del_mpl( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mpl bad ercd !E_ID" ); + ercd = cre_mpl( -6, &t_cmpl ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mpl bad ercd !E_ID" ); + ercd = cre_mpl( 99, &t_cmpl ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mpl bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + // [first get a valid block from it for the freeing test later] + ercd = pget_blk( &vp, 3, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blk bad ercd" ); + ercd = cre_mpl( 3, &t_cmpl ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_mpl bad ercd !E_OBJ" ); + // delete it so we can play + ercd = del_mpl( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); + // check it is deleted + ercd = rel_blk( 3, vp ); // vp did come from this pool + CYG_TEST_CHECK( E_NOEXS == ercd, "rel_blk bad ercd !E_NOEXS" ); + ercd = pget_blk( &vp, 3, 100 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blk bad ercd !E_NOEXS" ); + ercd = tget_blk( &vp, 3, 100, 10 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "tget_blk bad ercd !E_NOEXS" ); + ercd = get_blk( &vp, 3, 100 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blk bad ercd !E_NOEXS" ); + ercd = ref_mpl( &t_rmpl, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_mpl bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_mpl( 3, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_mpl bad ercd !E_PAR" ); +#endif + ercd = cre_mpl( 3, NADR ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_mpl bad ercd !E_PAR" ); + t_cmpl.mplatr = 0xfff; + ercd = cre_mpl( 3, &t_cmpl ); + CYG_TEST_CHECK( E_RSATR == ercd, "cre_mpl bad ercd !E_RSATR" ); +#endif // we can test bad param error returns + t_cmpl.mplatr = 0; + t_cmpl.mplsz = 100000000; + ercd = cre_mpl( 3, &t_cmpl ); + CYG_TEST_CHECK( E_NOMEM == ercd, "cre_mpl bad ercd" ); + // now create it well + t_cmpl.mplatr = 0; + t_cmpl.mplsz = 1000; + ercd = cre_mpl( 3, &t_cmpl ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpl bad ercd" ); + // and check we can use it + ercd = pget_blk( &vp, 3, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blk bad ercd" ); + ercd = pget_blk( &vp, 3, 100000000 ); // way too large + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + ercd = tget_blk( &vp, 3, 100, 10 ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blk bad ercd" ); + ercd = get_blk( &vp, 3, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "get_blk bad ercd" ); + ercd = rel_blk( 3, vp ); // vp did come from new pool + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + ercd = rel_blk( 3, vp ); // vp already freed + CYG_TEST_CHECK( E_PAR == ercd, "rel_blk bad ercd !E_PAR" ); + ercd = ref_mpl( &t_rmpl, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpl bad ercd" ); + + // In order to wait on the pools, we must first consume all they have: + while ( E_OK == (ercd = pget_blk( &vp, 1, 100 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + while ( E_OK == (ercd = tget_blk( &vp, 2, 100, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk bad ercd !E_TMOUT" ); + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = get_blk( &vp, 1, 200 ); + CYG_TEST_CHECK( E_DLT == ercd, "get_blk bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = tget_blk( &vp, 2, 100, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "tget_blk bad ercd !E_DLT" ); + // check they are deleted + ercd = get_blk( &vp, 1, 200 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blk bad ercd !E_NOEXS" ); + ercd = pget_blk( &vp, 2, 20 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blk bad ercd !E_NOEXS" ); + + // re-create and do it again + ercd = cre_mpl( 1, &t_cmpl ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpl bad ercd" ); + ercd = cre_mpl( 2, &t_cmpl ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpl bad ercd" ); + + // In order to wait on the pools, we must first consume all they have: + while ( E_OK == (ercd = pget_blk( &vp, 1, 20 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + while ( E_OK == (ercd = tget_blk( &vp, 2, 400, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk bad ercd !E_TMOUT" ); + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = get_blk( &vp, 1, 200 ); + CYG_TEST_CHECK( E_DLT == ercd, "get_blk bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = tget_blk( &vp, 2, 500, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "tget_blk bad ercd !E_DLT" ); + // check they are deleted + ercd = tget_blk( &vp, 1, 200, 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blk bad ercd !E_NOEXS" ); + ercd = get_blk( &vp, 2, 20 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blk bad ercd !E_NOEXS" ); + + CYG_TEST_PASS("create/delete variable mempools"); +#endif // CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + ercd = dly_tsk( 5 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + // all done + if ( 0 == tests ) { + CYG_TEST_NA( "No objects have create/delete enabled" ); + } + else { + CYG_TEST_EXIT( "All done" ); + } + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + int i; + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &i ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == i, "tid not 2" ); + if ( 22222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 22222" ); + + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + ercd = del_mpf( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpf( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpf( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpf( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); +#endif // CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + ercd = del_mpl( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpl( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpl( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpl( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); +#endif // CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + + // we expect task2 to be killed here + CYG_TEST_FAIL( "Task 2 ran to completion!" ); +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF test9.c diff --git a/packages/compat/uitron/v2_0/tests/testcx2.cxx b/packages/compat/uitron/v2_0/tests/testcx2.cxx new file mode 100644 index 00000000..f528e621 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/testcx2.cxx @@ -0,0 +1,937 @@ +//=========================================================================== +// +// testcx2.cxx +// +// uITRON "C++" test program two +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough flag objects */ \ + defined( CYGPKG_UITRON_FLAGS ) && \ + (CYGNUM_UITRON_FLAGS >= 3) && \ + (CYGNUM_UITRON_FLAGS < 90) && \ + ( !defined(CYGPKG_UITRON_FLAGS_CREATE_DELETE) || \ + CYGNUM_UITRON_FLAGS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough message boxes */ \ + defined( CYGPKG_UITRON_MBOXES ) && \ + (CYGNUM_UITRON_MBOXES >= 3) && \ + (CYGNUM_UITRON_MBOXES < 90) && \ + ( !defined(CYGPKG_UITRON_MBOXES_CREATE_DELETE) || \ + CYGNUM_UITRON_MBOXES_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough fixed memory pools */ \ + defined( CYGPKG_UITRON_MEMPOOLFIXED ) && \ + (CYGNUM_UITRON_MEMPOOLFIXED >= 3) && \ + (CYGNUM_UITRON_MEMPOOLFIXED < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLFIXED_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough variable mempools */ \ + defined( CYGPKG_UITRON_MEMPOOLVAR ) && \ + (CYGNUM_UITRON_MEMPOOLVAR >= 3) && \ + (CYGNUM_UITRON_MEMPOOLVAR < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLVAR_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +int intercom = 0; +int intercount = 0; +INT scratch = 0; + +extern "C" { + void task1( unsigned int arg ); + void task2( unsigned int arg ); + void task3( unsigned int arg ); + void task4( unsigned int arg ); +} + +void task1( unsigned int arg ) +{ + ER ercd; + + T_RSEM sem_info; + T_RFLG flg_info; + T_RMBX mbx_info; + T_RMPF mpf_info; + T_RMPL mpl_info; + UINT flagptn; + static char foo[] = "Test message"; + T_MSG *msgptr = (T_MSG *)foo; + T_MSG *rxptr = NULL; + VP blfptr = (VP)foo; + VP blkptr = (VP)foo; + + int delay = 10; + if (cyg_test_is_simulator) + delay = 3; + + CYG_TEST_INFO( "Task 1 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 1 == scratch, "tid not 1" ); + + // start a lower prio task to interact with + intercom = 1; + ercd = sta_tsk( 2, 222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + // Semaphores; all the illegal argument combinations first + CYG_TEST_INFO( "Testing semaphore ops" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = sig_sem( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "sig_sem bad ercd !E_ID" ); + ercd = sig_sem( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "sig_sem bad ercd !E_ID" ); + ercd = wai_sem( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "wai_sem bad ercd !E_ID" ); + ercd = wai_sem( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "wai_sem bad ercd !E_ID" ); + ercd = preq_sem( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "preq_sem bad ercd !E_ID" ); + ercd = preq_sem( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "preq_sem bad ercd !E_ID" ); + ercd = twai_sem( -6, delay ); + CYG_TEST_CHECK( E_ID == ercd, "twai_sem bad ercd !E_ID" ); + ercd = twai_sem( 99, delay ); + CYG_TEST_CHECK( E_ID == ercd, "twai_sem bad ercd !E_ID" ); + ercd = twai_sem( 2, -999 ); + CYG_TEST_CHECK( E_PAR == ercd, "twai_sem bad ercd !E_PAR" ); + ercd = ref_sem( &sem_info, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_sem bad ercd !E_ID" ); + ercd = ref_sem( &sem_info, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_sem bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_sem( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_sem bad ercd !E_PAR" ); +#endif + CYG_TEST_PASS( "bad calls: sig_sem, [t]wai_sem, preq_sem, ref_sem" ); +#endif // we can test bad param error returns + + // check the waitable functions versus dispatch disable + ercd = preq_sem( 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "preq_sem bad ercd !E_TMOUT" ); + ercd = twai_sem( 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem bad ercd !E_TMOUT" ); + ercd = twai_sem( 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem(POL) bad ercd !E_TMOUT" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = wai_sem( 2 ); + CYG_TEST_CHECK( E_CTX == ercd, "wai_sem bad ercd !E_CTX" ); + ercd = twai_sem( 2, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "twai_sem bad ercd !E_CTX" ); + ercd = twai_sem( 2, TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "twai_sem(FEVR) bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = twai_sem( 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem(POL) bad ercd !E_TMOUT" ); + ercd = preq_sem( 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "preq_sem bad ercd !E_TMOUT" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = preq_sem( 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "preq_sem bad ercd !E_TMOUT" ); + ercd = twai_sem( 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem bad ercd !E_TMOUT" ); + ercd = twai_sem( 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem(POL) bad ercd !E_TMOUT" ); + CYG_TEST_PASS( "bad calls: wai_sem, twai_sem with dis_dsp" ); + + // check ref_sem with various states + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 1 == sem_info.semcnt, "semcnt should be 1" ); + ercd = preq_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 2 == sem_info.semcnt, "semcnt should be 2" ); + ercd = wai_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 1 == sem_info.semcnt, "semcnt should be 1" ); + ercd = twai_sem( 2, delay ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + intercom = 0; + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + intercom = 1; + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 != sem_info.wtsk, "sem.wtsk should be non0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be non0" ); +#if 1 + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); +#else // old, non-uITRON semantics + CYG_TEST_CHECK( 1 == sem_info.semcnt, "semcnt should be 1" ); +#endif + ercd = dly_tsk( delay ); // let task 2 pick up the signal + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_sem( &sem_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + CYG_TEST_CHECK( 0 == sem_info.wtsk, "sem.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == sem_info.semcnt, "semcnt should be 0" ); + CYG_TEST_PASS( "good calls: sig_sem, [t]wai,preq_sem with ref_sem" ); + + // Flags; all the illegal argument combinations first + CYG_TEST_INFO( "Testing flag ops" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = set_flg( -6, 1 ); + CYG_TEST_CHECK( E_ID == ercd, "set_flg bad ercd !E_ID" ); + ercd = set_flg( 99, 1 ); + CYG_TEST_CHECK( E_ID == ercd, "set_flg bad ercd !E_ID" ); + ercd = clr_flg( -6, 1 ); + CYG_TEST_CHECK( E_ID == ercd, "clr_flg bad ercd !E_ID" ); + ercd = clr_flg( 99, 1 ); + CYG_TEST_CHECK( E_ID == ercd, "sig_flg bad ercd !E_ID" ); + ercd = wai_flg( &flagptn, -6, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_ID == ercd, "wai_flg bad ercd !E_ID" ); + ercd = wai_flg( &flagptn, 99, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_ID == ercd, "wai_flg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = wai_flg( NULL, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_PAR == ercd, "wai_flg bad ercd !E_PAR" ); +#endif + ercd = wai_flg( &flagptn, 2, 7, 34657 ); + CYG_TEST_CHECK( E_PAR == ercd, "wai_flg bad ercd !E_PAR" ); + ercd = wai_flg( &flagptn, 2, 0, TWF_ANDW ); + CYG_TEST_CHECK( E_PAR == ercd, "wai_flg bad ercd !E_PAR" ); + ercd = pol_flg( &flagptn, -6, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_ID == ercd, "pol_flg bad ercd !E_ID" ); + ercd = pol_flg( &flagptn, 99, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_ID == ercd, "pol_flg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = pol_flg( NULL, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_PAR == ercd, "pol_flg bad ercd !E_PAR" ); +#endif + ercd = pol_flg( &flagptn, 2, 7, 34657 ); + CYG_TEST_CHECK( E_PAR == ercd, "pol_flg bad ercd !E_PAR" ); + ercd = pol_flg( &flagptn, 2, 0, TWF_ANDW ); + CYG_TEST_CHECK( E_PAR == ercd, "pol_flg bad ercd !E_PAR" ); + ercd = twai_flg( &flagptn, -6, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_ID == ercd, "twai_flg bad ercd !E_ID" ); + ercd = twai_flg( &flagptn, 99, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_ID == ercd, "twai_flg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = twai_flg( NULL, 2, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "twai_flg bad ercd !E_PAR" ); +#endif + ercd = twai_flg( &flagptn, 2, 7, 34657, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "twai_flg bad ercd !E_PAR" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, -999 ); + CYG_TEST_CHECK( E_PAR == ercd, "twai_flg bad ercd !E_PAR" ); + ercd = twai_flg( &flagptn, 2, 0, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "twai_flg bad ercd !E_PAR" ); + ercd = ref_flg( &flg_info, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_flg bad ercd !E_ID" ); + ercd = ref_flg( &flg_info, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_flg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_flg( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_flg bad ercd !E_PAR" ); +#endif + CYG_TEST_PASS( "bad calls: set_flg, clr_flg, [t]wai,pol_flg, ref_flg" ); +#endif // we can test bad param error returns + + // check the waitable functions versus dispatch disable + ercd = pol_flg( &flagptn, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pol_flg bad ercd !E_TMOUT" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg bad ercd !E_TMOUT" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg(POL) bad ercd !E_TMOUT" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = wai_flg( &flagptn, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_CTX == ercd, "wai_flg bad ercd !E_CTX" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "twai_flg bad ercd !E_CTX" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "twai_flg(FEVR) bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg(POL) bad ercd !E_TMOUT" ); + ercd = pol_flg( &flagptn, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pol_flg bad ercd !E_TMOUT" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = pol_flg( &flagptn, 2, 7, TWF_ANDW ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pol_flg bad ercd !E_TMOUT" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg bad ercd !E_TMOUT" ); + ercd = twai_flg( &flagptn, 2, 7, TWF_ANDW, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg(POL) bad ercd !E_TMOUT" ); + CYG_TEST_PASS( "bad calls: wai_flg, twai_flg with dis_dsp" ); + + // check ref_flg with various states + ercd = ref_flg( &flg_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 == flg_info.wtsk, "flg.wtsk should be non0" ); + CYG_TEST_CHECK( 0 == flg_info.flgptn, "flgptn should be 0" ); + intercom = 0; + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + intercom = 1; + ercd = ref_flg( &flg_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 != flg_info.wtsk, "flg.wtsk should be non0" ); + CYG_TEST_CHECK( 0 == flg_info.flgptn, "flgptn should be 0" ); + ercd = set_flg( 2, 0x5555 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_flg bad ercd" ); + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_flg( &flg_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 != flg_info.wtsk, "flg.wtsk should be non0" ); + CYG_TEST_CHECK( 0x5555 == flg_info.flgptn, "flgptn should be 0x5555" ); + ercd = clr_flg( 2, 0xF0F0 ); + CYG_TEST_CHECK( E_OK == ercd, "clr_flg bad ercd" ); + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_flg( &flg_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 != flg_info.wtsk, "flg.wtsk should be non0" ); + CYG_TEST_CHECK( 0x5050 == flg_info.flgptn, "flgptn should be 0x5050" ); + ercd = set_flg( 2, 0xFFFF ); + CYG_TEST_CHECK( E_OK == ercd, "sig_flg bad ercd" ); + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_flg( &flg_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 == flg_info.wtsk, "flg.wtsk should be 0" ); + CYG_TEST_CHECK( 0xFFFF == flg_info.flgptn, "flgptn should be 0xFFFF" ); + CYG_TEST_PASS( "good calls: clr_flg, set_flg, wai_flg with ref_flg" ); + + // Mailboxes; all the illegal argument combinations first + CYG_TEST_INFO( "Testing mailbox ops" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = snd_msg( -6, msgptr ); + CYG_TEST_CHECK( E_ID == ercd, "snd_msg bad ercd !E_ID" ); + ercd = snd_msg( 99, msgptr ); + CYG_TEST_CHECK( E_ID == ercd, "snd_msg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = snd_msg( 2, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "snd_msg bad ercd !E_PAR" ); +#endif + ercd = rcv_msg( &rxptr, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "rcv_msg bad ercd !E_ID" ); + ercd = rcv_msg( &rxptr, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "rcv_msg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = rcv_msg( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "rcv_msg bad ercd !E_PAR" ); +#endif + ercd = prcv_msg( &rxptr, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "prcv_msg bad ercd !E_ID" ); + ercd = prcv_msg( &rxptr, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "prcv_msg bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = prcv_msg( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "prcv_msg bad ercd !E_PAR" ); +#endif + ercd = trcv_msg( &rxptr, -6, delay ); + CYG_TEST_CHECK( E_ID == ercd, "trcv_msg bad ercd !E_ID" ); + ercd = trcv_msg( &rxptr, 99, delay ); + CYG_TEST_CHECK( E_ID == ercd, "trcv_msg bad ercd !E_ID" ); + ercd = trcv_msg( &rxptr, 2, -999 ); + CYG_TEST_CHECK( E_PAR == ercd, "trcv_msg bad ercd !E_PAR" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = trcv_msg( NULL, 2, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "trcv_msg bad ercd !E_PAR" ); +#endif + ercd = ref_mbx( &mbx_info, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mbx bad ercd !E_ID" ); + ercd = ref_mbx( &mbx_info, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mbx bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_mbx( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_mbx bad ercd !E_PAR" ); +#endif + CYG_TEST_PASS( "bad calls: snd_msg, [pt]rcv_msg, ref_mbx" ); +#endif // we can test bad param error returns + + // check the waitable functions versus dispatch disable + ercd = prcv_msg( &rxptr, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "prcv_msg bad ercd !E_TMOUT" ); + ercd = trcv_msg( &rxptr, 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg bad ercd !E_TMOUT" ); + ercd = trcv_msg( &rxptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg(POL) bad ercd !E_TMOUT" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rcv_msg( &rxptr, 2 ); + CYG_TEST_CHECK( E_CTX == ercd, "rcv_msg bad ercd !E_CTX" ); + ercd = trcv_msg( &rxptr, 2, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "trcv_msg bad ercd !E_CTX" ); + ercd = trcv_msg( &rxptr, 2, TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "trcv_msg(FEVR) bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = trcv_msg( &rxptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg(POL) bad ercd !E_TMOUT" ); + ercd = prcv_msg( &rxptr, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "prcv_msg bad ercd !E_TMOUT" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = prcv_msg( &rxptr, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "prcv_msg bad ercd !E_TMOUT" ); + ercd = trcv_msg( &rxptr, 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg bad ercd !E_TMOUT" ); + ercd = trcv_msg( &rxptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg(POL) bad ercd !E_TMOUT" ); + CYG_TEST_PASS( "bad calls: rcv_msg, trcv_msg with dis_dsp" ); + + // check ref_mbx with various states + ercd = ref_mbx( &mbx_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mbx bad ercd" ); + CYG_TEST_CHECK( 0 == mbx_info.wtsk, "mbx.wtsk should be 0" ); + CYG_TEST_CHECK( NADR == mbx_info.pk_msg, "mbx peek should be NADR" ); + intercom = 0; + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + intercom = 1; + ercd = ref_mbx( &mbx_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mbx bad ercd" ); + CYG_TEST_CHECK( 0 != mbx_info.wtsk, "mbx.wtsk should be non0" ); + CYG_TEST_CHECK( NADR == mbx_info.pk_msg, "mbx peek should be NADR" ); + ercd = snd_msg( 2, msgptr ); + CYG_TEST_CHECK( E_OK == ercd, "snd_msg bad ercd" ); + ercd = ref_mbx( &mbx_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mbx bad ercd" ); + CYG_TEST_CHECK( 0 == mbx_info.wtsk, "mbx.wtsk should be 0" ); +#if 1 + CYG_TEST_CHECK( NADR == mbx_info.pk_msg, "mbx peek should be NADR" ); +#else // old, non-uITRON semantics + CYG_TEST_CHECK( msgptr == mbx_info.pk_msg, "mbx peek should be msgptr" ); +#endif + ercd = dly_tsk( delay ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_mbx( &mbx_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mbx bad ercd" ); + CYG_TEST_CHECK( 0 == mbx_info.wtsk, "mbx.wtsk should be 0" ); + CYG_TEST_CHECK( NADR == mbx_info.pk_msg, "mbx peek should be NADR" ); + // fill the message box, expect E_QOVR + for ( scratch = 0 ; scratch < 100 ; scratch++ ) { + if ( E_OK != ( ercd = snd_msg( 2, msgptr ) ) ) + break; + } + CYG_TEST_CHECK( (100 == scratch) || (E_QOVR == ercd), + "snd_msg bad ercd !E_QOVR/E_OK" ); + // empty the message box, expect the right number and E_TMOUT + for ( ; 1 ; scratch-- ) { + if ( E_OK != ( ercd = prcv_msg( &rxptr, 2 ) ) ) + break; + } + CYG_TEST_CHECK( 0 == scratch, "rcv_msg count bad scratch!=0" ); + CYG_TEST_CHECK( E_TMOUT == ercd, "rcv_msg bad ercd !E_TMOUT" ); + + CYG_TEST_PASS( "good calls: rcv_msg, snd_msg with ref_msg" ); + + // Fixed block memory pools: all the illegal argument combinations first + CYG_TEST_INFO( "Testing fixed block memory ops" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rel_blf( -6, blfptr ); + CYG_TEST_CHECK( E_ID == ercd, "rel_blf bad ercd !E_ID" ); + ercd = rel_blf( 99, blfptr ); + CYG_TEST_CHECK( E_ID == ercd, "rel_blf bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = rel_blf( 2, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "rel_blf bad ercd !E_PAR" ); +#endif +#endif // we can test bad param error returns + ercd = rel_blf( 2, blfptr ); // it did not come from a mpf + CYG_TEST_CHECK( E_PAR == ercd, "rel_blf bad ercd !E_PAR" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blf( &blfptr, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "get_blf bad ercd !E_ID" ); + ercd = get_blf( &blfptr, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "get_blf bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = get_blf( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "get_blf bad ercd !E_PAR" ); +#endif + ercd = pget_blf( &blfptr, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "pget_blf bad ercd !E_ID" ); + ercd = pget_blf( &blfptr, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "pget_blf bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = pget_blf( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "pget_blf bad ercd !E_PAR" ); +#endif + ercd = tget_blf( &blfptr, -6, delay ); + CYG_TEST_CHECK( E_ID == ercd, "tget_blf bad ercd !E_ID" ); + ercd = tget_blf( &blfptr, 99, delay ); + CYG_TEST_CHECK( E_ID == ercd, "tget_blf bad ercd !E_ID" ); + ercd = tget_blf( &blfptr, 2, -999 ); + CYG_TEST_CHECK( E_PAR == ercd, "tget_blf bad ercd !E_PAR" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = tget_blf( NULL, 2, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "tget_blf bad ercd !E_PAR" ); +#endif + ercd = ref_mpf( &mpf_info, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mpf bad ercd !E_ID" ); + ercd = ref_mpf( &mpf_info, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mpf bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_mpf( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_mpf bad ercd !E_PAR" ); +#endif + CYG_TEST_PASS( "bad calls: rel_blf, [pt]get_blf, ref_mpf " ); +#endif // we can test bad param error returns + + // check the waitable functions versus dispatch disable + ercd = pget_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blf bad ercd" ); + ercd = rel_blf( 2, blfptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blf bad ercd" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = rel_blf( 2, blfptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_CTX == ercd, "get_blf bad ercd !E_CTX" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blf bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = pget_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blf bad ercd" ); + ercd = rel_blf( 2, blfptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blf bad ercd" ); + ercd = rel_blf( 2, blfptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + // consume the whole thing then do it again, expecting E_TMOUT + while ( E_OK == (ercd = pget_blf( &blfptr, 2 ) ) ) + continue; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + ercd = pget_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf bad ercd !E_TMOUT" ); + ercd = tget_blf( &blfptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf(POL) bad ercd !E_TMOUT" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_CTX == ercd, "get_blf bad ercd !E_CTX" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blf bad ercd !E_CTX" ); + ercd = tget_blf( &blfptr, 2, TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blf(FEVR) bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = tget_blf( &blfptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf(POL) bad ercd !E_TMOUT" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = pget_blf( &blfptr, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + ercd = tget_blf( &blfptr, 2, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + ercd = tget_blf( &blfptr, 2, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf(POL) bad ercd !E_TMOUT" ); + CYG_TEST_PASS( "bad calls: rel_blf, [pt]get_blf with ena_dsp" ); + + // check ref_mpf with various states + ercd = ref_mpf( &mpf_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpf bad ercd" ); + CYG_TEST_CHECK( 0 == mpf_info.wtsk, "mpf.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == mpf_info.frbcnt, "mpf.frbcnt should be 0" ); + intercom = 0; + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + intercom = 1; + ercd = ref_mpf( &mpf_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpf bad ercd" ); + CYG_TEST_CHECK( 0 != mpf_info.wtsk, "mpf.wtsk should be non0" ); + CYG_TEST_CHECK( 0 == mpf_info.frbcnt, "mpf.frbcnt should be 0" ); + ercd = rel_blf( 2, blfptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + ercd = ref_mpf( &mpf_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpf bad ercd" ); + CYG_TEST_CHECK( 0 == mpf_info.wtsk, "mpf.wtsk should be 0" ); +#if 1 + CYG_TEST_CHECK( 0 == mpf_info.frbcnt, "mpf.frbcnt should be 0" ); +#else // old, non-uITRON semantics + CYG_TEST_CHECK( 0 != mpf_info.frbcnt, "mpf.frbcnt should be non0" ); +#endif + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_mpf( &mpf_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpf bad ercd" ); + CYG_TEST_CHECK( 0 == mpf_info.wtsk, "mpf.wtsk should be 0" ); + CYG_TEST_CHECK( 0 == mpf_info.frbcnt, "mpf.frbcnt should be 0" ); + CYG_TEST_PASS( "good calls: rel_blf, get_blf with ref_mpf" ); + + // Variable block memory pools; illegal arguments + CYG_TEST_INFO( "Testing variable block memory ops" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rel_blk( -6, blkptr ); + CYG_TEST_CHECK( E_ID == ercd, "rel_blk bad ercd !E_ID" ); + ercd = rel_blk( 99, blkptr ); + CYG_TEST_CHECK( E_ID == ercd, "rel_blk bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = rel_blk( 2, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "rel_blk bad ercd !E_PAR" ); +#endif +#endif // we can test bad param error returns + ercd = rel_blk( 2, blkptr ); // it did not come from a mpl + CYG_TEST_CHECK( E_PAR == ercd, "rel_blk bad ercd !E_PAR" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blk( &blkptr, -6, 100 ); + CYG_TEST_CHECK( E_ID == ercd, "get_blk bad ercd !E_ID" ); + ercd = get_blk( &blkptr, 99, 100 ); + CYG_TEST_CHECK( E_ID == ercd, "get_blk bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = get_blk( NULL, 2, 100 ); + CYG_TEST_CHECK( E_PAR == ercd, "get_blk bad ercd !E_PAR" ); +#endif + ercd = pget_blk( &blkptr, -6, 100 ); + CYG_TEST_CHECK( E_ID == ercd, "pget_blk bad ercd !E_ID" ); + ercd = pget_blk( &blkptr, 99, 100 ); + CYG_TEST_CHECK( E_ID == ercd, "pget_blk bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = pget_blk( NULL, 2, 100 ); + CYG_TEST_CHECK( E_PAR == ercd, "pget_blk bad ercd !E_PAR" ); +#endif + ercd = tget_blk( &blkptr, -6, 100, delay ); + CYG_TEST_CHECK( E_ID == ercd, "tget_blk bad ercd !E_ID" ); + ercd = tget_blk( &blkptr, 99, 100, delay ); + CYG_TEST_CHECK( E_ID == ercd, "tget_blk bad ercd !E_ID" ); + ercd = tget_blk( &blkptr, 2, 100, -999 ); + CYG_TEST_CHECK( E_PAR == ercd, "tget_blk bad ercd !E_PAR" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = tget_blk( NULL, 2, 100, delay ); + CYG_TEST_CHECK( E_PAR == ercd, "tget_blk bad ercd !E_PAR" ); +#endif + ercd = ref_mpl( &mpl_info, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mpl bad ercd !E_ID" ); + ercd = ref_mpl( &mpl_info, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_mpl bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_mpl( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_mpl bad ercd !E_PAR" ); +#endif + CYG_TEST_PASS( "bad calls: rel_blk, [pt]get_blk, ref_mpl " ); +#endif // we can test bad param error returns + + // check the waitable functions versus dispatch disable + ercd = pget_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blk bad ercd" ); + ercd = rel_blk( 2, blkptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blk bad ercd" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = rel_blk( 2, blkptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_CTX == ercd, "get_blk bad ercd !E_CTX" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blk bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = pget_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blk bad ercd" ); + ercd = rel_blk( 2, blkptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blk bad ercd" ); + ercd = rel_blk( 2, blkptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + // consume the whole thing then do it again, expecting E_TMOUT + while ( E_OK == (ercd = pget_blk( &blkptr, 2, 100 ) ) ) + continue; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + ercd = pget_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk bad ercd !E_TMOUT" ); + ercd = tget_blk( &blkptr, 2, 100, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk(POL) bad ercd !E_TMOUT" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = get_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_CTX == ercd, "get_blk bad ercd !E_CTX" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blk bad ercd !E_CTX" ); + ercd = tget_blk( &blkptr, 2, 100, TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "tget_blk(FEVR) bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = tget_blk( &blkptr, 2, 100, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk(POL) bad ercd !E_TMOUT" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = pget_blk( &blkptr, 2, 100 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + ercd = tget_blk( &blkptr, 2, 100, delay ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + ercd = tget_blk( &blkptr, 2, 100, TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk(POL) bad ercd !E_TMOUT" ); + CYG_TEST_PASS( "bad calls: rel_blk, [pt]get_blk with ena_dsp" ); + + // check ref_mpl with various states + ercd = ref_mpl( &mpl_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpl bad ercd" ); + CYG_TEST_CHECK( 0 == mpl_info.wtsk, "mpl.wtsk should be 0" ); + CYG_TEST_CHECK( mpl_info.maxsz <= mpl_info.frsz, + "mpl.maxsz not < mpl.frsz" ); + intercom = 0; + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + intercom = 1; + ercd = ref_mpl( &mpl_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpl bad ercd" ); + CYG_TEST_CHECK( 0 != mpl_info.wtsk, "mpl.wtsk should be non0" ); + ercd = rel_blk( 2, blkptr ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + ercd = ref_mpl( &mpl_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpl bad ercd" ); + CYG_TEST_CHECK( 0 == mpl_info.wtsk, "mpl.wtsk should be 0" ); + ercd = dly_tsk( delay ); // let task 2 start waiting + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_mpl( &mpl_info, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpl bad ercd" ); + CYG_TEST_CHECK( 0 == mpl_info.wtsk, "mpl.wtsk should be 0" ); + CYG_TEST_PASS( "good calls: rel_blk, get_blk with ref_mpl" ); + + // all done + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + T_MSG *msgp = NULL; + UINT flgval = 0; + VP blfp = NULL; + VP blkp = NULL; + + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == scratch, "tid not 2" ); + if ( 222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 222" ); + + while ( intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + } + ercd = wai_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + while ( intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + } + ercd = wai_flg( &flgval, 2, 99, TWF_ANDW ); + CYG_TEST_CHECK( E_OK == ercd, "wai_flg bad ercd" ); + CYG_TEST_CHECK( 99 == (99 & flgval), "flg value no good" ); + while ( intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + } + ercd = rcv_msg( &msgp, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "rcv_msg bad ercd" ); + CYG_TEST_CHECK( NULL != msgp, "no msg received" ); + CYG_TEST_CHECK( NADR != msgp, "no msg received" ); + while ( intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + } + ercd = get_blf( &blfp, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "get_blf bad ercd" ); + CYG_TEST_CHECK( NULL != blfp, "no blf allocated" ); + CYG_TEST_CHECK( NADR != blfp, "no blf allocated" ); + while ( intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + } + ercd = get_blk( &blkp, 2, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "get_blk bad ercd" ); + CYG_TEST_CHECK( NULL != blkp, "no blk allocated" ); + CYG_TEST_CHECK( NADR != blkp, "no blk allocated" ); + + ext_tsk(); + CYG_TEST_FAIL( "Task 2 failed to exit" ); +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK " +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF testcx2.cxx diff --git a/packages/compat/uitron/v2_0/tests/testcx3.cxx b/packages/compat/uitron/v2_0/tests/testcx3.cxx new file mode 100644 index 00000000..d8d69781 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/testcx3.cxx @@ -0,0 +1,262 @@ +//=========================================================================== +// +// testcx3.cxx +// +// uITRON "C++" test program three +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +int t2done = 0; +int t3done = 0; +int t4done = 0; + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +extern "C" { + void task1( unsigned int arg ); + void task2( unsigned int arg ); + void task3( unsigned int arg ); + void task4( unsigned int arg ); +} + +void task1( unsigned int arg ) +{ + ER ercd; + INT scratch; + + CYG_TEST_INFO( "Task 1 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 1 == scratch, "tid not 1" ); + + // start lower prio tasks to interact with + ercd = sta_tsk( 2, 222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = sta_tsk( 3, 333 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = sta_tsk( 4, 444 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + + // now start the test + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + CYG_TEST_INFO( "T1 awoken" ); + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + CYG_TEST_INFO( "T1 signalled" ); + + // let the others complete, so we get the status back + ercd = dly_tsk( 50 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + CYG_TEST_CHECK( t2done, "t2 not done" ); + CYG_TEST_CHECK( t3done, "t3 not done" ); + CYG_TEST_CHECK( t4done, "t4 not done" ); + + CYG_TEST_PASS( "Immediate-dispatch producer/consumer test OK" ); + + // all done + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + INT scratch; + + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == scratch, "tid not 2" ); + if ( 222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 222" ); + + // now start the test + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + CYG_TEST_INFO( "T2 awoken" ); + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = wup_tsk( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + + CYG_TEST_INFO( "T2 completing" ); + t2done++; + + ercd = slp_tsk(); + CYG_TEST_FAIL( "Task 2 sleep came back" ); +} + +void task3( unsigned int arg ) +{ + ER ercd; + INT scratch; + + CYG_TEST_INFO( "Task 3 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 3 == scratch, "tid not 3" ); + if ( 333 != arg ) + CYG_TEST_FAIL( "Task 3 arg not 333" ); + + // now start the test + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + CYG_TEST_INFO( "T3 awoken" ); + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + + CYG_TEST_INFO( "T3 completing" ); + t3done++; + + ercd = slp_tsk(); + CYG_TEST_FAIL( "Task 3 sleep came back" ); +} + +void task4( unsigned int arg ) +{ + ER ercd; + INT scratch; + + CYG_TEST_INFO( "Task 4 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 4 == scratch, "tid not 4" ); + if ( 444 != arg ) + CYG_TEST_FAIL( "Task 4 arg not 444" ); + + // now start the test + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + + CYG_TEST_INFO( "T4 completing" ); + t4done++; + + ercd = slp_tsk(); + CYG_TEST_FAIL( "Task 4 sleep came back" ); +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF testcx3.cxx diff --git a/packages/compat/uitron/v2_0/tests/testcx4.cxx b/packages/compat/uitron/v2_0/tests/testcx4.cxx new file mode 100644 index 00000000..b4c2367e --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/testcx4.cxx @@ -0,0 +1,406 @@ +//=========================================================================== +// +// testcx4.cxx +// +// uITRON "C++" test program four +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dsm +// Contributors: dsm +// Date: 1998-06-12 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough cyclic handlers */ \ + defined( CYGPKG_UITRON_CYCLICS ) && \ + (CYGNUM_UITRON_CYCLICS >= 3) && \ + (CYGNUM_UITRON_CYCLICS < 90) && \ + \ + /* test configuration for enough alarm handlers */ \ + defined( CYGPKG_UITRON_ALARMS ) && \ + (CYGNUM_UITRON_ALARMS >= 3) && \ + (CYGNUM_UITRON_ALARMS < 90) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +volatile int intercount = 0; +INT scratch; + +void hand1(void) +{ + CYG_TEST_INFO("Handler 1 called"); + intercount++; +} + +void hand2(void) +{ + CYG_TEST_CHECK( 2 == intercount, "handler out of sync" ); + CYG_TEST_INFO("Handler 2 called"); + intercount++; +} + +extern "C" { + void task1( unsigned int arg ); + void task2( unsigned int arg ); + void task3( unsigned int arg ); + void task4( unsigned int arg ); +} + +void task1( unsigned int arg ) +{ + ER ercd; + + T_DCYC dcyc; + T_DALM dalm; + T_RCYC rcyc; + T_RALM ralm; + + unsigned int tm; + + static char foo[] = "Test message"; + VP info = (VP)foo; + + // Increase times when running on HW since overhead of GDB packet + // acknowledgements may cause tests of timing to fail. + if (cyg_test_is_simulator) + tm = 1; + else + tm = 4; + + CYG_TEST_INFO( "Task 1 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 1 == scratch, "tid not 1" ); + + dcyc.exinf = (VP)info; + dcyc.cycatr = TA_HLNG; + dcyc.cychdr = (FP)&hand1; + dcyc.cycact = TCY_INI; // bad + dcyc.cyctim = 2; + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = def_cyc(3, &dcyc); + CYG_TEST_CHECK( E_PAR == ercd, "def_cyc bad ercd !E_PAR" ); +#endif // we can test bad param error returns + + dcyc.cycact = TCY_OFF; // make good + dcyc.cyctim = 0; // bad + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = def_cyc(3, &dcyc); + CYG_TEST_CHECK( E_PAR == ercd, "def_cyc bad ercd !E_PAR" ); +#endif // we can test bad param error returns + + dcyc.cyctim = 1; // make good + + ercd = def_cyc(3, &dcyc); + CYG_TEST_CHECK( E_OK == ercd, "def_cyc bad ercd" ); + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = def_cyc(-6, &dcyc); + CYG_TEST_CHECK( E_PAR == ercd, "def_cyc bad ercd !E_PAR" ); + ercd = def_cyc(99, &dcyc); + CYG_TEST_CHECK( E_PAR == ercd, "def_cyc bad ercd !E_PAR" ); + + ercd = act_cyc(-6, TCY_OFF); + CYG_TEST_CHECK( E_PAR == ercd, "act_cyc bad ercd !E_PAR" ); + ercd = act_cyc(99, TCY_OFF); + CYG_TEST_CHECK( E_PAR == ercd, "act_cyc bad ercd !E_PAR" ); + ercd = act_cyc( 3, ~0); + CYG_TEST_CHECK( E_PAR == ercd, "act_cyc bad ercd !E_PAR" ); + + ercd = ref_cyc(&rcyc, -6); + CYG_TEST_CHECK( E_PAR == ercd, "ref_cyc bad ercd !E_PAR" ); + ercd = ref_cyc(&rcyc, 99); + CYG_TEST_CHECK( E_PAR == ercd, "ref_cyc bad ercd !E_PAR" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_cyc(NULL, 3); + CYG_TEST_CHECK( E_PAR == ercd, "ref_cyc bad ercd !E_PAR" ); +#endif +#endif // we can test bad param error returns + + ercd = def_cyc(3, (T_DCYC *)NADR); + CYG_TEST_CHECK( E_OK == ercd, "def_cyc bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_cyc bad ercd !E_NOEXS" ); +#endif // we can test bad param error returns + + CYG_TEST_PASS( "bad calls: def_cyc, act_cyc, ref_cyc" ); + + dalm.exinf = (VP)info; + dalm.almatr = TA_HLNG; + dalm.almhdr = (FP)&hand2; + dalm.tmmode = ~0; // bad + dalm.almtim = 20; + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = def_alm(3, &dalm); + CYG_TEST_CHECK( E_PAR == ercd, "def_alm bad ercd !E_PAR" ); +#endif // we can test bad param error returns + + dalm.tmmode = TTM_REL; // make good + dalm.almtim = 0; // bad + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = def_alm(3, &dalm); + CYG_TEST_CHECK( E_PAR == ercd, "def_alm bad ercd !E_PAR" ); +#endif // we can test bad param error returns + + dalm.almtim = 1000; // make good + + ercd = def_alm(3, &dalm); + CYG_TEST_CHECK( E_OK == ercd, "def_alm bad ercd" ); + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = ref_alm(&ralm, -6); + CYG_TEST_CHECK( E_PAR == ercd, "ref_alm bad ercd !E_PAR" ); + ercd = ref_alm(&ralm, 99); + CYG_TEST_CHECK( E_PAR == ercd, "ref_alm bad ercd !E_PAR" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_alm(NULL, 3); + CYG_TEST_CHECK( E_PAR == ercd, "ref_alm bad ercd !E_PAR" ); +#endif + +#endif // we can test bad param error returns + ercd = def_alm(3, (T_DALM *)NADR); + CYG_TEST_CHECK( E_OK == ercd, "def_cyc bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = ref_alm(&ralm, 3); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_cyc bad ercd !E_NOEXS" ); +#endif // we can test bad param error returns + + CYG_TEST_PASS( "bad calls: def_alm, act_alm, ref_alm" ); + + dcyc.exinf = (VP)info; + dcyc.cycatr = TA_HLNG; + dcyc.cychdr = (FP)&hand1; + dcyc.cycact = TCY_ON; + dcyc.cyctim = 50*tm; + + ercd = def_cyc(3, &dcyc); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 45*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 50*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_ON == rcyc.cycact, "rcyc.cycact should be TCY_ON" ); + ercd = act_cyc(3, TCY_OFF); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 45*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 50*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_OFF == rcyc.cycact, "rcyc.cycact should be TCY_OFF" ); + ercd = act_cyc(3, TCY_ON); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc bad ercd" ); + + CYG_TEST_PASS("good calls: def_cyc, act_cyc, ref_cyc"); + + dalm.exinf = (VP)info; + dalm.almatr = TA_HLNG; + dalm.almhdr = (FP)&hand2; + dalm.tmmode = TTM_REL; + dalm.almtim = 120*tm; + + ercd = def_alm(3, &dalm); + CYG_TEST_CHECK( E_OK == ercd, "def_alm bad ercd" ); + ercd = ref_alm(&ralm, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_alm bad ercd" ); + CYG_TEST_CHECK( info == ralm.exinf, "ralm.exinf should be info" ); + CYG_TEST_CHECK( 115*tm < ralm.lfttim, "ralm.lfttim too small" ); + CYG_TEST_CHECK( ralm.lfttim <= 120*tm, "ralm.lfttim too big" ); + + // Expect handlers to be called at approximate times + // time intercount + // tm*50 hand1 0 + // tm*100 hand1 1 + // tm*120 hand2 2 + // tm*150 hand1 3 + + ercd = dly_tsk(160*tm); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 4 == intercount, "handlers not both called" ); + + ercd = act_cyc(3, TCY_OFF); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc(off) bad ercd" ); + + ercd = dly_tsk(60*tm); // enough for at least one tick + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 4 == intercount, "cyclic not disabled" ); + + // approx time now 220, so we expect a cycle in about 30 ticks + ercd = act_cyc(3, TCY_ON); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc(on) bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 25*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 35*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_ON == rcyc.cycact, "rcyc.cycact should be TCY_ON" ); + + // now resynchronize with right now: + ercd = act_cyc(3, TCY_ON|TCY_INI); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc(on) bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 45*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 50*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_ON == rcyc.cycact, "rcyc.cycact should be TCY_ON" ); + + // wait a bit and check that time marches on, or even down + ercd = dly_tsk(10*tm); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 35*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 45*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_ON == rcyc.cycact, "rcyc.cycact should be TCY_ON" ); + + // now turn it off and re-synch with right now: + ercd = act_cyc(3, TCY_OFF|TCY_INI); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc(on) bad ercd" ); + ercd = ref_cyc(&rcyc, 3); + CYG_TEST_CHECK( E_OK == ercd, "ref_cyc bad ercd" ); + CYG_TEST_CHECK( info == rcyc.exinf, "rcyc.exinf should be info" ); + CYG_TEST_CHECK( 45*tm < rcyc.lfttim, "rcyc.lfttim too small" ); + CYG_TEST_CHECK( rcyc.lfttim <= 50*tm, "rcyc.lfttim too big" ); + CYG_TEST_CHECK( TCY_OFF == rcyc.cycact, "rcyc.cycact should be TCY_OFF" ); + + ercd = act_cyc(3, TCY_OFF); + CYG_TEST_CHECK( E_OK == ercd, "act_cyc(on) bad ercd" ); + + CYG_TEST_PASS("good calls: def_cyc, act_cyc, ref_cyc, def_alm, ref_alm"); + + // all done + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF testcx4.cxx diff --git a/packages/compat/uitron/v2_0/tests/testcx5.cxx b/packages/compat/uitron/v2_0/tests/testcx5.cxx new file mode 100644 index 00000000..ee16e613 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/testcx5.cxx @@ -0,0 +1,363 @@ +//=========================================================================== +// +// testcx5.cxx +// +// uITRON "C++" test program five +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dsm +// Contributors: dsm +// Date: 1998-06-12 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough flag objects */ \ + defined( CYGPKG_UITRON_FLAGS ) && \ + (CYGNUM_UITRON_FLAGS >= 3) && \ + (CYGNUM_UITRON_FLAGS < 90) && \ + ( !defined(CYGPKG_UITRON_FLAGS_CREATE_DELETE) || \ + CYGNUM_UITRON_FLAGS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough message boxes */ \ + defined( CYGPKG_UITRON_MBOXES ) && \ + (CYGNUM_UITRON_MBOXES >= 3) && \ + (CYGNUM_UITRON_MBOXES < 90) && \ + ( !defined(CYGPKG_UITRON_MBOXES_CREATE_DELETE) || \ + CYGNUM_UITRON_MBOXES_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough fixed memory pools */ \ + defined( CYGPKG_UITRON_MEMPOOLFIXED ) && \ + (CYGNUM_UITRON_MEMPOOLFIXED >= 3) && \ + (CYGNUM_UITRON_MEMPOOLFIXED < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLFIXED_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough variable mempools */ \ + defined( CYGPKG_UITRON_MEMPOOLVAR ) && \ + (CYGNUM_UITRON_MEMPOOLVAR >= 3) && \ + (CYGNUM_UITRON_MEMPOOLVAR < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLVAR_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +volatile int intercount = 0; + +UINT scratch; +T_MSG *t_msg; +VP vp; + + +extern "C" { + void task1( unsigned int arg ); + void task2( unsigned int arg ); + void task3( unsigned int arg ); + void task4( unsigned int arg ); +} + + +void task1( unsigned int arg ) +{ + ER ercd; + int i; + T_RSYS rsys; + + CYG_TEST_INFO( "Task 1 running" ); + + // check initial state + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_TSK == rsys.sysstat, "system state not TSS_TSK" ); + // disable intrs and check state + ercd = loc_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "loc_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_LOC == rsys.sysstat, "system state not TSS_LOC" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // try an illegal op + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_CTX == ercd, "dly_tsk bad ercd !E_CTX" ); +#endif // CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // enable intrs and check state and a legal sleep + ercd = unl_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "unl_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_TSK == rsys.sysstat, "system state not TSS_TSK" ); + ercd = dly_tsk( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + // disable intrs and try scheduler illegal ops + ercd = loc_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "loc_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_LOC == rsys.sysstat, "system state not TSS_LOC" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = dis_dsp(); + CYG_TEST_CHECK( E_CTX == ercd, "dis_dsp bad ercd !E_CTX" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_CTX == ercd, "ena_dsp bad ercd !E_CTX" ); +#endif // CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // enable again and check state + ercd = unl_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "unl_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_TSK == rsys.sysstat, "system state not TSS_TSK" ); + // disable the scheduler and check state + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_DDSP == rsys.sysstat, "system state not TSS_DDSP" ); + // disable intrs and check state + ercd = loc_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "loc_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_LOC == rsys.sysstat, "system state not TSS_LOC" ); + // then unlock and check state + ercd = unl_cpu(); + CYG_TEST_CHECK( E_OK == ercd, "unl_cpu bad ercd" ); + ercd = ref_sys( &rsys ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sys bad ercd" ); + CYG_TEST_CHECK( TSS_TSK == rsys.sysstat, "system state not TSS_TSK" ); + + CYG_TEST_PASS( "Interrupt dis/enabling and interactions" ); + + // and now we can do the rest of the test + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai bad ercd !E_OBJ" ); + ercd = rel_wai( 1 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai(me) bad ercd !E_OBJ" ); + ercd = rel_wai( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "rel_wai bad ercd !E_ID" ); + ercd = rel_wai( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "rel_wai bad ercd !E_ID" ); +#endif // we can test bad param error returns + + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 2, 22222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 2, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai bad ercd !E_OBJ" ); + ercd = rel_wai( 1 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai(me) bad ercd !E_OBJ" ); +#endif // we can test bad param error returns + + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "wai_sem bad ercd !E_RLWAI" ); + + ercd = twai_sem( 1, 20 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "twai_sem bad ercd !E_RLWAI" ); + + ercd = wai_flg( &scratch, 1, 9999, 0 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "wai_flg bad ercd !E_RLWAI" ); + + ercd = twai_flg( &scratch, 1, 9999, 0, 10 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "twai_flg bad ercd !E_RLWAI" ); + + ercd = rcv_msg( &t_msg, 1 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "rcv_msg bad ercd !E_RLWAI" ); + + ercd = trcv_msg( &t_msg, 1, 10 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "trcv_msg bad ercd !E_RLWAI" ); + + // these are loops so as to consume the whole of the mempool + // in order to wait at the end + for ( i = 0; i < 10; i++ ) + if ( E_OK != (ercd = get_blf( &vp, 3 ) ) ) + break; + CYG_TEST_CHECK( E_RLWAI == ercd, "get_blf bad ercd !E_RLWAI" ); + + for ( i = 0; i < 10; i++ ) + if ( E_OK != (ercd = tget_blf( &vp, 3, 10 ) ) ) + break; + CYG_TEST_CHECK( E_RLWAI == ercd, "tget_blf bad ercd !E_RLWAI" ); + + for ( i = 0; i < 10; i++ ) + if ( E_OK != (ercd = get_blk( &vp, 1, 1000 ) ) ) + break; + CYG_TEST_CHECK( E_RLWAI == ercd, "get_blk bad ercd !E_RLWAI" ); + + for ( i = 0; i < 10; i++ ) + if ( E_OK != (ercd = tget_blk( &vp, 1, 1000, 10 ) ) ) + break; + CYG_TEST_CHECK( E_RLWAI == ercd, "tget_blk bad ercd !E_RLWAI" ); + + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "dly_tsk bad ercd !E_RLWAI" ); + + ercd = tslp_tsk( 10 ); + CYG_TEST_CHECK( E_RLWAI == ercd, "tslp_tsk bad ercd !E_RLWAI" ); + + ercd = slp_tsk(); + CYG_TEST_CHECK( E_RLWAI == ercd, "slp_tsk bad ercd !E_RLWAI" ); + + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + CYG_TEST_PASS("release wait: various waiting calls"); + + // all done + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + int i; + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &i ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == i, "tid not 2" ); + if ( 22222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 22222" ); + + for ( i = 0 ; i < 100; i++ ) { + ercd = rel_wai( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_wai bad ercd" ); + } + // we expect task2 to be killed here + CYG_TEST_FAIL( "Task 2 ran to completion!" ); +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF testcx5.cxx diff --git a/packages/compat/uitron/v2_0/tests/testcx6.cxx b/packages/compat/uitron/v2_0/tests/testcx6.cxx new file mode 100644 index 00000000..14c01c5e --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/testcx6.cxx @@ -0,0 +1,600 @@ +//=========================================================================== +// +// testcx6.cxx +// +// uITRON "C++" test program six +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-10-14 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough flag objects */ \ + defined( CYGPKG_UITRON_FLAGS ) && \ + (CYGNUM_UITRON_FLAGS >= 3) && \ + (CYGNUM_UITRON_FLAGS < 90) && \ + ( !defined(CYGPKG_UITRON_FLAGS_CREATE_DELETE) || \ + CYGNUM_UITRON_FLAGS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough message boxes */ \ + defined( CYGPKG_UITRON_MBOXES ) && \ + (CYGNUM_UITRON_MBOXES >= 3) && \ + (CYGNUM_UITRON_MBOXES < 90) && \ + ( !defined(CYGPKG_UITRON_MBOXES_CREATE_DELETE) || \ + CYGNUM_UITRON_MBOXES_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +volatile int intercount = 0; +UINT scratch; +T_MSG *t_msg = (T_MSG *)&scratch; +T_MSG *msg; +VP vp; + +T_CSEM t_csem = { NULL, 0, 0 }; +T_CMBX t_cmbx = { NULL, 0 }; +T_CFLG t_cflg = { NULL, 0, 0 }; +T_RSEM t_rsem; +T_RMBX t_rmbx; +T_RFLG t_rflg; + + +extern "C" { + void task1( unsigned int arg ); + void task2( unsigned int arg ); + void task3( unsigned int arg ); + void task4( unsigned int arg ); +} + +void task1( unsigned int arg ) +{ + ER ercd; + int tests = 0; + + CYG_TEST_INFO( "Task 1 running" ); + + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 2, 22222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 2, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + tests++; +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_sem( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_sem bad ercd !E_ID" ); + ercd = del_sem( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_sem bad ercd !E_ID" ); + ercd = cre_sem( -6, &t_csem ); + CYG_TEST_CHECK( E_ID == ercd, "cre_sem bad ercd !E_ID" ); + ercd = cre_sem( 99, &t_csem ); + CYG_TEST_CHECK( E_ID == ercd, "cre_sem bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + ercd = cre_sem( 3, &t_csem ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_sem bad ercd !E_OBJ" ); + // delete it so we can play + ercd = del_sem( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); + // check it is deleted + ercd = sig_sem( 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sig_sem bad ercd !E_NOEXS" ); + ercd = preq_sem( 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "preq_sem bad ercd !E_NOEXS" ); + ercd = twai_sem( 3, 10 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "twai_sem bad ercd !E_NOEXS" ); + ercd = wai_sem( 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "wai_sem bad ercd !E_NOEXS" ); + ercd = ref_sem( &t_rsem, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_sem bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_sem( 3, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_sem bad ercd !E_PAR" ); +#endif + t_csem.sematr = 0xfff; + ercd = cre_sem( 3, &t_csem ); + CYG_TEST_CHECK( E_RSATR == ercd, "cre_sem bad ercd !E_RSATR" ); + t_csem.sematr = 0; +#endif // we can test bad param error returns + ercd = cre_sem( 3, &t_csem ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); + // and check we can use it + ercd = sig_sem( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + ercd = wai_sem( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + ercd = preq_sem( 3 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "preq_sem bad ercd !E_TMOUT" ); + ercd = twai_sem( 3, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_sem bad ercd !E_TMOUT" ); + ercd = ref_sem( &t_rsem, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_sem bad ercd" ); + + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_sem bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = twai_sem( 2, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_sem bad ercd !E_DLT" ); + + // check they are deleted + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sig_sem bad ercd !E_NOEXS" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sig_sem bad ercd !E_NOEXS" ); + // re-create and do it again + ercd = cre_sem( 1, &t_csem ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); + ercd = cre_sem( 2, &t_csem ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); + + // now wait while task 2 deletes the wait objects again + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_sem bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = twai_sem( 2, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_sem bad ercd !E_DLT" ); + + // check they are deleted + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sig_sem bad ercd !E_NOEXS" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sig_sem bad ercd !E_NOEXS" ); + + CYG_TEST_PASS("create/delete semaphores"); +#endif // CYGPKG_UITRON_SEMAS_CREATE_DELETE + + +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + tests++; +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_flg( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_flg bad ercd !E_ID" ); + ercd = del_flg( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_flg bad ercd !E_ID" ); + ercd = cre_flg( -6, &t_cflg ); + CYG_TEST_CHECK( E_ID == ercd, "cre_flg bad ercd !E_ID" ); + ercd = cre_flg( 99, &t_cflg ); + CYG_TEST_CHECK( E_ID == ercd, "cre_flg bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + ercd = cre_flg( 3, &t_cflg ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_flg bad ercd !E_OBJ" ); + // delete it so we can play + ercd = del_flg( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + // check it is deleted + ercd = set_flg( 3, 0x6789 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "set_flg bad ercd !E_NOEXS" ); + ercd = clr_flg( 3, 0x9876 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "clr_flg bad ercd !E_NOEXS" ); + ercd = pol_flg( &scratch, 3, 0xdddd, TWF_ANDW ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pol_flg bad ercd !E_NOEXS" ); + ercd = twai_flg( &scratch, 3, 0x4444, TWF_ORW, 10 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "twai_flg bad ercd !E_NOEXS" ); + ercd = wai_flg( &scratch, 3, 0xbbbb, TWF_ANDW | TWF_CLR ); + CYG_TEST_CHECK( E_NOEXS == ercd, "wai_flg bad ercd !E_NOEXS" ); + ercd = ref_flg( &t_rflg, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_flg bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_flg( 3, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_flg bad ercd !E_PAR" ); +#endif + t_cflg.flgatr = 0xfff; + ercd = cre_flg( 3, &t_cflg ); + CYG_TEST_CHECK( E_RSATR == ercd, "cre_flg bad ercd !E_RSATR" ); +#endif // we can test bad param error returns + // now create it well + t_cflg.flgatr = 0; + t_cflg.iflgptn = 0; + ercd = cre_flg( 3, &t_cflg ); + CYG_TEST_CHECK( E_OK == ercd, "cre_flg bad ercd" ); + // and check we can use it + ercd = clr_flg( 3, 0x7256 ); + CYG_TEST_CHECK( E_OK == ercd, "clr_flg bad ercd" ); + ercd = set_flg( 3, 0xff ); + CYG_TEST_CHECK( E_OK == ercd, "set_flg bad ercd" ); + ercd = wai_flg( &scratch, 3, 0xaa, TWF_ANDW | TWF_CLR ); + CYG_TEST_CHECK( E_OK == ercd, "wai_flg bad ercd" ); + ercd = pol_flg( &scratch, 3, 0xaa, TWF_ANDW | TWF_CLR ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pol_flg bad ercd !E_TMOUT" ); + ercd = twai_flg( &scratch, 3, 0xaa, TWF_ANDW | TWF_CLR, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "twai_flg bad ercd !E_TMOUT" ); + ercd = ref_flg( &t_rflg, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 == t_rflg.flgptn, "ref_flg bad ercd" ); + // now create it again with a preset pattern and check that we can + // detect that pattern: + ercd = del_flg( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + t_cflg.flgatr = 0; + t_cflg.iflgptn = 0x1234; + ercd = cre_flg( 3, &t_cflg ); + CYG_TEST_CHECK( E_OK == ercd, "cre_flg bad ercd" ); + // and check we can use it + ercd = wai_flg( &scratch, 3, 0x1200, TWF_ANDW ); + CYG_TEST_CHECK( E_OK == ercd, "wai_flg bad ercd" ); + ercd = pol_flg( &scratch, 3, 0x0034, TWF_ANDW ); + CYG_TEST_CHECK( E_OK == ercd, "pol_flg bad ercd" ); + ercd = twai_flg( &scratch, 3, 0x1004, TWF_ANDW, 10 ); + CYG_TEST_CHECK( E_OK == ercd, "twai_flg bad ercd" ); + ercd = pol_flg( &scratch, 3, 0xffedcb, TWF_ORW ); + CYG_TEST_CHECK( E_TMOUT == ercd, "pol_flg bad ercd !E_TMOUT" ); + ercd = ref_flg( &t_rflg, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0x1234 == t_rflg.flgptn, "ref_flg bad ercd" ); + ercd = clr_flg( 3, 0 ); + ercd = ref_flg( &t_rflg, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_flg bad ercd" ); + CYG_TEST_CHECK( 0 == t_rflg.flgptn, "ref_flg bad ercd" ); + + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = wai_flg( &scratch, 1, 0xaa, TWF_ANDW ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_flg bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = twai_flg( &scratch, 2, 0x55, TWF_ANDW, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_flg bad ercd !E_DLT" ); + + // check they are deleted + ercd = set_flg( 1, 0x22 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "set_flg bad ercd !E_NOEXS" ); + ercd = clr_flg( 2, 0xdd ); + CYG_TEST_CHECK( E_NOEXS == ercd, "clr_flg bad ercd !E_NOEXS" ); + // re-create and do it again + t_cflg.iflgptn = 0x5555; + ercd = cre_flg( 1, &t_cflg ); + CYG_TEST_CHECK( E_OK == ercd, "cre_flg bad ercd" ); + t_cflg.iflgptn = 0; + ercd = cre_flg( 2, &t_cflg ); + CYG_TEST_CHECK( E_OK == ercd, "cre_flg bad ercd" ); + + // now wait while task 2 deletes the wait objects again + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = wai_flg( &scratch, 1, 0xaaaa, TWF_ORW | TWF_CLR ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_flg bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = twai_flg( &scratch, 2, 0xffff, TWF_ORW, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_flg bad ercd !E_DLT" ); + + // check they are deleted + ercd = clr_flg( 1, 0xd00d ); + CYG_TEST_CHECK( E_NOEXS == ercd, "clr_flg bad ercd !E_NOEXS" ); + ercd = set_flg( 2, 0xfff00 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "set_flg bad ercd !E_NOEXS" ); + + CYG_TEST_PASS("create/delete flags"); +#endif // CYGPKG_UITRON_FLAGS_CREATE_DELETE + +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE + tests++; +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_mbx( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mbx bad ercd !E_ID" ); + ercd = del_mbx( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mbx bad ercd !E_ID" ); + ercd = cre_mbx( -6, &t_cmbx ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mbx bad ercd !E_ID" ); + ercd = cre_mbx( 99, &t_cmbx ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mbx bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + ercd = cre_mbx( 3, &t_cmbx ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_mbx bad ercd !E_OBJ" ); + // delete it so we can play + ercd = del_mbx( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); + // check it is deleted + ercd = snd_msg( 3, t_msg ); + CYG_TEST_CHECK( E_NOEXS == ercd, "snd_msg bad ercd !E_NOEXS" ); + ercd = rcv_msg( &msg, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "rcv_msg bad ercd !E_NOEXS" ); + ercd = trcv_msg( &msg, 3, 10 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "trcv_msg bad ercd !E_NOEXS" ); + ercd = prcv_msg( &msg, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "prcv_msg bad ercd !E_NOEXS" ); + ercd = ref_mbx( &t_rmbx, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_mbx bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_mbx( 3, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_mbx bad ercd !E_PAR" ); +#endif + t_cmbx.mbxatr = 0xfff; + ercd = cre_mbx( 3, &t_cmbx ); + CYG_TEST_CHECK( E_RSATR == ercd, "cre_mbx bad ercd !E_RSATR" ); + t_cmbx.mbxatr = 0; +#endif // we can test bad param error returns + ercd = cre_mbx( 3, &t_cmbx ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mbx bad ercd" ); + // and check we can use it + ercd = snd_msg( 3, t_msg ); + CYG_TEST_CHECK( E_OK == ercd, "snd_msg bad ercd" ); + ercd = rcv_msg( &msg, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "rcv_msg bad ercd" ); + ercd = trcv_msg( &msg, 3, 2 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "trcv_msg bad ercd !E_TMOUT" ); + ercd = prcv_msg( &msg, 3 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "prcv_msg bad ercd !E_TMOUT" ); + ercd = ref_mbx( &t_rmbx, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mbx bad ercd" ); + + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rcv_msg( &msg, 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_mbx bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = trcv_msg( &msg, 2, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_mbx bad ercd !E_DLT" ); + + // check they are deleted + ercd = snd_msg( 1, t_msg ); + CYG_TEST_CHECK( E_NOEXS == ercd, "snd_msg bad ercd !E_NOEXS" ); + ercd = snd_msg( 2, t_msg ); + CYG_TEST_CHECK( E_NOEXS == ercd, "snd_msg bad ercd !E_NOEXS" ); + // re-create and do it again + ercd = cre_mbx( 1, &t_cmbx ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mbx bad ercd" ); + ercd = cre_mbx( 2, &t_cmbx ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mbx bad ercd" ); + + // now wait while task 2 deletes the wait objects again + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rcv_msg( &msg, 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "wai_mbx bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = trcv_msg( &msg, 2, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "twai_mbx bad ercd !E_DLT" ); + + // check they are deleted + ercd = snd_msg( 1, t_msg ); + CYG_TEST_CHECK( E_NOEXS == ercd, "snd_msg bad ercd !E_NOEXS" ); + ercd = snd_msg( 2, t_msg ); + CYG_TEST_CHECK( E_NOEXS == ercd, "snd_msg bad ercd !E_NOEXS" ); + + CYG_TEST_PASS("create/delete mboxes"); +#endif // CYGPKG_UITRON_MBOXES_CREATE_DELETE + + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + ercd = dly_tsk( 5 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + // all done + if ( 0 == tests ) { + CYG_TEST_NA( "No objects have create/delete enabled" ); + } + else { + CYG_TEST_EXIT( "All done" ); + } + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + int i; + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &i ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == i, "tid not 2" ); + if ( 22222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 22222" ); + + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + ercd = del_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); +#endif // CYGPKG_UITRON_SEMAS_CREATE_DELETE + +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + ercd = del_flg( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_flg( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_flg( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_flg( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); +#endif // CYGPKG_UITRON_FLAGS_CREATE_DELETE + +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE + ercd = del_mbx( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mbx( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mbx( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mbx( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); +#endif // CYGPKG_UITRON_MBOXES_CREATE_DELETE + + // we expect task2 to be killed here + CYG_TEST_FAIL( "Task 2 ran to completion!" ); +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF testcx6.cxx diff --git a/packages/compat/uitron/v2_0/tests/testcx7.cxx b/packages/compat/uitron/v2_0/tests/testcx7.cxx new file mode 100644 index 00000000..b50e9683 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/testcx7.cxx @@ -0,0 +1,1101 @@ +//=========================================================================== +// +// testcx7.cxx +// +// uITRON "C++" test program seven +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-10-14 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough flag objects */ \ + defined( CYGPKG_UITRON_FLAGS ) && \ + (CYGNUM_UITRON_FLAGS >= 3) && \ + (CYGNUM_UITRON_FLAGS < 90) && \ + ( !defined(CYGPKG_UITRON_FLAGS_CREATE_DELETE) || \ + CYGNUM_UITRON_FLAGS_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough message boxes */ \ + defined( CYGPKG_UITRON_MBOXES ) && \ + (CYGNUM_UITRON_MBOXES >= 3) && \ + (CYGNUM_UITRON_MBOXES < 90) && \ + ( !defined(CYGPKG_UITRON_MBOXES_CREATE_DELETE) || \ + CYGNUM_UITRON_MBOXES_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough fixed memory pools */ \ + defined( CYGPKG_UITRON_MEMPOOLFIXED ) && \ + (CYGNUM_UITRON_MEMPOOLFIXED >= 3) && \ + (CYGNUM_UITRON_MEMPOOLFIXED < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLFIXED_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough variable mempools */ \ + defined( CYGPKG_UITRON_MEMPOOLVAR ) && \ + (CYGNUM_UITRON_MEMPOOLVAR >= 3) && \ + (CYGNUM_UITRON_MEMPOOLVAR < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLVAR_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + +#include // stack analysis tools + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + + +extern "C" { + void task1( unsigned int arg ); + void task2( unsigned int arg ); + void task3( unsigned int arg ); + void task4( unsigned int arg ); +} + +// ======================================================================== + +enum { + START_WAITOP = 0, + SLEEP = 0, + DELAY, + SEMGET, + FLAGWAIT, + MSGGET, + MEMFIXEDGET, + MEMVARGET, + DONE_WAITOP +}; +typedef int WAITOP; + +enum { + START_TYPE = 0, + PLAIN = 0, + TIMED = 1, + DONE_TYPE +}; +typedef int WAITTYPE; + +enum { + START_KILLOP = 0, + + // These are the 5 ways out of a wait that we perm + // with other circumstances: + SIGNAL = 0, // do the appropriate producer op + TIMEOUT, // wait for the timeout to fire + RELEASE, // do a rel_wai() + DELETE, // delete the object; del_xxx() + KILL, // do a ter_tsk() on the waiter + + SUSPEND_SIGNAL_RESUME, + SUSPEND_TIMEOUT_RESUME, + SUSPEND_RELEASE_RESUME, + SUSPEND_DELETE_RESUME, + SUSPEND_KILL, // resume not applicable + + SUSPEND_SIGNAL_KILL, + SUSPEND_TIMEOUT_KILL, + SUSPEND_RELEASE_KILL, + SUSPEND_DELETE_KILL, + // SUSPEND_KILL_KILL not applicable + +#if 0 + // support these later if _really_ keen. + SUSPEND_SIGNAL_DELETE_RESUME, + SUSPEND_TIMEOUT_DELETE_RESUME, + SUSPEND_RELEASE_DELETE_RESUME, + // SUSPEND_DELETE_DELETE_RESUME not applicable + // SUSPEND_KILL_DELETE_RESUME not applicable + + SUSPEND_SIGNAL_DELETE_KILL, + SUSPEND_TIMEOUT_DELETE_KILL, + SUSPEND_RELEASE_DELETE_KILL, + // SUSPEND_DELETE_DELETE_KILL, + SUSPEND_KILL_DELETE // 2nd kill not applicable +#endif + + DONE_KILLOP +}; +typedef int KILLOP; + +// ======================================================================== + +char * waitstrings[] = +{ "Sleep ", "Delay ", "Sema ", "Flag ", "Mbox ", "MemFix", "MemVar" }; + +char * typestrings[] = +{ " (Plain) : ", " (Timed) : " }; + +char * killstrings[] = +{ "Signal", + "Wait-for-timeout", + "Release-wait", + "Delete-object", + "Kill-task", + + "Suspend/Signal/Resume", + "Suspend/Wait-for-timeout/Resume", + "Suspend/Release-wait/Resume", + "Suspend/Delete-object/Resume", + "Suspend/Kill-task", + + "Suspend/Signal/Kill-task", + "Suspend/Wait-for-timeout/Kill-task", + "Suspend/Release-wait/Kill-task", + "Suspend/Delete-object/Kill-task", + + +}; + +// ======================================================================== + +inline int task2arg( WAITOP wait, WAITTYPE waittype, KILLOP kill ) +{ + return waittype + (wait << 1) + (kill << 8); +} + +inline void decodearg( int arg, WAITOP *pwait, WAITTYPE *pwaittype, KILLOP *pkill ) +{ + *pwaittype = (arg & 1) ? TIMED : PLAIN; + *pwait = (arg >> 1) & 0x7f; + *pkill = (arg >> 8); +} + +static char *strdog( char *p, char *q ) +{ + while ( 0 != (*p++ = *q++) ); + return p - 1; +} + +static char * +makemsg( char *z, WAITOP wait, WAITTYPE waittype, KILLOP kill ) +{ + static char buf[ 1000 ]; + char *p = buf; + p = strdog( p, z ); + p = strdog( p, waitstrings[ wait ] ); + p = strdog( p, typestrings[ waittype ] ); + p = strdog( p, killstrings[ kill ] ); + *p = 0; + return buf; +} + +// ======================================================================== + +volatile int intercom = 0; + +// ======================================================================== + +T_RTSK rtsk; + +void +do_suspend( void ) +{ + ER ercd; + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_WAI == rtsk.tskstat, "bad tskstat !TTS_WAI" ); + ercd = sus_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_WAS == rtsk.tskstat, "bad tskstat !TTS_WAS" ); +} + +void +do_resume( void ) +{ + ER ercd; + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_SUS == rtsk.tskstat, "bad tskstat !TTS_SUS" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = rsm_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "rsm_tsk bad ercd" ); + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_RDY == rtsk.tskstat, "bad tskstat !TTS_RDY" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); +} + +// ======================================================================== + +#define T1_WAIT (7) +#define T2_WAIT (5) + +#define T1_MALLOC (110) +#ifdef CYGSEM_KERNEL_MEMORY_COALESCE +#define T2_MALLOC (100) +#else +#define T2_MALLOC T1_MALLOC +#endif + +VP vptmp; +VP vp = NULL; +VP vp1 = NULL; +VP t2vp = NULL; +VP t2vp_backup = NULL; + +UINT scratch; + +T_MSG *msg = (T_MSG *)&scratch; +T_MSG *msg1; + +void +do_prep( WAITOP wait ) +{ + ER ercd; + switch ( wait ) { + case SLEEP: + case DELAY: + case SEMGET: + case FLAGWAIT: + case MSGGET: + // do nothing for all of those + break; + case MEMFIXEDGET: + // allocate all the memory in the pool; remember a couple + // for freeing as the signalling operation: + t2vp = NULL; + vp = vptmp = NULL; + do { + vp1 = vptmp; + vptmp = vp; + ercd = pget_blf( &vp, 1 ); + } while ( E_OK == ercd ); + CYG_TEST_CHECK( E_TMOUT == ercd, "get_blf bad ercd" ); + CYG_TEST_CHECK( NULL != vp, "no allocated block to free" ); + CYG_TEST_CHECK( NULL != vp1, "no allocated block to free1" ); + break; + case MEMVARGET: + // allocate all the memory in the pool; remember a couple + // for freeing as the signalling operation: + t2vp = NULL; + vp = vptmp = NULL; + do { + vp1 = vptmp; + vptmp = vp; + ercd = pget_blk( &vp, 1, T1_MALLOC ); + } while ( E_OK == ercd ); + CYG_TEST_CHECK( E_TMOUT == ercd, "get_blk bad ercd" ); + CYG_TEST_CHECK( NULL != vp, "no allocated block to free" ); + CYG_TEST_CHECK( NULL != vp1, "no allocated block to free1" ); + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } +} + +void +do_tidyup( WAITOP wait ) +{ + ER ercd; + switch ( wait ) { + case SLEEP: + case DELAY: + case SEMGET: + case MSGGET: + // do nothing for all of those + break; + case FLAGWAIT: + // clear the flag variable + ercd = clr_flg( 1, 0 ); + CYG_TEST_CHECK( E_OK == ercd, "clr_flg bad ercd, tidy vp" ); + break; + case MEMFIXEDGET: + if ( NULL != vp ) { + ercd = rel_blf( 1, vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd, tidy vp" ); + } + if ( NULL != vp1 ) { + ercd = rel_blf( 1, vp1 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd, tidy vp1" ); + } + if ( NULL != t2vp ) { + ercd = rel_blf( 1, t2vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd, tidy t2vp" ); + } + break; + case MEMVARGET: + if ( NULL != vp ) { + ercd = rel_blk( 1, vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd, tidy vp" ); + } + if ( NULL != vp1 ) { + ercd = rel_blk( 1, vp1 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd, tidy vp1" ); + } + if ( NULL != t2vp ) { + ercd = rel_blk( 1, t2vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd, tidy t2vp" ); + } + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } +} + +void +do_recreate( WAITOP wait ) +{ +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + static T_CSEM t_csem = { NULL, 0, 0 }; +#endif +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE + static T_CMBX t_cmbx = { NULL, 0 }; +#endif +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + static T_CFLG t_cflg = { NULL, 0, 0 }; +#endif +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + static T_CMPF t_cmpf = { NULL, 0, 20, 95 }; +#endif +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + static T_CMPL t_cmpl = { NULL, 0, 2000 }; +#endif + ER ercd = E_OK; + switch ( wait ) { + case SLEEP: + case DELAY: + // do nothing for all of those + break; + case SEMGET: +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + // create the semaphore + ercd = cre_sem( 1, &t_csem ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_recreate SEMGET" ); +#endif + break; + case FLAGWAIT: +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + // create the flag + ercd = cre_flg( 1, &t_cflg ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_recreate FLAGWAIT" ); +#endif + break; + case MSGGET: +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE + // create the mbox + ercd = cre_mbx( 1, &t_cmbx ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_recreate MSGGET" ); +#endif + break; + case MEMFIXEDGET: +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + // create the mempool + ercd = cre_mpf( 1, &t_cmpf ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_recreate MEMFIXEDGET" ); +#endif + break; + case MEMVARGET: +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + // create the mempool + ercd = cre_mpl( 1, &t_cmpl ); + CYG_TEST_CHECK( E_OK == ercd, "cre_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_recreate MEMVARGET" ); +#endif + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } + // this is just to use ercd to prevent warnings + CYG_TEST_CHECK( E_OK == ercd, " bad ercd" ); +} + + + +void +do_signal( WAITOP wait ) +{ + ER ercd; + switch ( wait ) { + case SLEEP: + // send a wakeup + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + break; + case DELAY: + // simply wait for task 2's delay to complete + ercd = dly_tsk( T1_WAIT ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + break; + case SEMGET: + // signal the semaphore + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + break; + case FLAGWAIT: + // set the flag bits + ercd = set_flg( 1, 0xff ); + CYG_TEST_CHECK( E_OK == ercd, "set_flg bad ercd" ); + break; + case MSGGET: + // send a message + ercd = snd_msg( 1, msg ); + CYG_TEST_CHECK( E_OK == ercd, "snd_msg bad ercd" ); + break; + case MEMFIXEDGET: + // release a couple of blocks we allocated earlier. I hope. + CYG_TEST_CHECK( NULL != vp, "no allocated block to free" ); + CYG_TEST_CHECK( NULL != vp1, "no allocated block to free1" ); + ercd = rel_blf( 1, vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + vp = NULL; + ercd = rel_blf( 1, vp1 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd1" ); + vp1 = NULL; + break; + case MEMVARGET: + // release a couple of blocks we allocated earlier. I hope. + CYG_TEST_CHECK( NULL != vp, "no allocated block to free" ); + CYG_TEST_CHECK( NULL != vp1, "no allocated block to free1" ); + ercd = rel_blk( 1, vp ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + vp = NULL; + ercd = rel_blk( 1, vp1 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd1" ); + vp1 = NULL; + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } +} + +void +do_delete( WAITOP wait ) +{ + ER ercd = E_OK; + switch ( wait ) { + case SLEEP: + case DELAY: + CYG_TEST_FAIL( "bad call to do_delete( SLEEP or DELAY )" ); + break; + case SEMGET: +#ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE + // delete the semaphore + ercd = del_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_sem bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_delete( SEMGET )" ); +#endif + break; + case FLAGWAIT: +#ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE + // delete the flag + ercd = del_flg( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_flg bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_delete( FLAGWAIT )" ); +#endif + break; + case MSGGET: +#ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE + // delete the mbox + ercd = del_mbx( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mbx bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_delete( MSGGET )" ); +#endif + break; + case MEMFIXEDGET: +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + // delete the mempool + ercd = del_mpf( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_delete( MEMFIXEDGET )" ); +#endif + break; + case MEMVARGET: +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + // delete the mempool + ercd = del_mpl( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); +#else + CYG_TEST_FAIL( "bad call to do_delete( MEMVARGET )" ); +#endif + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } + // this is just to use ercd to prevent warnings + CYG_TEST_CHECK( E_OK == ercd, " bad ercd" ); +} + + + +ER +do_wait( WAITOP wait, WAITTYPE type ) +{ + switch ( wait ) { + case SLEEP: + return ( PLAIN == type ) ? slp_tsk() : tslp_tsk( T2_WAIT ); + case DELAY: + return dly_tsk( T2_WAIT ); // forget the type + case SEMGET: + return ( PLAIN == type ) ? wai_sem( 1 ) : twai_sem( 1, T2_WAIT ); + case FLAGWAIT: + return ( PLAIN == type ) ? + wai_flg( &scratch, 1, 0x55, TWF_ANDW ) : + twai_flg( &scratch, 1, 0xaa, TWF_ANDW, T2_WAIT ); + case MSGGET: + return ( PLAIN == type ) ? + rcv_msg( &msg1, 1 ) : + trcv_msg( &msg1, 1, T2_WAIT ); + case MEMFIXEDGET: + return ( PLAIN == type ) ? + get_blf( &t2vp, 1 ) : + tget_blf( &t2vp, 1, T2_WAIT ); + case MEMVARGET: + return ( PLAIN == type ) ? + get_blk( &t2vp, 1, T2_MALLOC ) : + tget_blk( &t2vp, 1, T2_MALLOC, T2_WAIT ); + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } + CYG_TEST_FAIL( "Bad wait in do_wait" ); + return E_SYS; +} + +void +check_waitstate( WAITOP wait, int waiting ) +{ + ER ercd; + int waity = 0; + switch ( wait ) { + case SLEEP: + case DELAY: + return; // do nothing for these + case SEMGET: { + T_RSEM rsem; + ercd = ref_sem( &rsem, 1 ); + waity = rsem.wtsk; + break; + } + case FLAGWAIT: { + T_RFLG rflg; + ercd = ref_flg( &rflg, 1 ); + waity = rflg.wtsk; + break; + } + case MSGGET: { + T_RMBX rmbx; + ercd = ref_mbx( &rmbx, 1 ); + waity = rmbx.wtsk; + break; + } + case MEMFIXEDGET: { + T_RMPF rmpf; + ercd = ref_mpf( &rmpf, 1 ); + waity = rmpf.wtsk; + break; + } + case MEMVARGET: { + T_RMPL rmpl; + ercd = ref_mpl( &rmpl, 1 ); + waity = rmpl.wtsk; + break; + } + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } + if ( waiting ) + CYG_TEST_CHECK( waity, "Object has no task waiting!" ); + else + CYG_TEST_CHECK( !waity, "Object had a task waiting!" ); +} + +// ======================================================================== +void task1( unsigned int arg ) +{ + ER ercd; + WAITOP wait; + WAITTYPE type; + KILLOP kill; + + CYG_TEST_INFO( "Task 1 running" ); + + { + extern Cyg_Thread cyg_uitron_TASKS[]; + cyg_test_dump_thread_stack_stats( + "Startup, task1", &cyg_uitron_TASKS[ 0 ] ); + cyg_test_dump_thread_stack_stats( + "Startup, task2", &cyg_uitron_TASKS[ 1 ] ); + cyg_test_dump_interrupt_stack_stats( "Startup" ); + cyg_test_dump_idlethread_stack_stats( "Startup" ); + cyg_test_clear_interrupt_stack(); + } + + ercd = chg_pri( 1, 8 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + + for ( wait = START_WAITOP; wait < DONE_WAITOP ; wait++) { + for ( type = START_TYPE; type < DONE_TYPE ; type++ ) { + for ( kill = START_KILLOP; kill < DONE_KILLOP ; kill++ ) { + + // These clauses deal with a couple of special cases: + // [doing it this way helps keep the rest of the code + // nicely general and orthogonal] + // + // 1) DELAY: dly_tsk(): when this times out, the retcode is + // E_OK rather than E_TMOUT, and it always times out. The + // "signalling" method here is just to wait yourself. So we + // do not test DELAY with TIMED type. + // + // 2) PLAIN tests with TIMEOUT kill operations: a PLAIN test + // will not time out, it'll wait forever, so waiting for it + // so to do is pointless; further, we would check for the + // wrong error code. So we do not test PLAIN tests with + // TIMOUT kill operations. + // + // 3) SLEEP or DELAY tests with DELETE operations: there is + // no synchronization to delete in those cases. + // 3a) Individual object types are tested for delete support, + // and if there is none, the test is skipped. + + if ( DELAY == wait && TIMED == type ) + continue; + + if ( PLAIN == type && + ( ( TIMEOUT == kill) || + (SUSPEND_TIMEOUT_RESUME == kill) || + (SUSPEND_TIMEOUT_KILL == kill) ) ) + continue; + + if ( ( +#ifndef CYGPKG_UITRON_SEMAS_CREATE_DELETE + (SEMGET == wait) || +#endif +#ifndef CYGPKG_UITRON_FLAGS_CREATE_DELETE + (FLAGWAIT == wait) || +#endif +#ifndef CYGPKG_UITRON_MBOXES_CREATE_DELETE + (MSGGET == wait) || +#endif +#ifndef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + (MEMFIXEDGET == wait) || +#endif +#ifndef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + (MEMVARGET == wait) || +#endif + (SLEEP == wait) || + (DELAY == wait) + ) && + ((DELETE == kill) || + (SUSPEND_DELETE_RESUME == kill) || + (SUSPEND_DELETE_KILL == kill)) ) + continue; + + + CYG_TEST_INFO( makemsg( "T1: ", wait, type, kill ) ); + + intercom = 0; + + // prepare the synchronization objects + // (actually, just empty the mempools) + do_prep( wait ); + + // start task 2 at a higher priority than myself + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 2, task2arg( wait, type, kill ) ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 2, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + // task 2 should run now, until it waits. + + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_WAI == rtsk.tskstat, "bad tskstat" ); + CYG_TEST_CHECK( 5 == rtsk.tskpri, "bad tskpri" ); + + switch ( kill ) { + case SIGNAL: + // signal the task appropriately + do_signal( wait ); + // it should now have run to completion + break; + case TIMEOUT: + check_waitstate( wait, 1 ); + // wait for the timeout to occur + ercd = dly_tsk( T1_WAIT ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + check_waitstate( wait, 0 ); + // it should now have run to completion + break; + case RELEASE: + // hit the task with a release-wait + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_wai bad ercd" ); + // it should now have run to completion + break; + case DELETE: + // delete the object appropriately + do_delete( wait ); + // it should now have run to completion + break; + case KILL: + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + case SUSPEND_SIGNAL_RESUME: + // suspend the task + do_suspend(); + // signal the task appropriately + do_signal( wait ); + // resume the task + do_resume(); + // it should now have run to completion + break; + case SUSPEND_TIMEOUT_RESUME: + check_waitstate( wait, 1 ); + // suspend the task + do_suspend(); + check_waitstate( wait, 1 ); + // wait for the timeout to occur + ercd = dly_tsk( T1_WAIT ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + check_waitstate( wait, 0 ); + // resume the task + do_resume(); + // it should now have run to completion + break; + case SUSPEND_RELEASE_RESUME: + // suspend the task + do_suspend(); + // hit the task with a release-wait + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_wai bad ercd" ); + // resume the task + do_resume(); + // it should now have run to completion + break; + case SUSPEND_DELETE_RESUME: + // suspend the task + do_suspend(); + // delete the object appropriately + do_delete( wait ); + // resume the task + do_resume(); + // it should now have run to completion + break; + case SUSPEND_KILL: + // suspend the task + do_suspend(); + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + case SUSPEND_SIGNAL_KILL: + // suspend the task + do_suspend(); + // signal the task appropriately + do_signal( wait ); + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + case SUSPEND_TIMEOUT_KILL: + check_waitstate( wait, 1 ); + // suspend the task + do_suspend(); + check_waitstate( wait, 1 ); + // wait for the timeout to occur + ercd = dly_tsk( T1_WAIT ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + check_waitstate( wait, 0 ); + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + case SUSPEND_RELEASE_KILL: + // suspend the task + do_suspend(); + // hit the task with a release-wait + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "rel_wai bad ercd" ); + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + case SUSPEND_DELETE_KILL: + // suspend the task + do_suspend(); + // delete the object appropriately + do_delete( wait ); + // kill the task + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + // it should now have terminated without running + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } + + // task 2 should be dormant now, however it got there + ercd = ref_tsk( &rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_DMT == rtsk.tskstat, "bad tskstat" ); + + if ( (SUSPEND_SIGNAL_KILL == kill) && + ((MEMFIXEDGET == wait) || (MEMVARGET == wait)) ) { + // it was a killed successful memory alloc, so we have + // lost the pointer to memory allocated; there is an + // implicit storeleak problem when the task trying + // to allocate is signalled then killed. + // Recreate the pointer from an old version: + CYG_TEST_CHECK( NULL == t2vp, "t2vp WAS allocated!" ); + t2vp = t2vp_backup; + } + + switch ( kill ) { + case KILL: + case SUSPEND_KILL: + case SUSPEND_SIGNAL_KILL: + case SUSPEND_TIMEOUT_KILL: + case SUSPEND_RELEASE_KILL: + case SUSPEND_DELETE_KILL: + // if task 2 was killed, expect only one increment + CYG_TEST_CHECK( 1 == intercom, "intercom bad value !1" ); + break; + default: + // otherwise expect two increments + CYG_TEST_CHECK( 2 == intercom, "intercom bad value !2" ); + break; + } + + // tidy up or recreate the synchronization objects + if ( (DELETE == kill) || + (SUSPEND_DELETE_RESUME == kill) || + (SUSPEND_DELETE_KILL == kill) ) + do_recreate( wait ); + else + do_tidyup( wait ); + } + } + } + CYG_TEST_PASS("synchronization interaction tests"); + + { + extern Cyg_Thread cyg_uitron_TASKS[]; + cyg_test_dump_thread_stack_stats( + "All done, task1", &cyg_uitron_TASKS[ 0 ] ); + cyg_test_dump_thread_stack_stats( + "All done, task2", &cyg_uitron_TASKS[ 1 ] ); + cyg_test_dump_interrupt_stack_stats( "All done" ); + cyg_test_dump_idlethread_stack_stats( "All done" ); + } + // all done + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + WAITOP wait; + WAITTYPE waittype; + KILLOP kill; + + decodearg( arg, &wait, &waittype, &kill ); + +// CYG_TEST_INFO( makemsg( " 2: ", wait, waittype, kill ) ); + + intercom++; + ercd = do_wait( wait, waittype ); + intercom++; + + switch ( kill ) { + case SIGNAL: + case SUSPEND_SIGNAL_RESUME: + // we expect to have been signalled correctly + CYG_TEST_CHECK( E_OK == ercd, "T2 wait bad ercd" ); + // here we know that the op completed OK + if ( (MEMFIXEDGET == wait) || (MEMVARGET == wait) ) { + // it was a successful memory alloc of whichever type, + // so we can save away a copy of t2vp for working round an + // implicit storeleak problem when the task trying to allocate + // is signalled then killed: + CYG_TEST_CHECK( NULL != t2vp, "No t2vp allocated!" ); + t2vp_backup = t2vp; + } + break; + case TIMEOUT: + case SUSPEND_TIMEOUT_RESUME: + // we expect to have timed out - if it's a timeout op. + CYG_TEST_CHECK( E_TMOUT == ercd, "T2 timeout bad ercd, !E_TMOUT" ); + break; + case RELEASE: + case SUSPEND_RELEASE_RESUME: + // we expect to have suffered a release wait. + CYG_TEST_CHECK( E_RLWAI == ercd, "T2 release bad ercd, !E_RLWAI" ); + break; + case DELETE: + case SUSPEND_DELETE_RESUME: + // we expect to be told the object is gone + CYG_TEST_CHECK( E_DLT == ercd, "T2 release bad ercd, !E_DLT" ); + break; + case KILL: + case SUSPEND_KILL: + case SUSPEND_SIGNAL_KILL: + case SUSPEND_TIMEOUT_KILL: + case SUSPEND_RELEASE_KILL: + case SUSPEND_DELETE_KILL: + // we expect to have been killed here, ie. this won't execute! + CYG_TEST_FAIL( "Task 2 ran to completion!" ); + break; + default: + CYG_TEST_FAIL( "bad switch" ); + break; + } +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF testcx7.cxx diff --git a/packages/compat/uitron/v2_0/tests/testcx8.cxx b/packages/compat/uitron/v2_0/tests/testcx8.cxx new file mode 100644 index 00000000..cb6eb413 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/testcx8.cxx @@ -0,0 +1,395 @@ +//=========================================================================== +// +// testcx8.cxx +// +// uITRON "C++" test program eight +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-10-14 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough semaphores */ \ + defined( CYGPKG_UITRON_SEMAS ) && \ + (CYGNUM_UITRON_SEMAS >= 3) && \ + (CYGNUM_UITRON_SEMAS < 90) && \ + ( !defined(CYGPKG_UITRON_SEMAS_CREATE_DELETE) || \ + CYGNUM_UITRON_SEMAS_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +volatile int intercount = 0; +INT scratch; + +void newtask( unsigned int arg ); + +T_CTSK t_ctsk = { NULL, 0, (FP)&newtask, 1, CYGNUM_UITRON_STACK_SIZE }; +T_RTSK t_rtsk; + +extern "C" { + void task1( unsigned int arg ); + void task2( unsigned int arg ); + void task3( unsigned int arg ); + void task4( unsigned int arg ); +} + +void task1( unsigned int arg ) +{ + ER ercd; + + CYG_TEST_INFO( "Task 1 running" ); + + // change us to prio 3 for flexibility + ercd = chg_pri( 0, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + +#ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE + // first, check that we can delete a task: +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_tsk( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_tsk bad ercd !E_ID" ); + ercd = del_tsk( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_tsk bad ercd !E_ID" ); + ercd = cre_tsk( -6, &t_ctsk ); + CYG_TEST_CHECK( E_ID == ercd, "cre_tsk bad ercd !E_ID" ); + ercd = cre_tsk( 99, &t_ctsk ); + CYG_TEST_CHECK( E_ID == ercd, "cre_tsk bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + ercd = cre_tsk( 2, &t_ctsk ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_tsk bad ercd !E_OBJ" ); + // try a pre-existing object - ourselves! + ercd = cre_tsk( 1, &t_ctsk ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_tsk bad ercd !E_OBJ" ); + // try deleting an active task + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 2, 22222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 2, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + // Task 2 is now ready-to-run, lower prio than us + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "del_tsk bad ercd !E_OBJ" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + // Task 2 is now sleeping + CYG_TEST_CHECK( 1 == intercount, "bad intercount !1" ); + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "del_tsk bad ercd !E_OBJ" ); + // try deleting a running task - ourselves! + ercd = del_tsk( 1 ); + CYG_TEST_CHECK( E_OBJ == ercd, "del_tsk bad ercd !E_OBJ" ); + // terminate task 2; should then be OK to delete it + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + CYG_TEST_CHECK( 1 == intercount, "bad intercount !1" ); + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_tsk bad ercd" ); + CYG_TEST_CHECK( 1 == intercount, "bad intercount !1" ); + // and check it is deleted + ercd = sta_tsk( 2, 99 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sta_tsk bad ercd !E_NOEXS" ); + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ter_tsk bad ercd !E_NOEXS" ); + ercd = chg_pri( 2, 6 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "chg_pri bad ercd !E_NOEXS" ); + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "rel_wai bad ercd !E_NOEXS" ); + ercd = sus_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sus_tsk bad ercd !E_NOEXS" ); + ercd = rsm_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "rsm_tsk bad ercd !E_NOEXS" ); + ercd = frsm_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "frsm_tsk bad ercd !E_NOEXS" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "wup_tsk bad ercd !E_NOEXS" ); + ercd = can_wup( &scratch, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "can_wup bad ercd !E_NOEXS" ); + ercd = ref_tsk( &t_rtsk, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_tsk bad ercd !E_NOEXS" ); + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "del_tsk bad ercd !E_NOEXS" ); + // recreate task2, with the same function + t_ctsk.task = (FP)&task2; + t_ctsk.itskpri = 7; + ercd = cre_tsk( 2, &t_ctsk ); + CYG_TEST_CHECK( E_OK == ercd, "cre_tsk bad ercd" ); + ercd = ref_tsk( &t_rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( 7 == t_rtsk.tskpri, "Bad tskpri in new task2 !7" ); + CYG_TEST_CHECK( TTS_DMT == t_rtsk.tskstat, + "Bad tskstat in new task2 !TTS_DMT" ); + CYG_TEST_CHECK( 1 == intercount, "bad intercount !1" ); + // now start the task and do the same lot again... + ercd = cre_tsk( 2, &t_ctsk ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_tsk bad ercd !E_OBJ" ); + // try deleting an active task + ercd = sta_tsk( 2, 22222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + // Task 2 is now ready-to-run, lower prio than us + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "del_tsk bad ercd !E_OBJ" ); + CYG_TEST_CHECK( 1 == intercount, "bad intercount !1" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 2 == intercount, "bad intercount !2" ); + // Task 2 is now sleeping + ercd = ref_tsk( &t_rtsk, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( 7 == t_rtsk.tskpri, "Bad tskpri in new task2 !7" ); + CYG_TEST_CHECK( TTS_WAI == t_rtsk.tskstat, + "Bad tskstat in new task2 !TTS_WAI" ); + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "del_tsk bad ercd !E_OBJ" ); + // up its priority + ercd = chg_pri( 2, 1 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + // awaken task 2; it will then exit-and-delete itself: + CYG_TEST_CHECK( 2 == intercount, "bad intercount !2" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "bad intercount !3" ); + // and check it is deleted + ercd = sta_tsk( 2, 99 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sta_tsk bad ercd !E_NOEXS" ); + CYG_TEST_CHECK( 3 == intercount, "bad intercount !3" ); + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ter_tsk bad ercd !E_NOEXS" ); + ercd = chg_pri( 2, 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "chg_pri bad ercd !E_NOEXS" ); + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "rel_wai bad ercd !E_NOEXS" ); + ercd = sus_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "sus_tsk bad ercd !E_NOEXS" ); + ercd = rsm_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "rsm_tsk bad ercd !E_NOEXS" ); + ercd = frsm_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "frsm_tsk bad ercd !E_NOEXS" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "wup_tsk bad ercd !E_NOEXS" ); + ercd = can_wup( &scratch, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "can_wup bad ercd !E_NOEXS" ); + ercd = ref_tsk( &t_rtsk, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_tsk bad ercd !E_NOEXS" ); + CYG_TEST_CHECK( 3 == intercount, "bad intercount !3" ); + ercd = del_tsk( 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "del_tsk bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_tsk( 2, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_tsk bad ercd !E_PAR" ); +#endif + t_ctsk.stksz = 0x40000000; + ercd = cre_tsk( 2, &t_ctsk ); + CYG_TEST_CHECK( E_NOMEM == ercd, "cre_tsk bad ercd !E_NOMEM" ); + t_ctsk.stksz = CYGNUM_UITRON_STACK_SIZE; + CYG_TEST_CHECK( 3 == intercount, "bad intercount !3" ); +#endif // we can test bad param error returns + + ercd = del_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_tsk bad ercd" ); + t_ctsk.task = (FP)&task4; + t_ctsk.itskpri = 9; + ercd = cre_tsk( 3, &t_ctsk ); + CYG_TEST_CHECK( E_OK == ercd, "cre_tsk bad ercd" ); + // check we can delete it again immediately + ercd = del_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_tsk bad ercd" ); + ercd = ref_tsk( &t_rtsk, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_tsk bad ercd !E_NOEXS" ); + t_ctsk.task = (FP)&newtask; + t_ctsk.itskpri = 1; + ercd = cre_tsk( 3, &t_ctsk ); + CYG_TEST_CHECK( E_OK == ercd, "cre_tsk bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "bad intercount !3" ); + ercd = sta_tsk( 3, 999 ); + CYG_TEST_CHECK( E_OK == ercd, "cre_tsk bad ercd" ); + // it should have run now, and exited + CYG_TEST_CHECK( 5 == intercount, "bad intercount !5" ); + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + // and check that it will just run again... + ercd = sta_tsk( 3, 999 ); + CYG_TEST_CHECK( E_OK == ercd, "cre_tsk bad ercd" ); + // it should have run now, and exited + CYG_TEST_CHECK( 7 == intercount, "bad intercount !7" ); + ercd = wai_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + // all done. + + CYG_TEST_PASS("create/delete tasks"); + + // all done + CYG_TEST_EXIT( "All done" ); +#else // ! CYGPKG_UITRON_TASKS_CREATE_DELETE + CYG_TEST_NA( "Tasks do not have create/delete enabled" ); +#endif // ! CYGPKG_UITRON_TASKS_CREATE_DELETE + ext_tsk(); +} + + + +void newtask( unsigned int arg ) +{ + ER ercd; + int i; + CYG_TEST_INFO( "Newtask running" ); + CYG_TEST_CHECK( 999 == arg, "Bad arg to newtask() !999" ); + ercd = get_tid( &i ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 3 == i, "tid not 3" ); + intercount++; + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem bad ercd" ); + intercount++; + // and just return +} + +void task2( unsigned int arg ) +{ + ER ercd; + int i; + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &i ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == i, "tid not 2" ); + if ( 22222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 22222" ); + + intercount++; + + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + + intercount++; + + exd_tsk(); // if we are not killed first + + intercount++; // shouldn't happen +} + +void task3( unsigned int arg ) +{ + CYG_TEST_FAIL( "How come I'm being run?" ); +} + +void task4( unsigned int arg ) +{ + CYG_TEST_FAIL( "How come I'm being run?" ); +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF testcx8.cxx diff --git a/packages/compat/uitron/v2_0/tests/testcx9.cxx b/packages/compat/uitron/v2_0/tests/testcx9.cxx new file mode 100644 index 00000000..d8c38c20 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/testcx9.cxx @@ -0,0 +1,492 @@ +//=========================================================================== +// +// testcx9.cxx +// +// uITRON "C++" test program nine +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-10-16 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* test configuration for enough fixed memory pools */ \ + defined( CYGPKG_UITRON_MEMPOOLFIXED ) && \ + (CYGNUM_UITRON_MEMPOOLFIXED >= 3) && \ + (CYGNUM_UITRON_MEMPOOLFIXED < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLFIXED_INITIALLY >= 3 ) && \ + \ + /* test configuration for enough variable mempools */ \ + defined( CYGPKG_UITRON_MEMPOOLVAR ) && \ + (CYGNUM_UITRON_MEMPOOLVAR >= 3) && \ + (CYGNUM_UITRON_MEMPOOLVAR < 90) && \ + ( !defined(CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE) || \ + CYGNUM_UITRON_MEMPOOLVAR_INITIALLY >= 3 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +VP vp; + +T_CMPL t_cmpl = { NULL, 0, 1000 }; +T_RMPL t_rmpl; +T_CMPF t_cmpf = { NULL, 0, 10, 100 }; +T_RMPF t_rmpf; + + +extern "C" { + void task1( unsigned int arg ); + void task2( unsigned int arg ); + void task3( unsigned int arg ); + void task4( unsigned int arg ); +} + +void task1( unsigned int arg ) +{ + ER ercd; + int tests = 0; + + CYG_TEST_INFO( "Task 1 running" ); + + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 2, 22222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 2, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + tests++; +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_mpf( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mpf bad ercd !E_ID" ); + ercd = del_mpf( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mpf bad ercd !E_ID" ); + ercd = cre_mpf( -6, &t_cmpf ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mpf bad ercd !E_ID" ); + ercd = cre_mpf( 99, &t_cmpf ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mpf bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + // [first get a valid block from it for the freeing test later] + ercd = pget_blf( &vp, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blf bad ercd" ); + ercd = cre_mpf( 3, &t_cmpf ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_mpf bad ercd !E_OBJ" ); + // delete it so we can play + ercd = del_mpf( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); + // check it is deleted + ercd = rel_blf( 3, vp ); // vp did come from this pool + CYG_TEST_CHECK( E_NOEXS == ercd, "rel_blf bad ercd !E_NOEXS" ); + ercd = pget_blf( &vp, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blf bad ercd !E_NOEXS" ); + ercd = tget_blf( &vp, 3, 10 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "tget_blf bad ercd !E_NOEXS" ); + ercd = get_blf( &vp, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blf bad ercd !E_NOEXS" ); + ercd = ref_mpf( &t_rmpf, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_mpf bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_mpf( 3, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_mpf bad ercd !E_PAR" ); +#endif + t_cmpf.mpfatr = 0xfff; + ercd = cre_mpf( 3, &t_cmpf ); + CYG_TEST_CHECK( E_RSATR == ercd, "cre_mpf bad ercd !E_RSATR" ); +#endif // we can test bad param error returns + t_cmpf.mpfatr = 0; + t_cmpf.mpfcnt = 10000; + t_cmpf.blfsz = 100; + ercd = cre_mpf( 3, &t_cmpf ); + CYG_TEST_CHECK( E_NOMEM == ercd, "cre_mpf bad ercd" ); + t_cmpf.mpfcnt = 100; + t_cmpf.blfsz = 100000; + ercd = cre_mpf( 3, &t_cmpf ); + CYG_TEST_CHECK( E_NOMEM == ercd, "cre_mpf bad ercd" ); + // now create it well + t_cmpf.mpfatr = 0; + t_cmpf.mpfcnt = 10; + t_cmpf.blfsz = 100; + ercd = cre_mpf( 3, &t_cmpf ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpf bad ercd" ); + // and check we can use it + ercd = pget_blf( &vp, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blf bad ercd" ); + ercd = tget_blf( &vp, 3, 10 ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blf bad ercd" ); + ercd = get_blf( &vp, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "get_blf bad ercd" ); + ercd = rel_blf( 3, vp ); // vp did come from new pool + CYG_TEST_CHECK( E_OK == ercd, "rel_blf bad ercd" ); + ercd = rel_blf( 3, vp ); // vp already freed + CYG_TEST_CHECK( E_PAR == ercd, "rel_blf bad ercd !E_PAR" ); + ercd = ref_mpf( &t_rmpf, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpf bad ercd" ); + + // In order to wait on the pools, we must first consume all they have: + while ( E_OK == (ercd = pget_blf( &vp, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + while ( E_OK == (ercd = tget_blf( &vp, 2, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf bad ercd !E_TMOUT" ); + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = get_blf( &vp, 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "get_blf bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = tget_blf( &vp, 2, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "tget_blf bad ercd !E_DLT" ); + // check they are deleted + ercd = get_blf( &vp, 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blf bad ercd !E_NOEXS" ); + ercd = pget_blf( &vp, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blf bad ercd !E_NOEXS" ); + + // re-create and do it again + t_cmpf.mpfcnt = 90; + t_cmpf.blfsz = 20; + ercd = cre_mpf( 1, &t_cmpf ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpf bad ercd" ); + t_cmpf.mpfcnt = 5; + t_cmpf.blfsz = 200; + ercd = cre_mpf( 2, &t_cmpf ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpf bad ercd" ); + + // In order to wait on the pools, we must first consume all they have: + while ( E_OK == (ercd = pget_blf( &vp, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blf bad ercd !E_TMOUT" ); + while ( E_OK == (ercd = tget_blf( &vp, 2, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blf bad ercd !E_TMOUT" ); + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = get_blf( &vp, 1 ); + CYG_TEST_CHECK( E_DLT == ercd, "get_blf bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = tget_blf( &vp, 2, 10 ); + CYG_TEST_CHECK( E_DLT == ercd, "tget_blf bad ercd !E_DLT" ); + // check they are deleted + ercd = tget_blf( &vp, 1, 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blf bad ercd !E_NOEXS" ); + ercd = get_blf( &vp, 2 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blf bad ercd !E_NOEXS" ); + + CYG_TEST_PASS("create/delete fixed mempools"); +#endif // CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + tests++; +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = del_mpl( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mpl bad ercd !E_ID" ); + ercd = del_mpl( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "del_mpl bad ercd !E_ID" ); + ercd = cre_mpl( -6, &t_cmpl ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mpl bad ercd !E_ID" ); + ercd = cre_mpl( 99, &t_cmpl ); + CYG_TEST_CHECK( E_ID == ercd, "cre_mpl bad ercd !E_ID" ); +#endif // we can test bad param error returns + // try a pre-existing object + // [first get a valid block from it for the freeing test later] + ercd = pget_blk( &vp, 3, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blk bad ercd" ); + ercd = cre_mpl( 3, &t_cmpl ); + CYG_TEST_CHECK( E_OBJ == ercd, "cre_mpl bad ercd !E_OBJ" ); + // delete it so we can play + ercd = del_mpl( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); + // check it is deleted + ercd = rel_blk( 3, vp ); // vp did come from this pool + CYG_TEST_CHECK( E_NOEXS == ercd, "rel_blk bad ercd !E_NOEXS" ); + ercd = pget_blk( &vp, 3, 100 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blk bad ercd !E_NOEXS" ); + ercd = tget_blk( &vp, 3, 100, 10 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "tget_blk bad ercd !E_NOEXS" ); + ercd = get_blk( &vp, 3, 100 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blk bad ercd !E_NOEXS" ); + ercd = ref_mpl( &t_rmpl, 3 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "ref_mpl bad ercd !E_NOEXS" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + // now try creating it (badly) +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = cre_mpl( 3, NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "cre_mpl bad ercd !E_PAR" ); +#endif + t_cmpl.mplatr = 0xfff; + ercd = cre_mpl( 3, &t_cmpl ); + CYG_TEST_CHECK( E_RSATR == ercd, "cre_mpl bad ercd !E_RSATR" ); +#endif // we can test bad param error returns + t_cmpl.mplatr = 0; + t_cmpl.mplsz = 100000000; + ercd = cre_mpl( 3, &t_cmpl ); + CYG_TEST_CHECK( E_NOMEM == ercd, "cre_mpl bad ercd" ); + // now create it well + t_cmpl.mplatr = 0; + t_cmpl.mplsz = 1000; + ercd = cre_mpl( 3, &t_cmpl ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpl bad ercd" ); + // and check we can use it + ercd = pget_blk( &vp, 3, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "pget_blk bad ercd" ); + ercd = pget_blk( &vp, 3, 100000000 ); // way too large + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + ercd = tget_blk( &vp, 3, 100, 10 ); + CYG_TEST_CHECK( E_OK == ercd, "tget_blk bad ercd" ); + ercd = get_blk( &vp, 3, 100 ); + CYG_TEST_CHECK( E_OK == ercd, "get_blk bad ercd" ); + ercd = rel_blk( 3, vp ); // vp did come from new pool + CYG_TEST_CHECK( E_OK == ercd, "rel_blk bad ercd" ); + ercd = rel_blk( 3, vp ); // vp already freed + CYG_TEST_CHECK( E_PAR == ercd, "rel_blk bad ercd !E_PAR" ); + ercd = ref_mpl( &t_rmpl, 3 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_mpl bad ercd" ); + + // In order to wait on the pools, we must first consume all they have: + while ( E_OK == (ercd = pget_blk( &vp, 1, 100 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + while ( E_OK == (ercd = tget_blk( &vp, 2, 100, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk bad ercd !E_TMOUT" ); + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = get_blk( &vp, 1, 200 ); + CYG_TEST_CHECK( E_DLT == ercd, "get_blk bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = tget_blk( &vp, 2, 100, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "tget_blk bad ercd !E_DLT" ); + // check they are deleted + ercd = get_blk( &vp, 1, 200 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blk bad ercd !E_NOEXS" ); + ercd = pget_blk( &vp, 2, 20 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blk bad ercd !E_NOEXS" ); + + // re-create and do it again + ercd = cre_mpl( 1, &t_cmpl ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpl bad ercd" ); + ercd = cre_mpl( 2, &t_cmpl ); + CYG_TEST_CHECK( E_OK == ercd, "cre_mpl bad ercd" ); + + // In order to wait on the pools, we must first consume all they have: + while ( E_OK == (ercd = pget_blk( &vp, 1, 20 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "pget_blk bad ercd !E_TMOUT" ); + while ( E_OK == (ercd = tget_blk( &vp, 2, 400, 1 )) ) /* nothing */; + CYG_TEST_CHECK( E_TMOUT == ercd, "tget_blk bad ercd !E_TMOUT" ); + // now wait while task 2 deletes the wait objects + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = get_blk( &vp, 1, 200 ); + CYG_TEST_CHECK( E_DLT == ercd, "get_blk bad ercd !E_DLT" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = tget_blk( &vp, 2, 500, 20 ); + CYG_TEST_CHECK( E_DLT == ercd, "tget_blk bad ercd !E_DLT" ); + // check they are deleted + ercd = tget_blk( &vp, 1, 200, 1 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "get_blk bad ercd !E_NOEXS" ); + ercd = get_blk( &vp, 2, 20 ); + CYG_TEST_CHECK( E_NOEXS == ercd, "pget_blk bad ercd !E_NOEXS" ); + + CYG_TEST_PASS("create/delete variable mempools"); +#endif // CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + + ercd = ter_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ter_tsk bad ercd" ); + ercd = dly_tsk( 5 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + // all done + if ( 0 == tests ) { + CYG_TEST_NA( "No objects have create/delete enabled" ); + } + else { + CYG_TEST_EXIT( "All done" ); + } + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + int i; + CYG_TEST_INFO( "Task 2 running" ); + ercd = get_tid( &i ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == i, "tid not 2" ); + if ( 22222 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 22222" ); + + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + +#ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + ercd = del_mpf( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpf( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpf( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpf( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpf bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); +#endif // CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE + +#ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + ercd = del_mpl( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpl( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpl( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + ercd = del_mpl( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "del_mpl bad ercd" ); + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); +#endif // CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE + + // we expect task2 to be killed here + CYG_TEST_FAIL( "Task 2 ran to completion!" ); +} + +void task3( unsigned int arg ) +{ +} + +void task4( unsigned int arg ) +{ +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF testcx9.cxx diff --git a/packages/compat/uitron/v2_0/tests/testcxx.cxx b/packages/compat/uitron/v2_0/tests/testcxx.cxx new file mode 100644 index 00000000..b19051c0 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/testcxx.cxx @@ -0,0 +1,817 @@ +//=========================================================================== +// +// testcxx.cxx +// +// uITRON "C++" test program +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1998-03-13 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + + + +#include // uITRON + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + cyg_uitron_start(); +} + +volatile int intercom = 0; +volatile int intercount = 0; +INT scratch = 0; + +extern "C" { + void task1( unsigned int arg ); + void task2( unsigned int arg ); + void task3( unsigned int arg ); + void task4( unsigned int arg ); +} + + +#ifndef CYGSEM_KERNEL_SCHED_TIMESLICE +#define TIMESLICEMSG "Assuming no kernel timeslicing" +#define TSGO() (1) +#define TSRELEASE() CYG_EMPTY_STATEMENT +#define TSSTOP() CYG_EMPTY_STATEMENT +#define TSLOCK() CYG_EMPTY_STATEMENT +#define TSUNLOCK() CYG_EMPTY_STATEMENT +#define ICWAIT( _i_ ) CYG_EMPTY_STATEMENT + +#else +// Now follow some nasty bodges to control the scheduling when basically it +// isn't controlled ie. timeslicing is on. It's bodgy because we're +// testing normal synchronization methods, so we shouldn't rely on them for +// comms between threads here. Instead there's a mixture of communicating +// via a flag (ts_interlock) which stops the "controlled" thread running +// away, and waiting for the controlled thread to run enough for us. +// +// Tasks 3 and 4 are waited for by the control task: task 3 locks the +// scheduler so is immediately descheduled when it unlocks it, task 4 does +// waiting-type operations, so we must give it chance to run by yielding a +// few times ourselves. Note the plain constant in ICWAIT() below. + +#define TIMESLICEMSG "Assuming kernel timeslicing ENABLED" +volatile int ts_interlock = 0; +#define TSGO() (ts_interlock) +#define TSRELEASE() ts_interlock = 1 +#define TSSTOP() ts_interlock = 0 + +#define TSLOCK() CYG_MACRO_START \ + ER ercd2 = dis_dsp(); \ + CYG_TEST_CHECK( E_OK == ercd2, "dis_dsp (TSLOCK) bad ercd2" ); \ +CYG_MACRO_END + +#define TSUNLOCK() CYG_MACRO_START \ + ER ercd3 = ena_dsp(); \ + CYG_TEST_CHECK( E_OK == ercd3, "ena_dsp (TSUNLOCK) bad ercd3" ); \ +CYG_MACRO_END + +#define ICWAIT( _i_ ) CYG_MACRO_START \ + int loops; \ + for ( loops = 3; (0 < loops) || ((_i_) > intercount); loops-- ) { \ + ER ercd4 = rot_rdq( 0 ); /* yield */ \ + CYG_TEST_CHECK( E_OK == ercd4, "rot_rdq (ICWAIT) bad ercd4" ); \ + } \ +CYG_MACRO_END +#endif // CYGSEM_KERNEL_SCHED_TIMESLICE + +/* +#define IC() \ +CYG_MACRO_START \ + static char *msgs[] = { "ZERO", "ONE", "TWO", "THREE", "FOUR", "LOTS" }; \ + CYG_TEST_INFO( msgs[ intercount > 5 ? 5 : intercount ] ); \ +CYG_MACRO_END +*/ + +// #define CYG_TEST_UITRON_TEST1_LOOPING 1 + +void task1( unsigned int arg ) +{ + ER ercd; + T_RTSK ref_tskd; + +#ifdef CYG_TEST_UITRON_TEST1_LOOPING + while ( 1 ) { +#endif // CYG_TEST_UITRON_TEST1_LOOPING + + CYG_TEST_INFO( "Task 1 running" ); + CYG_TEST_INFO( TIMESLICEMSG ); + + intercom = 0; + intercount = 0; + + CYG_TEST_INFO( "Testing get_tid and ref_tsk" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 1 == scratch, "tid not 1" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = get_tid( NULL ); + CYG_TEST_CHECK( E_PAR == ercd, "get_tid bad ercd !E_PAR" ); +#endif + ercd = ref_tsk( &ref_tskd, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_tsk bad ercd !E_ID" ); + ercd = ref_tsk( &ref_tskd, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "ref_tsk bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = ref_tsk( NULL, 1 ); + CYG_TEST_CHECK( E_PAR == ercd, "ref_tsk bad ercd !E_PAR" ); +#endif +#endif // we can test bad param error returns + ercd = ref_tsk( &ref_tskd, 1 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_RUN == ref_tskd.tskstat, "Bad task status 1" ); + ercd = ref_tsk( &ref_tskd, 0 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_RUN == ref_tskd.tskstat, "Bad task status 0" ); + ercd = ref_tsk( &ref_tskd, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_DMT == ref_tskd.tskstat, "Bad task status 2" ); + CYG_TEST_CHECK( 2 == ref_tskd.tskpri, "Bad task prio 2" ); + + ercd = rsm_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rsm_tsk DMT bad ercd !E_OBJ" ); + ercd = frsm_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "frsm_tsk DMT bad ercd !E_OBJ" ); + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai DMT bad ercd !E_OBJ" ); + ercd = sus_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "sus_tsk DMT bad ercd !E_OBJ" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "wup_tsk DMT bad ercd !E_OBJ" ); + ercd = can_wup( &scratch, 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "can_wup DMT bad ercd !E_OBJ" ); + + CYG_TEST_PASS( "get_tid, ref_tsk" ); + + CYG_TEST_INFO( "Testing prio change and start task" ); + ercd = sta_tsk( 2, 99 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + + // drop pri of task 2 + ercd = chg_pri( 2, 4 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ref_tsk( &ref_tskd, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( TTS_RDY == ref_tskd.tskstat, "Bad task status 2" ); + CYG_TEST_CHECK( 4 == ref_tskd.tskpri, "Bad task prio 2" ); + + // drop our pri below task 2 + ercd = chg_pri( 0, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + + ercd = ref_tsk( &ref_tskd, 1 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( 5 == ref_tskd.tskpri, "Bad task prio 1" ); + ercd = ref_tsk( &ref_tskd, 0 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + CYG_TEST_CHECK( 5 == ref_tskd.tskpri, "Bad task prio 0" ); + ercd = ref_tsk( &ref_tskd, 2 ); + CYG_TEST_CHECK( E_OK == ercd, "ref_tsk bad ercd" ); + // it will have run to completion and regained its original prio + CYG_TEST_CHECK( 2 == ref_tskd.tskpri, "Bad task prio 2" ); + CYG_TEST_CHECK( TTS_DMT == ref_tskd.tskstat, "Bad task status 2" ); + + // retest these now that the task has executed once + ercd = rsm_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rsm_tsk DMT bad ercd !E_OBJ" ); + ercd = frsm_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "frsm_tsk DMT bad ercd !E_OBJ" ); + ercd = rel_wai( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "rel_wai DMT bad ercd !E_OBJ" ); + ercd = sus_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "sus_tsk DMT bad ercd !E_OBJ" ); + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "wup_tsk DMT bad ercd !E_OBJ" ); + ercd = can_wup( &scratch, 2 ); + CYG_TEST_CHECK( E_OBJ == ercd, "can_wup DMT bad ercd !E_OBJ" ); + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = chg_pri( -6, 9 ); + CYG_TEST_CHECK( E_ID == ercd, "chg_pri bad ercd !E_ID" ); + ercd = chg_pri( 99, 9 ); + CYG_TEST_CHECK( E_ID == ercd, "chg_pri bad ercd !E_ID" ); + ercd = sta_tsk( -6, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "sta_tsk bad ercd !E_ID" ); + ercd = sta_tsk( 99, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "sta_tsk bad ercd !E_ID" ); +#endif // we can test bad param error returns + + CYG_TEST_PASS( "sta_tsk, chg_pri" ); + + CYG_TEST_INFO( "Testing delay and dispatch disabling" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_CTX == ercd, "dly_tsk bad ercd !E_CTX" ); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_CTX == ercd, "dly_tsk bad ercd !E_CTX" ); +#endif // we can test bad param error returns + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = dly_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + CYG_TEST_PASS( "dly_tsk, ena_dsp, dis_dsp" ); + + CYG_TEST_INFO( "Testing ready queue manipulation" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ercd = rot_rdq( 4 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ercd = rot_rdq( 5 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = rot_rdq( -6 ); + CYG_TEST_CHECK( E_PAR == ercd, "rot_rdq bad ercd !E_PAR" ); + ercd = rot_rdq( 99 ); + CYG_TEST_CHECK( E_PAR == ercd, "rot_rdq bad ercd !E_PAR" ); +#endif // we can test bad param error returns + + CYG_TEST_PASS( "rot_rdq" ); + + CYG_TEST_INFO( "Testing suspend/resume" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = sus_tsk( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "sus_tsk bad ercd !E_ID" ); + ercd = sus_tsk( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "sus_tsk bad ercd !E_ID" ); + ercd = rsm_tsk( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "rsm_tsk bad ercd !E_ID" ); + ercd = rsm_tsk( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "rsm_tsk bad ercd !E_ID" ); + ercd = frsm_tsk( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "frsm_tsk bad ercd !E_ID" ); + ercd = frsm_tsk( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "frsm_tsk bad ercd !E_ID" ); +#endif // we can test bad param error returns + // drop task 3 pri to same as us + CYG_TEST_CHECK( 0 == intercount, "intercount != 0" ); + + intercom = 3; // tell T3 to loop + TSRELEASE(); + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 3, 66 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 3, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 1 ); + CYG_TEST_CHECK( 1 == intercount, "intercount != 1" ); + ercd = sus_tsk( 3 ); + TSRELEASE(); + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + intercom = 0; // bad data to T3 + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 1 == intercount, "intercount != 1" ); + intercom = 3; // tell T3 to loop + TSRELEASE(); + ercd = rsm_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "rsm_tsk bad ercd" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 2 ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + + CYG_TEST_INFO( "Command task 3 inner loop stop" ); + intercom = 2 + 4; + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + + ercd = sus_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + intercom = 0; // bad data to T3 + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ercd = sus_tsk( 3 ); // suspend AGAIN + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + ercd = sus_tsk( 3 ); // AND AGAIN + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + ercd = rsm_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "rsm_tsk bad ercd" ); + ercd = rsm_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "rsm_tsk bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + intercom = 3; // tell T3 to loop + TSRELEASE(); + ercd = rsm_tsk( 3 ); // expect restart this time + CYG_TEST_CHECK( E_OK == ercd, "rsm_tsk bad ercd" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 3 ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + + CYG_TEST_INFO( "Command task 3 inner loop stop 2" ); + intercom = 2 + 4; + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + + ercd = sus_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + intercom = 0; // bad data to T3 + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + ercd = sus_tsk( 3 ); // suspend AGAIN + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + ercd = sus_tsk( 3 ); // AND AGAIN + CYG_TEST_CHECK( E_OK == ercd, "sus_tsk bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + intercom = 3; // tell T3 to loop + TSRELEASE(); + ercd = frsm_tsk( 3 ); // expect restart this time + CYG_TEST_CHECK( E_OK == ercd, "frsm_tsk bad ercd" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 4 ); + CYG_TEST_CHECK( 4 == intercount, "intercount != 4" ); + + TSRELEASE(); + ercd = rsm_tsk( 3 ); // try it again + CYG_TEST_CHECK( E_OBJ == ercd, "rsm_tsk bad ercd !E_OBJ" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 5 ); + CYG_TEST_CHECK( 5 == intercount, "intercount != 5" ); + + TSRELEASE(); + ercd = frsm_tsk( 3 ); // try it again + CYG_TEST_CHECK( E_OBJ == ercd, "frsm_tsk bad ercd !E_OBJ" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 6 ); + CYG_TEST_CHECK( 6 == intercount, "intercount != 6" ); + + CYG_TEST_INFO( "Command task 3 all loops stop" ); + intercom = 4 + 8; + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 6 == intercount, "intercount != 6" ); + + intercom = intercount = 0; + + CYG_TEST_PASS( "sus_tsk, rsm_tsk, frsm_tsk" ); + + CYG_TEST_INFO( "Testing sleep/wakeup stuff" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = wup_tsk( -6 ); + CYG_TEST_CHECK( E_ID == ercd, "wup_tsk bad ercd !E_ID" ); + ercd = wup_tsk( 99 ); + CYG_TEST_CHECK( E_ID == ercd, "wup_tsk bad ercd !E_ID" ); + ercd = can_wup( &scratch, -6 ); + CYG_TEST_CHECK( E_ID == ercd, "can_wup bad ercd !E_ID" ); + ercd = can_wup( &scratch, 99 ); + CYG_TEST_CHECK( E_ID == ercd, "can_wup bad ercd !E_ID" ); +#ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR + ercd = can_wup( NULL, 2 ); + CYG_TEST_CHECK( E_PAR == ercd, "can_wup bad ercd !E_PAR" ); +#endif + + ercd = wup_tsk( 0 ); // not ourself + CYG_TEST_CHECK( E_ID == ercd, "wup_tsk bad ercd !E_ID" ); + ercd = wup_tsk( 1 ); // ourself + CYG_TEST_CHECK( E_OBJ == ercd, "wup_tsk bad ercd !E_OBJ" ); +#endif // we can test bad param error returns + +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = tslp_tsk( -6 ); + CYG_TEST_CHECK( E_PAR == ercd, "tslp_tsk bad ercd !E_PAR" ); +#endif // we can test bad param error returns + ercd = tslp_tsk( TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tslp_tsk bad ercd !E_TMOUT" ); + ercd = tslp_tsk( 5 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tslp_tsk bad ercd !E_TMOUT" ); +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = tslp_tsk( TMO_FEVR ); + CYG_TEST_CHECK( E_CTX == ercd, "tslp_tsk bad ercd !E_CTX" ); + ercd = tslp_tsk( TMO_POL ); + CYG_TEST_CHECK( E_CTX == ercd, "tslp_tsk bad ercd !E_CTX" ); + ercd = tslp_tsk( 5 ); + CYG_TEST_CHECK( E_CTX == ercd, "tslp_tsk bad ercd !E_CTX" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + ercd = tslp_tsk( -6 ); + CYG_TEST_CHECK( E_PAR == ercd, "tslp_tsk bad ercd !E_PAR" ); +#endif // we can test bad param error returns + ercd = tslp_tsk( TMO_POL ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tslp_tsk bad ercd !E_TMOUT" ); + ercd = tslp_tsk( 5 ); + CYG_TEST_CHECK( E_TMOUT == ercd, "tslp_tsk bad ercd !E_TMOUT" ); + + // drop task 4 pri to same as us + intercount = 0; + intercom = 1; // test plain slp_tsk + TSRELEASE(); + ercd = chg_pri( 4, 5 ); + CYG_TEST_CHECK( E_OBJ == ercd, "chg_pri bad ercd" ); + + ercd = dis_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "dis_dsp bad ercd" ); + ercd = sta_tsk( 4, 77 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk bad ercd" ); + ercd = chg_pri( 4, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri bad ercd" ); + ercd = ena_dsp(); + CYG_TEST_CHECK( E_OK == ercd, "ena_dsp bad ercd" ); + + ercd = wup_tsk( 4 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 1 ); + CYG_TEST_CHECK( 1 == intercount, "intercount != 1" ); + intercom = 2; // test tslp_tsk + TSRELEASE(); + ercd = wup_tsk( 4 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 2 ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + intercom = 3; // test tslp_tsk + TSRELEASE(); + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 2 == intercount, "intercount != 2" ); + intercom = 1; // test slp_tsk next... + ercd = dly_tsk( 20 ); // without a wup + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + ICWAIT( 3 ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + + intercom = 1; // ...test slp_tsk + TSRELEASE(); + ercd = dly_tsk( 20 ); // without a wup (yet) + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + TSRELEASE(); + ercd = tslp_tsk( 20 ); // yield again + CYG_TEST_CHECK( E_TMOUT == ercd, "tslp_tsk bad ercd !E_TMOUT" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); // and again + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 3 == intercount, "intercount != 3" ); + TSRELEASE(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rot_rdq( 0 ); // and yield + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 4 ); + CYG_TEST_CHECK( 4 == intercount, "intercount != 4" ); + + intercom = 1; // test slp_tsk + TSRELEASE(); + ercd = dly_tsk( 20 ); // without a wup (yet) + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 4 == intercount, "intercount != 4" ); + + // this wup will restart it when we yield: + TSLOCK(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + // these will count up: + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + scratch = -1; + ercd = can_wup( &scratch, 4 ); + CYG_TEST_CHECK( E_OK == ercd, "can_wup bad ercd" ); + CYG_TEST_CHECK( 2 == scratch, "Cancelled wups not 2" ); + CYG_TEST_CHECK( 4 == intercount, "intercount != 4" ); + TSUNLOCK(); + + intercom = 4; // do nothing + TSRELEASE(); + ercd = rot_rdq( 0 ); // and yield + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 5 ); + CYG_TEST_CHECK( 5 == intercount, "intercount != 5" ); + TSRELEASE(); + ercd = dly_tsk( 20 ); // let it do nothing + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + + TSRELEASE(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + TSRELEASE(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + TSRELEASE(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + TSRELEASE(); + ercd = dly_tsk( 20 ); // lots of wups but no sleep + CYG_TEST_CHECK( E_OK == ercd, "dly_tsk bad ercd" ); + CYG_TEST_CHECK( 5 == intercount, "intercount != 5" ); + scratch = -1; + ercd = can_wup( &scratch, 4 ); + CYG_TEST_CHECK( E_OK == ercd, "can_wup bad ercd" ); + CYG_TEST_CHECK( 3 == scratch, "Cancelled wups not 3" ); + // now check that they are cancelled by doing a wait again + intercom = 1; // test slp_tsk + TSRELEASE(); + ercd = rot_rdq( 0 ); // still without a wup + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); // still without a wup + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + intercom = 4; // do nothing next + TSRELEASE(); + ICWAIT( 6 ); + CYG_TEST_CHECK( 6 == intercount, "intercount != 6" ); + ercd = rot_rdq( 0 ); // still without a wup + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 6 == intercount, "intercount != 6" ); + TSRELEASE(); + ercd = wup_tsk( 4 ); // now issue a wup + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + ercd = rot_rdq( 0 ); // it will run now + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk bad ercd" ); + TSRELEASE(); + ercd = rot_rdq( 0 ); // it will run now + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 7 ); + CYG_TEST_CHECK( 7 == intercount, "intercount != 7" ); + + TSRELEASE(); + intercom = 99; // exit, all done + ercd = rot_rdq( 0 ); // let it run + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + ICWAIT( 8 ); + CYG_TEST_CHECK( 8 == intercount, "intercount != 8" ); + + TSRELEASE(); + ercd = rot_rdq( 0 ); // let it run + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq bad ercd" ); + CYG_TEST_CHECK( 8 == intercount, "intercount != 8" ); + + CYG_TEST_PASS( "wup_tsk, can_wup, slp_tsk, tslp_tsk" ); + +#ifdef CYG_TEST_UITRON_TEST1_LOOPING + chg_pri( 1, 1 ); + rot_rdq( 0 ); + ter_tsk( 2 ); + rot_rdq( 0 ); + ter_tsk( 3 ); + rot_rdq( 0 ); + ter_tsk( 4 ); + rot_rdq( 0 ); + } +#endif // CYG_TEST_UITRON_TEST1_LOOPING + + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + + +void task2( unsigned int arg ) +{ + ER ercd; + CYG_TEST_PASS( "Task 2 running" ); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 2 == scratch, "tid not 2" ); + if ( 99 != arg ) + CYG_TEST_FAIL( "Task 2 arg not 99" ); + ext_tsk(); + CYG_TEST_FAIL( "Task 2 failed to exit" ); +} + +void task3( unsigned int arg ) +{ + ER ercd; + TSLOCK(); + CYG_TEST_PASS("Task3 running"); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 3 == scratch, "tid not 3" ); + if ( 66 != arg ) + CYG_TEST_FAIL( "Task 3 arg not 66" ); + + while ( 2 & intercom ) { + while ( 1 & intercom ) { + intercount++; + TSSTOP(); + do { + TSUNLOCK(); + ercd = rot_rdq( 0 ); // yield() + TSLOCK(); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq 1 (task3) bad ercd" ); + } while ( !TSGO() ); + } + CYG_TEST_CHECK( 4 & intercom, "should not have got here yet 1" ); + TSSTOP(); + do { + TSUNLOCK(); + ercd = rot_rdq( 0 ); // yield() + TSLOCK(); + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq 2 (task3) bad ercd" ); + } while ( !TSGO() ); + } + CYG_TEST_CHECK( 8 & intercom, "should not have got here yet 2" ); + + TSUNLOCK(); + ext_tsk(); + CYG_TEST_FAIL( "Task 3 failed to exit" ); +} + +void task4( unsigned int arg ) +{ + ER ercd; + CYG_TEST_PASS("Task4 running"); + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 4 == scratch, "tid not 4" ); + if ( 77 != arg ) + CYG_TEST_FAIL( "Task 4 arg not 77" ); + while ( 1 ) { + switch ( intercom ) { + case 1: + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk (task4) bad ercd" ); + break; + case 2: + ercd = tslp_tsk( 10 ); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk (task4) bad ercd" ); + break; + case 3: + ercd = tslp_tsk( 10 ); + CYG_TEST_CHECK( E_TMOUT == ercd, + "slp_tsk (task4) bad ercd !E_TMOUT" ); + break; + case 4: + // busily do nothing + while ( 4 == intercom ) { + ercd = rot_rdq( 0 ); + CYG_TEST_CHECK( E_OK == ercd, + "rot_rdq (task4 idle) bad ercd" ); + } + break; + case 99: + goto out; + default: + CYG_TEST_FAIL( "Task 4 bad intercom" ); + goto out; + } + intercount++; + TSSTOP(); + do { + ercd = rot_rdq( 0 ); // yield() + CYG_TEST_CHECK( E_OK == ercd, "rot_rdq (task4) bad ercd" ); + } while ( !TSGO() ); + } +out: + ext_tsk(); + CYG_TEST_FAIL( "Task 4 failed to exit" ); +} + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF testcxx.cxx diff --git a/packages/compat/uitron/v2_0/tests/testintr.cxx b/packages/compat/uitron/v2_0/tests/testintr.cxx new file mode 100644 index 00000000..7eb509b5 --- /dev/null +++ b/packages/compat/uitron/v2_0/tests/testintr.cxx @@ -0,0 +1,892 @@ +//=========================================================================== +// +// testintr.c +// +// uITRON "C" test program for ixxx_yyy interrupt safe operators +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors:hmt +// Date: 1998-08-20 +// Purpose: uITRON API testing +// Description: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include +#include // uITRON setup CYGNUM_UITRON_SEMAS + // CYGPKG_UITRON et al +#include // testing infrastructure + +#ifdef CYGPKG_UITRON // we DO want the uITRON package + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE // we DO want prioritized threads + +#ifdef CYGFUN_KERNEL_THREADS_TIMER // we DO want timout-able calls + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // we DO want the realtime clock + +// we're OK if it's C++ or neither of those two is defined: +#if defined( __cplusplus ) || \ + (!defined( CYGIMP_UITRON_INLINE_FUNCS ) && \ + !defined( CYGIMP_UITRON_CPP_OUTLINE_FUNCS) ) + +// =================== TEST CONFIGURATION =================== +#if \ + /* test configuration for enough tasks */ \ + (CYGNUM_UITRON_TASKS >= 4) && \ + (CYGNUM_UITRON_TASKS < 90) && \ + (CYGNUM_UITRON_START_TASKS == 1) && \ + ( !defined(CYGPKG_UITRON_TASKS_CREATE_DELETE) || \ + CYGNUM_UITRON_TASKS_INITIALLY >= 4 ) && \ + \ + /* the end of the large #if statement */ \ + 1 + +// ============================ END ============================ + +#include +#include + +#include + +#include // uITRON +#include // uITRON interrupt funcs + +void set_interrupt_number( void ); + +unsigned int clock_interrupt = 0; + +externC void +cyg_package_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO( "Calling cyg_uitron_start()" ); + set_interrupt_number(); + cyg_uitron_start(); +} + +extern "C" { + void task1( unsigned int arg ); + void task2( unsigned int arg ); + void task3( unsigned int arg ); + void task4( unsigned int arg ); +} + +volatile int intercom = 0; +INT scratch = 0; + +// Plan: replace (by direct intervention) the ISR and DSR of the regular +// timer interrupt; be sure to ack the clock intr using the appropriate hal +// macros. +// +// The new ISR(s) will simply use the interrupt-safe signalling functions +// to control a 2nd task. Main task will check on the state thereof. +// +// We must test the ixxx_yyy() funcs with the scheduler already locked +// also, by direct sched calls on the KAPI. This must verify that the +// signal only happens when the scheduler unlocks. +// +// The 4 producer ops are: +// iwup_tsk ( ID tskid ); +// isig_sem ( ID semid ); +// iset_flg ( ID flgid, UINT setptn ); +// isnd_msg ( ID mbxid, T_MSG *pk_msg ); +// +// and return macros are: +// ret_wup( ID tskid ); +// ret_int(); +// +// These ISRs perform the producer ops on all available objects in turn. +// Tasks 2-4 +// Semas 1-4 +// Flags 1-4 with marching bit data; they'll all be set to 0x1ff eventually +// Mboxes 1-4 with an arbitrary pointer + +enum { + NOTHING = 0, + SLP, + SEM, + FLG, + MBX, + EXIT +}; + +#define ACK_CLOCK() CYG_MACRO_START \ + HAL_CLOCK_RESET( CYGNUM_HAL_INTERRUPT_RTC, \ + CYGNUM_KERNEL_COUNTERS_RTC_PERIOD ); \ + HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_RTC ); \ +CYG_MACRO_END + +#define CHECK_TID() CYG_MACRO_START \ + int my_tid; \ + ER ercd; \ + ercd = get_tid( &my_tid ); \ + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); \ + CYG_TEST_CHECK( 0 == my_tid, "tid not 0 in ISR" ); \ +CYG_MACRO_END + + +unsigned int +isr_wup_tsk( unsigned int vector, unsigned int data ) +{ + // Hit TASKS in range 2..4 + static int wtid = 2; + ACK_CLOCK(); + CHECK_TID(); + iwup_tsk( wtid ); + wtid++; + if ( 5 == wtid ) wtid = 2; + ret_int(); +} + +unsigned int +isr_ret_wup( unsigned int vector, unsigned int data ) +{ + // Hit TASKS in range 2..4 + static int rwid = 2; + ACK_CLOCK(); + CHECK_TID(); + rwid++; + if ( 6 == rwid ) rwid = 3; + ret_wup( rwid - 1 ); +} + +unsigned int +isr_sig_sem( unsigned int vector, unsigned int data ) +{ + // Hit SEMAS in range 1..3 + static int ssid = 1; + ACK_CLOCK(); + CHECK_TID(); + isig_sem( ssid ); + ssid++; + if ( ssid == 4 ) ssid = 1; + ret_int(); +} + +unsigned int +isr_set_flg( unsigned int vector, unsigned int data ) +{ + // Hit FLAGS in range 1..4 + static int sfid = 1; + static int sfdata = 0xff; + ACK_CLOCK(); + CHECK_TID(); + iset_flg( sfid, sfdata ); + sfid++; + if ( sfid == 5 ) sfid = 1; +// sfdata <<= 1; +// if ( sfdata == 0x20 ) sfdata = 1; // so that eventually all 0x1f set + ret_int(); +} + +unsigned int +isr_snd_msg( unsigned int vector, unsigned int data ) +{ + // Hit MBOXES in range 1..4 + static int smid = 1; + ACK_CLOCK(); + CHECK_TID(); + isnd_msg( smid, (T_MSG *)&smid ); + smid++; + if ( smid == 5 ) smid = 1; + ret_int(); +} + + +void attach_isr( unsigned int (*isr)(unsigned int, unsigned int) ); +void detach_isr( unsigned int (*isr)(unsigned int, unsigned int) ); + +void lock_sched( void ); +void unlock_sched( void ); + +volatile int count = -1; + +/* +#define BIGDELAY 50000000 +#define SMALLDELAY (BIGDELAY/SMALLLOOPS) +#define SMALLLOOPS 3 + +#define xxxLONGDELAY() \ +do { \ + int i; \ + for ( i = 0; i < BIGDELAY; i++ ) \ + if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break; \ +} while ( 0 ) + +#define xxxDELAYLOCKSCHED() \ +do { \ + int i,j; \ + for ( j = 0; j < SMALLLOOPS; j++ ) { \ + lock_sched(); \ + for ( i = 0; i < SMALLDELAY; i++ ) \ + if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break; \ + unlock_sched(); \ + if ( wakeups[ 4 ] > prewups[ 4 ] + 99 ) break; \ + } \ +} while ( 0 ) +*/ + +#define SMALLDELAYHW (5000000) +#define EVENTSHW ( 20) +#define SMALLDELAYSIM ( 100000) +#define EVENTSSIM ( 4) + +#define SMALLDELAY (smalldelay) +#define EVENTS (events) + +static int smalldelay = SMALLDELAYHW; +static int events = EVENTSHW; + +#define LONGDELAY() do { \ + count = 0; \ + do count++; while ( wakeups[ 4 ] < prewups[ 4 ] + EVENTS ); \ +} while ( 0 ) + + +#define DELAYLOCKSCHED() \ +do { \ + count = 0; \ + int i; \ + do { \ + lock_sched(); \ + for ( i = 0; i < SMALLDELAY; i++ ) { \ + count++; \ + if ( wakeups[ 4 ] >= prewups[ 4 ] + EVENTS ) \ + break; \ + } \ + unlock_sched(); \ + CYG_TEST_INFO(" [Still iterating, please wait....] "); \ + } while ( wakeups[ 4 ] < prewups[ 4 ] + EVENTS ); \ +} while ( 0 ) + +#define DELAY() \ +if ( 1 & loops ) \ + DELAYLOCKSCHED(); \ +else \ + LONGDELAY(); + + +volatile int wakeups[ 5 ] = { 0,0,0,0,0 }; +volatile int prewups[ 5 ] = { 0,0,0,0,0 }; + + +void task1( unsigned int arg ) +{ + ER ercd; + int loops; + + CYG_TEST_INFO( "Task 1 running" ); + + if ( cyg_test_is_simulator ) { + // take less time + events = EVENTSSIM; + } + + + // First test that dis_int() and ena_int() work for the clock interrupt +#ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS + ercd = ena_int( 123456789 ); // Hope this is large enough to error + CYG_TEST_CHECK( E_PAR == ercd, "ena_int bad ercd !E_PAR" ); + ercd = dis_int( 123456789 ); + CYG_TEST_CHECK( E_PAR == ercd, "dis_int bad ercd !E_PAR" ); +#endif + + // This may take too long on a sim... + // On the synthetic target this test cannot run reliably - the + // loop counting assumes exclusive access to the processor. +#ifndef CYGPKG_HAL_SYNTH + if ( ! cyg_test_is_simulator ) { + SYSTIME t1, t2; + + CYG_TEST_INFO( "Testing masking of clock interrupt" ); + + ercd = get_tim( &t1 ); + CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" ); + + // Wait for a tick. This loop acts as a synchronizer for the loop + // below, ensuring that it starts just after a tick. + for ( loops = 0; loops < 10000000; loops++ ) { + ercd = get_tim( &t2 ); + CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" ); + if ( t2 != t1 ) + break; + } + // Wait for next tick. Reset loops counter so we get the + // approximate loop count of one clock tick. + for ( loops = 0; loops < 10000000; loops++ ) { + ercd = get_tim( &t1 ); + CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" ); + if ( t2 != t1 ) + break; + } + + // save how many loops could be executed in one tick. Multiply + // with 3 : we run loops in pairs below and add the time of + // one extra to avoid small variations to trigger failures. + intercom = loops * 3; + + ercd = ena_int( clock_interrupt ); // was initialized already + CYG_TEST_CHECK( E_OK == ercd, "ena_int bad ercd" ); + + ercd = get_tim( &t1 ); + CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" ); + + // Wait for a tick + for ( loops = intercom; loops > 0; loops-- ) { + ercd = get_tim( &t2 ); + CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" ); + if ( t2 != t1 ) + break; + } + CYG_TEST_CHECK( 0 < loops, "No first tick" ); + // and a second one + for ( ; loops > 0; loops-- ) { + ercd = get_tim( &t1 ); + CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" ); + if ( t2 != t1 ) + break; + } + CYG_TEST_CHECK( 0 < loops, "No second tick" ); + + // The PowerPC cannot disable the timer interrupt (separately). +#ifndef CYGPKG_HAL_POWERPC + ercd = dis_int( clock_interrupt ); // was initialized already + CYG_TEST_CHECK( E_OK == ercd, "dis_int bad ercd" ); + + ercd = get_tim( &t1 ); + CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" ); + + // Wait for a tick (should not happen) + for ( loops = intercom; loops > 0; loops-- ) { + ercd = get_tim( &t2 ); + CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" ); + if ( t2 != t1 ) + break; + } + CYG_TEST_CHECK( 0 == loops, "A tick occured - should be masked" ); + CYG_TEST_CHECK( t1 == t2, "Times are different" ); + + // Now enable it again and ensure all is well: + ercd = ena_int( clock_interrupt ); + CYG_TEST_CHECK( E_OK == ercd, "ena_int bad ercd" ); +#endif + + ercd = get_tim( &t1 ); + CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" ); + + // Wait for a tick + for ( loops = intercom; loops > 0; loops-- ) { + ercd = get_tim( &t2 ); + CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" ); + if ( t2 != t1 ) + break; + } + CYG_TEST_CHECK( 0 < loops, "No first tick" ); + // and a second one + for ( ; loops > 0; loops-- ) { + ercd = get_tim( &t1 ); + CYG_TEST_CHECK( E_OK == ercd, "get_tim bad ercd" ); + if ( t2 != t1 ) + break; + } + CYG_TEST_CHECK( 0 < loops, "No second tick" ); + + CYG_TEST_PASS( "dis_int(), ena_int() OK" ); + } +#endif + + intercom = 0; + + ercd = get_tid( &scratch ); + CYG_TEST_CHECK( E_OK == ercd, "get_tid bad ercd" ); + CYG_TEST_CHECK( 1 == scratch, "tid not 1" ); + + // start all other tasks (our prio is 1 by default) + ercd = sta_tsk( 2, 222 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk 2 bad ercd" ); + ercd = sta_tsk( 3, 333 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk 3 bad ercd" ); + ercd = sta_tsk( 4, 444 ); + CYG_TEST_CHECK( E_OK == ercd, "sta_tsk 4 bad ercd" ); + // drop pri of other tasks all to 5 + ercd = chg_pri( 2, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri 2 bad ercd" ); + ercd = chg_pri( 3, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri 3 bad ercd" ); + ercd = chg_pri( 4, 5 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri 4 bad ercd" ); + + // Test sleep/wakeup + intercom = SLP; + // Drop our prio to lower; they will run in turn until asleep + ercd = chg_pri( 1, 6 ); + CYG_TEST_CHECK( E_OK == ercd, "chg_pri 1 (self) bad ercd" ); + + loops = 4; + do { + + if ( 1 & loops ) + CYG_TEST_INFO( " (toggling scheduler lock) " ); + else + CYG_TEST_INFO( " (unlocked scheduler) " ); + + + CYG_TEST_CHECK( 0 == wakeups[0], "init: Wakeups[0] hit" ); + CYG_TEST_CHECK( 0 == wakeups[1], "init: Wakeups[1] hit" ); + CYG_TEST_CHECK( prewups[2] == wakeups[2], "init: Wakeups[2] hit" ); + CYG_TEST_CHECK( prewups[3] == wakeups[3], "init: Wakeups[3] hit" ); + CYG_TEST_CHECK( prewups[4] == wakeups[4], "init: Wakeups[4] hit" ); + + // -------- TIMERS AND TIMESLICING DISABLED --------- + // install an isr that will wake them all up in turn + attach_isr( isr_wup_tsk ); + DELAY(); + detach_isr( isr_wup_tsk ); + // -------- timers and timeslicing ENABLED --------- + + CYG_TEST_CHECK( 0 == wakeups[0], "iwup_tsk: Wakeups[0] hit" ); + CYG_TEST_CHECK( 0 == wakeups[1], "iwup_tsk: Wakeups[1] hit" ); + CYG_TEST_CHECK( prewups[2] < wakeups[2], "iwup_tsk: Wakeups[2] not hit" ); + CYG_TEST_CHECK( prewups[3] < wakeups[3], "iwup_tsk: Wakeups[3] not hit" ); + CYG_TEST_CHECK( prewups[4] < wakeups[4], "iwup_tsk: Wakeups[4] not hit" ); + diag_printf( "INFO:<(fg loops %10d) thread wakeups : %2d %2d %2d >\n", count, + wakeups[2] - prewups[2], + wakeups[3] - prewups[3], + wakeups[4] - prewups[4] ); + prewups[2] = wakeups[2]; + prewups[3] = wakeups[3]; + prewups[4] = wakeups[4]; + + // -------- TIMERS AND TIMESLICING DISABLED --------- + // install an isr that will wake them all up in turn + attach_isr( isr_ret_wup ); + DELAY(); + detach_isr( isr_ret_wup ); + // -------- timers and timeslicing ENABLED --------- + + CYG_TEST_CHECK( 0 == wakeups[0], "ret_wup: Wakeups[0] hit" ); + CYG_TEST_CHECK( 0 == wakeups[1], "ret_wup: Wakeups[1] hit" ); + CYG_TEST_CHECK( prewups[2] < wakeups[2], "ret_wup: Wakeups[2] not hit" ); + CYG_TEST_CHECK( prewups[3] < wakeups[3], "ret_wup: Wakeups[3] not hit" ); + CYG_TEST_CHECK( prewups[4] < wakeups[4], "ret_wup: Wakeups[4] not hit" ); + diag_printf( "INFO:<(fg loops %10d) thread ret_wups: %2d %2d %2d >\n", count, + wakeups[2] - prewups[2], + wakeups[3] - prewups[3], + wakeups[4] - prewups[4] ); + prewups[2] = wakeups[2]; + prewups[3] = wakeups[3]; + prewups[4] = wakeups[4]; + + // move them on to waiting for a semaphore + intercom = SEM; + ercd = wup_tsk( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(2) bad ercd" ); + ercd = wup_tsk( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(3) bad ercd" ); + ercd = wup_tsk( 4 ); + CYG_TEST_CHECK( E_OK == ercd, "wup_tsk(4) bad ercd" ); + + CYG_TEST_CHECK( 0 == wakeups[0], "wup_tsk: Wakeups[0] hit" ); + CYG_TEST_CHECK( 0 == wakeups[1], "wup_tsk: Wakeups[1] hit" ); + CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "wup_tsk: Wakeups[2] not hit" ); + CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "wup_tsk: Wakeups[3] not hit" ); + CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "wup_tsk: Wakeups[4] not hit" ); + prewups[2] = wakeups[2]; + prewups[3] = wakeups[3]; + prewups[4] = wakeups[4]; + + // -------- TIMERS AND TIMESLICING DISABLED --------- + // install an isr that will wake them all up in turn + attach_isr( isr_sig_sem ); + DELAY(); + detach_isr( isr_sig_sem ); + // -------- timers and timeslicing ENABLED --------- + + CYG_TEST_CHECK( 0 == wakeups[0], "isig_sem: Wakeups[0] hit" ); + CYG_TEST_CHECK( 0 == wakeups[1], "isig_sem: Wakeups[1] hit" ); + CYG_TEST_CHECK( prewups[2] < wakeups[2], "isig_sem: Wakeups[2] not hit" ); + CYG_TEST_CHECK( prewups[3] < wakeups[3], "isig_sem: Wakeups[3] not hit" ); + CYG_TEST_CHECK( prewups[4] < wakeups[4], "isig_sem: Wakeups[4] not hit" ); + diag_printf( "INFO:<(fg loops %10d) semaphore waits: %2d %2d %2d >\n", count, + wakeups[2] - prewups[2], + wakeups[3] - prewups[3], + wakeups[4] - prewups[4] ); + prewups[2] = wakeups[2]; + prewups[3] = wakeups[3]; + prewups[4] = wakeups[4]; + + // move them on to waiting for a flag + intercom = FLG; + ercd = sig_sem( 1 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem(1) bad ercd" ); + ercd = sig_sem( 2 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem(2) bad ercd" ); + ercd = sig_sem( 3 ); + CYG_TEST_CHECK( E_OK == ercd, "sig_sem(3) bad ercd" ); + + CYG_TEST_CHECK( 0 == wakeups[0], "sig_sem: Wakeups[0] hit" ); + CYG_TEST_CHECK( 0 == wakeups[1], "sig_sem: Wakeups[1] hit" ); + CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "sig_sem: Wakeups[2] not hit" ); + CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "sig_sem: Wakeups[3] not hit" ); + CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "sig_sem: Wakeups[4] not hit" ); + prewups[2] = wakeups[2]; + prewups[3] = wakeups[3]; + prewups[4] = wakeups[4]; + + // -------- TIMERS AND TIMESLICING DISABLED --------- + // install an isr that will wake them all up in turn + attach_isr( isr_set_flg ); + DELAY(); + detach_isr( isr_set_flg ); + // -------- timers and timeslicing ENABLED --------- + + CYG_TEST_CHECK( 0 == wakeups[0], "iset_flg: Wakeups[0] hit" ); + CYG_TEST_CHECK( 0 == wakeups[1], "iset_flg: Wakeups[1] hit" ); + CYG_TEST_CHECK( prewups[2] < wakeups[2], "iset_flg: Wakeups[2] not hit" ); + CYG_TEST_CHECK( prewups[3] < wakeups[3], "iset_flg: Wakeups[3] not hit" ); + CYG_TEST_CHECK( prewups[4] < wakeups[4], "iset_flg: Wakeups[4] not hit" ); + diag_printf( "INFO:<(fg loops %10d) flag waits/sets: %2d %2d %2d >\n", count, + wakeups[2] - prewups[2], + wakeups[3] - prewups[3], + wakeups[4] - prewups[4] ); + prewups[2] = wakeups[2]; + prewups[3] = wakeups[3]; + prewups[4] = wakeups[4]; + + // move them on to waiting for a message box + intercom = MBX; + ercd = set_flg( 2, 0xfff ); + CYG_TEST_CHECK( E_OK == ercd, "set_flg(2) bad ercd" ); + ercd = set_flg( 3, 0xfff ); + CYG_TEST_CHECK( E_OK == ercd, "set_flg(3) bad ercd" ); + ercd = set_flg( 4, 0xfff ); + CYG_TEST_CHECK( E_OK == ercd, "set_flg(4) bad ercd" ); + + CYG_TEST_CHECK( 0 == wakeups[0], "set_flg: Wakeups[0] hit" ); + CYG_TEST_CHECK( 0 == wakeups[1], "set_flg: Wakeups[1] hit" ); + CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "set_flg: Wakeups[2] not hit" ); + CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "set_flg: Wakeups[3] not hit" ); + CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "set_flg: Wakeups[4] not hit" ); + prewups[2] = wakeups[2]; + prewups[3] = wakeups[3]; + prewups[4] = wakeups[4]; + + // -------- TIMERS AND TIMESLICING DISABLED --------- + // install an isr that will wake them all up in turn + attach_isr( isr_snd_msg ); + DELAY(); + detach_isr( isr_snd_msg ); + // -------- timers and timeslicing ENABLED --------- + + CYG_TEST_CHECK( 0 == wakeups[0], "isnd_msg: Wakeups[0] hit" ); + CYG_TEST_CHECK( 0 == wakeups[1], "isnd_msg: Wakeups[1] hit" ); + CYG_TEST_CHECK( prewups[2] < wakeups[2], "isnd_msg: Wakeups[2] not hit" ); + CYG_TEST_CHECK( prewups[3] < wakeups[3], "isnd_msg: Wakeups[3] not hit" ); + CYG_TEST_CHECK( prewups[4] < wakeups[4], "isnd_msg: Wakeups[4] not hit" ); + diag_printf( "INFO:<(fg loops %10d) message rec'pts: %2d %2d %2d >\n", count, + wakeups[2] - prewups[2], + wakeups[3] - prewups[3], + wakeups[4] - prewups[4] ); + prewups[2] = wakeups[2]; + prewups[3] = wakeups[3]; + prewups[4] = wakeups[4]; + + // move them on to exiting, all done + if ( 1 == loops ) + // then we are about to exit + intercom = EXIT; + else + intercom = SLP; + ercd = snd_msg( 2, (T_MSG *)&intercom ); + CYG_TEST_CHECK( E_OK == ercd, "snd_msg(2) bad ercd" ); + ercd = snd_msg( 3, (T_MSG *)&intercom ); + CYG_TEST_CHECK( E_OK == ercd, "snd_msg(3) bad ercd" ); + ercd = snd_msg( 4, (T_MSG *)&intercom ); + CYG_TEST_CHECK( E_OK == ercd, "snd_msg(4) bad ercd" ); + + CYG_TEST_CHECK( 0 == wakeups[0], "snd_msg: Wakeups[0] hit" ); + CYG_TEST_CHECK( 0 == wakeups[1], "snd_msg: Wakeups[1] hit" ); + CYG_TEST_CHECK( prewups[2] + 1 == wakeups[2], "snd_msg: Wakeups[2] not hit" ); + CYG_TEST_CHECK( prewups[3] + 1 == wakeups[3], "snd_msg: Wakeups[3] not hit" ); + CYG_TEST_CHECK( prewups[4] + 1 == wakeups[4], "snd_msg: Wakeups[4] not hit" ); + prewups[2] = wakeups[2]; + prewups[3] = wakeups[3]; + prewups[4] = wakeups[4]; + + CYG_TEST_PASS( "Tested ISR invoked uITRON functions" ); + + } while ( 0 < --loops ); + + CYG_TEST_EXIT( "All done" ); + ext_tsk(); +} + + +void body( int n ) +{ + unsigned int z; + ER ercd; + T_MSG *pk_msg; + + do { + switch ( intercom ) { + case NOTHING: + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk (doing nothing)" ); + continue; + case SLP: + ercd = slp_tsk(); + CYG_TEST_CHECK( E_OK == ercd, "slp_tsk bad ercd" ); + wakeups[ n ]++; + break; + case SEM: + ercd = wai_sem( n-1 ); // 1..3 for semas + CYG_TEST_CHECK( E_OK == ercd, "wai_sem bad ercd" ); + wakeups[ n ]++; + break; + case FLG: + ercd = wai_flg( &z, n, (1< +#include +#include +#include +#include + +void set_interrupt_number( void ) +{ + clock_interrupt = CYGNUM_HAL_INTERRUPT_RTC; +} + +// This snippet stolen from kernel/.../clock.cxx to be able to detach +// the RTC from its interrupt source. +class Cyg_RealTimeClock + : public Cyg_Clock +{ +public: + Cyg_Interrupt interrupt; + + static cyg_uint32 isr(cyg_vector vector, CYG_ADDRWORD data); + + static void dsr(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data); + + Cyg_RealTimeClock(); +}; + + +static Cyg_Interrupt uit_intr( + (unsigned)CYGNUM_HAL_INTERRUPT_RTC, // Vector to attach to + 0, // Queue priority + (unsigned)0, // Data pointer + &isr_wup_tsk, // Interrupt Service Routine + &cyg_uitron_dsr // Deferred Service Routine +); + +void +attach_isr( unsigned int (*isr)(unsigned int, unsigned int) ) +{ + int inuse; + int old_ints; + Cyg_RealTimeClock *prtc = (Cyg_RealTimeClock *)Cyg_Clock::real_time_clock; + HAL_DISABLE_INTERRUPTS(old_ints); + HAL_INTERRUPT_MASK( CYGNUM_HAL_INTERRUPT_RTC ); + prtc->interrupt.detach(); +#ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN + // Only check that the vector was cleared when there's a specific + // vector for the RTC. In chain mode, other interrupt handlers + // may prevent the shared vector from being cleared when detaching + // the RTC ISR, and this assertion fails. + HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse ); + CYG_TEST_CHECK( !inuse, "Failed to detach clock ISR" ); +#endif + uit_intr = Cyg_Interrupt( + CYGNUM_HAL_INTERRUPT_RTC, // Vector to attach to + 1, // Queue priority + 0, // Data pointer + isr, // Interrupt Service Routine + cyg_uitron_dsr // Deferred Service Routine + ); + uit_intr.attach(); + HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse ); + CYG_TEST_CHECK( inuse, "Failed to attach new ISR" ); + ACK_CLOCK(); + HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_RTC ); + HAL_RESTORE_INTERRUPTS(old_ints); +} + +void +detach_isr( unsigned int (*isr)(unsigned int, unsigned int) ) +{ + int inuse; + int old_ints; + Cyg_RealTimeClock *prtc = (Cyg_RealTimeClock *)Cyg_Clock::real_time_clock; + HAL_DISABLE_INTERRUPTS(old_ints); + HAL_INTERRUPT_MASK( CYGNUM_HAL_INTERRUPT_RTC ); + uit_intr.detach(); +#ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN + // See comment above in attach_isr. + HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse ); + CYG_TEST_CHECK( !inuse, "Failed to detach my ISR" ); +#endif + prtc->interrupt.attach(); + HAL_INTERRUPT_IN_USE( CYGNUM_HAL_INTERRUPT_RTC, inuse ); + CYG_TEST_CHECK( inuse, "Failed to attach clock ISR" ); + ACK_CLOCK(); + HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_RTC ); + HAL_RESTORE_INTERRUPTS(old_ints); +} + + +void +lock_sched( void ) +{ + cyg_uint32 l; + Cyg_Scheduler::lock(); + l = Cyg_Scheduler::get_sched_lock(); + CYG_TEST_CHECK( 0 < l, "lock: Sched not locked" ); + CYG_TEST_CHECK( 2 > l, "lock: Sched already locked" ); +} + +void +unlock_sched( void ) +{ + cyg_uint32 l; + l = Cyg_Scheduler::get_sched_lock(); + CYG_TEST_CHECK( 0 < l, "unlock: Sched not locked" ); + CYG_TEST_CHECK( 2 > l, "unlock: Sched already locked" ); + Cyg_Scheduler::unlock(); +} + + +#else // not enough (or too many) uITRON objects configured in +#define N_A_MSG "not enough uITRON objects to run test" +#endif // not enough (or too many) uITRON objects configured in +#else // not C++ and some C++ specific options enabled +#define N_A_MSG "C++ specific options selected but this is C" +#endif // not C++ and some C++ specific options enabled +#else // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#define N_A_MSG "no CYGVAR_KERNEL_COUNTERS_CLOCK" +#endif // ! CYGVAR_KERNEL_COUNTERS_CLOCK - can't test without it +#else // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#define N_A_MSG "no CYGFUN_KERNEL_THREADS_TIMER" +#endif // ! CYGFUN_KERNEL_THREADS_TIMER - can't test without it +#else // ! CYGIMP_THREAD_PRIORITY - can't test without it +#define N_A_MSG "no CYGSEM_KERNEL_SCHED_MLQUEUE" +#endif // ! CYGSEM_KERNEL_SCHED_MLQUEUE - can't test without it +#else // ! CYGPKG_UITRON +#define N_A_MSG "uITRON Compatibility layer disabled" +#endif // CYGPKG_UITRON + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG defined ie. we are N/A. + +// EOF testintr.c diff --git a/packages/cygmon/v2_0/ChangeLog b/packages/cygmon/v2_0/ChangeLog new file mode 100644 index 00000000..f52afbad --- /dev/null +++ b/packages/cygmon/v2_0/ChangeLog @@ -0,0 +1,252 @@ +2000-12-04 Drew Moseley + + * misc/monitor_cmd.c (breakpoint_cmd): Fix typo in printf + formatting for error message. + +2000-11-20 Drew Moseley + + * cdl/cygmon.cdl: Make sure we don't specify vectors.o and target.ld twice. + +2000-11-03 Jonathan Larmour + + * cdl/cygmon.cdl: Improve cygmon.elf make dependencies + +2000-10-17 Drew Moseley + + * misc/utils.c: Fix a typo. Also make sure we are ignoring the + '+' characters from gdb. + + * misc/monitor_cmd.c: Add a few cache flushes. + + * misc/monitor.h: Use the debug port for xvprintf. + +2000-08-14 Drew Moseley + + * misc/ecos_bsp.c: Added some include files to fix some build + failures on partially unsupported systems. (ie non-cygmon, etc). + +2000-08-12 Drew Moseley + + * misc/bsp/common/debug-io.c (bsp_debug_write): Use + output_gdb_string when stub_is_active. + +2000-08-10 Drew Moseley + + * misc/utils.c: Removed some unused functions. Also handle + printing invalid registers. + + * misc/monitor_cmd.c: Handle some unprintable characters better. + Also handle displaying of invalid memory locations better. + Add handling for register validity checking. + + * misc/monitor.h: Add a conditional field "reg_valid" to struct + regstruct. + + * misc/monitor.c: Added a call to a conditionally defined routine + INITIALIZE_MON_EACH_TIME(). This is called everytime the monitor + is invoked. For instance, this is used to determine which + registers have actually been read. + + * misc/generic_mem.c: Allow Cygmon to use the Safe memory routines + in the HAL. + + * misc/board.h: Added MN10300 basic support. + * misc/cpu-mon.c: Ditto. + * misc/cpu_info.h: Ditto. + * misc/bsp/cpu.h: Ditto. + * misc/bsp/mn10300/gdb-cpu.c: Ditto. New file. + * misc/bsp/mn10300/gdb-cpu.h: Ditto. New file. + * misc/bsp/mn10300/gdb.h: Ditto. New file. + * misc/bsp/mn10300/insn.h: Ditto. New file. + * misc/bsp/mn10300/singlestep.c: Ditto. New file. + * misc/mn10300/board.h: Ditto. New file. + * misc/mn10300/cpu.h: Ditto. New file. + * misc/mn10300/cpu_info.h: Ditto. New file. + * misc/mn10300/mn10300-mon.c: Ditto. New file. + + * cdl/cygmon.cdl: Removed dependency on the kernel and Serial I/O. + * misc/ecos_bsp.c: Ditto. + * misc/ecos_dummy.c: Ditto. + +2000-07-21 Drew Moseley + + * misc/ecos_bsp.c: Rearrange the linkage between Cygmon and HAL so + that Cygmon needs HAL but not vice-versa. ie HAL no longer calls + any Cygmon functions. + * misc/monitor.c: Ditto. + +2000-07-14 Drew Moseley + + * misc/bsp/mips/gdb-cpu.c: New files. Mips based Cygmon now running on top of eCos HAL. + * misc/bsp/mips/gdb-cpu.h: Ditto. + * misc/bsp/mips/gdb.h: Ditto. + * misc/bsp/mips/insn.h: Ditto. + * misc/bsp/mips/singlestep.c: Ditto. + * misc/mips/board.h: Ditto. + * misc/mips/cpu.h: Ditto. + * misc/mips/cpu_info.h: Ditto. + * misc/mips/mips-mon.c: Ditto. + + * misc/bsp/common/syscall.c: Added SYS_meminfo call to find out + how much RAM we have. + * misc/bsp/common/syscall.h: Ditto. + + * misc/bsp/common/breakpoint.c: Added __ECOS__ support. + + * misc/monitor_cmd.c: Cleanup. Added some more error handling. + * misc/utils.c: Ditto. + + * misc/monitor.c: Added basic syscall handling to support libgloss. + Added support for using more features of the HAL (ie breakpoints + and exceptions). + * misc/monitor.h: Ditto. + * misc/tservice.h: Ditto. + * misc/bsp/bsp.h: Ditto. + * misc/arm/cpu_info.h: Ditto. + + * misc/ledit.c: Cleanup. + + * misc/ecos_dummy.c: Support for reset through the HAL. + + * misc/ecos_bsp.c: Filled in uart_control function for setting baud rate + through the HAL. Also added VIRTUAL_VECTOR_SUPPORT and support of the + low-level HAL-based serial driver. Also added set_memsize() support. + + * misc/bplist-dynamic.c: Added option for using breakpoints in the HAL. + Also, various cleanups of build warnings, etc. + * misc/breakpoints.c: Ditto. + + * cdl/cygmon.cdl: Allow cygmon to be built for either Arm or Mips. + + * misc/board.h: Move architecture-dependent things out. + * misc/cpu-mon.c: Ditto. + * misc/cpu_info.h: Ditto. + * misc/bsp/cpu.h: Ditto. + * misc/bsp/common/gdb-cpu.c: Ditto. + * misc/bsp/common/gdb-cpu.h: Ditto. + * misc/bsp/common/singlestep.c: Ditto. + +2000-01-28 Jesper Skov + + * misc/Notes_CygMon_PID: Added. + +2000-01-27 Jesper Skov + + * cdl/cygmon.cdl: Include hal.h config for CygMon options defined + by platform CDL. + +2000-01-26 Jonathan Larmour + + * cdl/cygmon.cdl: Remove CYGDAT_CYGMON_ENABLE - no longer required + +2000-01-25 Jesper Skov + + * cdl/cygmon.cdl: Moved console device config to target CDL. + Let target CDL handle binary conversion. + +1999-12-17 Bart Veer + + * cdl/cygmon.cdl: + Fix a requires property, getting the quoting right + +1999-12-14 John Dallaway + + * cdl/cygmon.cdl: Add custom make rule to build CygMon. + +1999-12-06 Gary Thomas + + * misc/arm/arm-mon.c (machine_syscall): + * misc/ecos_bsp.c (_bsp_handle_exception): + * misc/PKGconf.mak: Adding 'syscall' support. + + * misc/CygMon_PID.cfg: + * misc/bsp/common/syscall.h: + * misc/bsp/common/syscall.c: New file(s). + +1999-11-26 Jonathan Larmour + + * misc/CygMon_EDB7211.cfg: Rename to misc/CygMon/EDB7xxx.cfg + * misc/CygMon_EDB7xxx.cfg: New file + +1999-11-26 Gary Thomas + + * misc/ecos_bsp.c (_bsp_board_init): Use/define HAL symbols + for board/cpu information. + (_bsp_memory_list): Use MLT information here. + + * misc/CygMon_EDB7211.cfg: Fix typo. Change startup to be + ROM which gives more useful RAM information. + +1999-11-19 Gary Thomas + + * misc/CygMon_EDB7211.cfg: Add platform parameter. Update + patch for latest changes. + +1999-11-03 Jesper Skov + + * cdl/cygmon.cdl: Added. + +1999-10-27 Gary Thomas + + * misc/PKGconf.mak: Add new targets (.bin .srec images). + + * include/pkgconf/cygmon.h: Update strings to be more conformant. + + * misc/CygMon_EDB7211.cfg: New file for building CygMon. + + * include/pkgconf/cygmon.h: Add work-around because packages + can't be disabled by default. + +1999-10-26 Gary Thomas + + * include/pkgconf/cygmon.h: Fix typo 'CYGPKC_LIBC'=>'CYGPKG_LIBC' + Also, node type was wrong ('radio' instead of 'boolean') + +1999-10-25 Gary Thomas + + * include/pkgconf/cygmon.h: Add configuration options for + console device [name] and extended help. Remove duplicate + boilerplate. + + * misc/board.h: Enable "help" via configuration option. + + * misc/ecos_bsp.c: Cleanup/remove extra (debug) code. + Add support for console port configuration. + + * misc/monitor.c: + * misc/monitor_cmd.c: Cleanup/remove some debug code. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/cygmon/v2_0/cdl/cygmon.cdl b/packages/cygmon/v2_0/cdl/cygmon.cdl new file mode 100644 index 00000000..04f4645a --- /dev/null +++ b/packages/cygmon/v2_0/cdl/cygmon.cdl @@ -0,0 +1,140 @@ +# ==================================================================== +# +# cygmon.cdl +# +# CygMon package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: gthomas +# Contributors: dmoseley +# Date: 1999-11-03 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== +cdl_package CYGPKG_CYGMON { + display "CygMon ROM monitor" + requires CYGPKG_LIBC_STRING + include_dir cyg/cygmon + define_header cygmon.h + description " + This package supports the CygMon \[stand-alone debug monitor\] + using eCos as the underlying board support mechanism." + + + # Since the CYGDAT_CYGMON_CONSOLE_DEV setting ends up in the platform + # HAL header, we need to include that here (via hal.h). + define_proc { + puts $::cdl_header "#include " + } + + cdl_option CYGDAT_CYGMON_USE_HELP { + display "Include detailed command help" + default_value 1 + description " + When this option is selected, the CygMon image will include + detailed help information for all built-in commands. Without + it, only minimal help will be provided." + } + + cdl_option CYGBLD_BUILD_CYGMON { + display "Build CygMon ROM ELF image" + default_value 0 + requires { CYG_HAL_STARTUP == "ROM" } + requires CYGPKG_INFRA + requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + requires ! CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + requires ! CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT + requires ! CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT + requires CYGPKG_LIBC_STRING + requires ! CYGFUN_LIBC_strtod + requires ! CYGPKG_LIBC_STDIO + requires ! CYGSEM_LIBC_SIGNALS_THREAD_SAFE + requires ! CYGIMP_LIBC_SIGNALS_RAISE_INLINE + requires ! CYGIMP_LIBC_SIGNALS_SIGNAL_INLINE + requires ! CYGSEM_LIBC_SIGNALS_RAISE_SETS_ERRNO + requires ! CYGSEM_LIBC_SIGNALS_SIGNAL_SETS_ERRNO + requires ! CYGFUN_LIBC_ATEXIT + requires ! CYGSEM_LIBC_EXIT_CALLS_FFLUSH + requires ! CYGPKG_LIBC_ENVIRONMENT + requires ! CYGSEM_LIBC_PER_THREAD_ERRNO + requires ! CYGSEM_LIBC_TIME_TIME_WORKING + requires ! CYGSEM_LIBC_TIME_SETTIME_WORKING + requires { CYGPKG_HAL_ARM || CYGPKG_HAL_MIPS || CYGPKG_HAL_MN10300 } + + no_define + description "This option enables the building of the CygMon ELF image. + The image may require further relocation or symbol + stripping before being converted to a binary image. + This is handled by a rule in the target CDL." + + make -priority 320 { + /bin/cygmon.elf : $(PREFIX)/lib/target.ld $(PREFIX)/lib/vectors.o $(PREFIX)/lib/libtarget.a $(PREFIX)/lib/libextras.a /misc/ecos_bsp.c /misc/ecos_dummy.c /misc/cpu-mon.c /misc/monitor.c /misc/monitor_cmd.c /misc/ledit.c /misc/breakpoints.c /misc/bplist-dynamic.c /misc/utils.c /misc/generic_fmt32.c /misc/generic_mem.c /misc/bsp/common/bsp.c /misc/bsp/common/bsp_if.c /misc/bsp/common/shared-data.c /misc/bsp/common/sysinfo.c /misc/bsp/common/console-io.c /misc/bsp/common/debug-io.c /misc/bsp/common/sprintf.c /misc/bsp/common/syscall.c /misc/bsp/common/printf.c /misc/bsp/common/vprintf.c /misc/bsp/common/breakpoint.c /misc/bsp/common/singlestep.c /misc/bsp/common/generic-mem.c /misc/bsp/common/bsp_cache.c /misc/bsp/common/gdb-cpu.c /misc/bsp/common/hex-utils.c + @sh -c "mkdir -p misc/bsp/common $(dir $@)" + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/ecos_bsp.o $(REPOSITORY)/$(PACKAGE)/misc/ecos_bsp.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/ecos_dummy.o $(REPOSITORY)/$(PACKAGE)/misc/ecos_dummy.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/cpu-mon.o $(REPOSITORY)/$(PACKAGE)/misc/cpu-mon.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/monitor.o $(REPOSITORY)/$(PACKAGE)/misc/monitor.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/monitor_cmd.o $(REPOSITORY)/$(PACKAGE)/misc/monitor_cmd.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/ledit.o $(REPOSITORY)/$(PACKAGE)/misc/ledit.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/breakpoints.o $(REPOSITORY)/$(PACKAGE)/misc/breakpoints.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bplist-dynamic.o $(REPOSITORY)/$(PACKAGE)/misc/bplist-dynamic.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/utils.o $(REPOSITORY)/$(PACKAGE)/misc/utils.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/generic_fmt32.o $(REPOSITORY)/$(PACKAGE)/misc/generic_fmt32.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/generic_mem.o $(REPOSITORY)/$(PACKAGE)/misc/generic_mem.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/bsp.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/bsp.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/bsp_if.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/bsp_if.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/shared-data.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/shared-data.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/sysinfo.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/sysinfo.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/console-io.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/console-io.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/debug-io.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/debug-io.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/sprintf.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/sprintf.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/syscall.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/syscall.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/printf.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/printf.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/vprintf.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/vprintf.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/breakpoint.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/breakpoint.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/singlestep.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/singlestep.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/generic-mem.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/generic-mem.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/bsp_cache.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/bsp_cache.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/gdb-cpu.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/gdb-cpu.c + $(CC) -c -I$(REPOSITORY)/$(PACKAGE)/misc $(INCLUDE_PATH) $(CFLAGS) -DHAVE_BSP -D__ECOS__ -o misc/bsp/common/hex-utils.o $(REPOSITORY)/$(PACKAGE)/misc/bsp/common/hex-utils.c + $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ $(filter-out %.ld %vectors.o, $(patsubst $(REPOSITORY)/$(PACKAGE)/%.c,%.o,$^)) + } + } +} diff --git a/packages/cygmon/v2_0/misc/Notes_CygMon_PID b/packages/cygmon/v2_0/misc/Notes_CygMon_PID new file mode 100644 index 00000000..b1fed767 --- /dev/null +++ b/packages/cygmon/v2_0/misc/Notes_CygMon_PID @@ -0,0 +1,168 @@ +=========================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +=========================================================================== + +28 Jan 2000 + +How to build and install CygMon on the PID + +Make CygMon image +~~~~~~~~~~~~~~~~~ + +Configure and build using the 'cygmon' template for the PID +target. These are the necessary CLI instructions. It can also be done +from the Configtool by selecting the appropriate templates. + + % cd /tmp + % mkdir cygmon + % cd cygmon + % ecosconfig new pid cygmon + % ecosconfig tree + % make + +This will install some files in ./install/bin: + + cygmon.elf: The built CygMon image + cygmon.bin: The image converted to binary (suitable for burning to ROM) + cygmon.img: The relocated ELF image (suitable for FLASH writing, see below) + cygmon.srec: The image converted to srecords + +Make FLASH tool +~~~~~~~~~~~~~~~ + +Again, these are the necessary CLI instructions. It can also be done +from the Configtool by selecting the appropriate templates, and +enabling the option. + + % cd /tmp + % mkdir pid-flash + % cd pid-flash + % ecosconfig new pid + % + --- ecos.ecc.orig Fri Jan 28 11:21:43 2000 + +++ ecos.ecc Fri Jan 28 11:22:01 2000 + @@ -150,7 +150,7 @@ + cdl_option CYGBLD_BUILD_FLASH_TOOL { + # Flavor: bool + # No user value, uncomment the following line to provide one. + - # user_value 0 + + user_value 1 + # value_source default + # Default value: 0 + # Requires: CYG_HAL_STARTUP == "RAM" + % ecosconfig resolve + % ecosconfig tree + % make + +The flash tool is installed in ./install/bin + +Prepare board for CygMon +~~~~~~~~~~~~~~~~~~~~~~~~ + 1. Set jumper 7-8 on LK6 [using the Angle code in the 16 bit EPROM] + 2. Set jumper 5-6 on LK6 [select 8bit ROM mode] + 3. Set jumper LK18 [ROM remap - this is also required for eCos] + 4. Set S1 to 0-0-1-1 [20MHz operation] + + +Program FLASH +~~~~~~~~~~~~~ + 1. Download the CygMon relocated image onto the PID board: + % cd /tmp + % arm-elf-gdb -nw cygmon/install/bin/cygmon.img + + (gdb) target rdi s= + Angel Debug Monitor V1.04 (Advanced RISC Machines SDT 2.11a) for PID + Built with Serial(x1), Parallel, DCC + Rebuilt on Apr 7 1998 at 22:20:43 + Serial Rate: 9600 + Connected to ARM RDI target. + (gdb) load + Loading section .rom_vectors, size 0x60 lma 0x60000 + Loading section .text, size 0xeea8 lma 0x60060 + Loading section .rodata, size 0x304c lma 0x6ef08 + Loading section .data, size 0x7f8 lma 0x71f54 + Start address 0x60060 , load size 75596 + Transfer rate: 5548 bits/sec. + (gdb) quit + + This will download the stubs onto the board at 0x60000..0x80000 + + Use /dev/ttyS0, COM1 or similar for the name. + + 2. Now download the FLASH programmer tool + % arm-elf-gdb -nw pid-flash/install/bin/prog_flash.img + + (gdb) target rdi s= + Angel Debug Monitor V1.04 (Advanced RISC Machines SDT 2.11a) for PID + Built with Serial(x1), Parallel, DCC + Rebuilt on Apr 7 1998 at 22:20:43 + Serial Rate: 9600 + Connected to ARM RDI target. + (gdb) load + Loading section .rom_vectors, size 0x60 lma 0x4000 + Loading section .text, size 0x4964 lma 0x4060 + Loading section .rodata, size 0x384 lma 0x89c4 + Loading section .data, size 0x28c lma 0x8d48 + Start address 0x4060 , load size 20436 + Transfer rate: 5449 bits/sec. + (gdb) cont + + 3. The FLASH tool will output some text on the board serial port B at + 38400 baud: + + ARM eCos + FLASH here! + manuf: 8, device: 40 + Error: Wrong Manufaturer: 08 + ... Please change FLASH jumper + + 4. This text is repeated until you remove the jumper 7-8 on LK6. Then + the output should be: + + manuf: 1F, device: A4 + AT29C040A recognised + About to program FLASH using data at 60000..80000 + *** Press RESET now to abort! + + 5. You have about 10 seconds to abort the operation by pressing + reset. After this timeout, the FLASH programming happens: + + ...Programming FLASH + All done! + + 6. Quit/kill the GDB process which will hang. + + 7. Next time you reset the board, CygMon will be in control, communicating + on serial port A at 38400 baud. See documentation for further details + on how to connect with GDB. diff --git a/packages/cygmon/v2_0/misc/arm/arm-mon.c b/packages/cygmon/v2_0/misc/arm/arm-mon.c new file mode 100644 index 00000000..30283f72 --- /dev/null +++ b/packages/cygmon/v2_0/misc/arm/arm-mon.c @@ -0,0 +1,281 @@ +//========================================================================== +// +// arm-mon.c +// +// Support code to extend the generic monitor code to support +// ARM(R) processors. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Support code to extend the generic monitor code to support +// ARM(R) processors. +// Description: Further board specific support is in other files. +// This file contains: +// register names lookup table +// +// Empty Stubs: +// Interval timer - This should really belong to the application +// operating system. +// +// Should not contain: +// low level uart getchar and putchar functions +// delay function to support uart +// +// ARM is a Registered Trademark of Advanced RISC Machines +// Limited. +// Other Brands and Trademarks are the property of their +// respective owners. +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include +#include +#include +#ifdef DISASSEMBLER +#include +#endif + +#include "cpu_info.h" +#include "monitor.h" + +/* This module is required to provide many of the services defined + in tservice.h */ + +static char *apcs_names[] = { + "a1", "a2", "a3", "a4", + "v1", "v2", "v3", "v4", + "v5", "v6", "sl", "fp", + "ip", "sp", "lr", "pc", +#if HAVE_FLOAT_REGS + "f0", "f1", "f2", "f3", + "f4", "f5", "f6", "f7", + "fps", +#endif + "ps" +}; + +static char *standard_names[] = +{ + "r0", "r1", "r2", "r3", + "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "pc", +#if HAVE_FLOAT_REGS + "f0", "f1", "f2", "f3", + "f4", "f5", "f6", "f7", + "fps", +#endif + "ps", +}; + + +void arm_othernames (void); + +struct regstruct regtab[] = +{ + { 0, REG_R0, REGTYPE_INT }, + { 0, REG_R1, REGTYPE_INT }, + { 0, REG_R2, REGTYPE_INT }, + { 0, REG_R3, REGTYPE_INT }, + { 0, REG_R4, REGTYPE_INT }, + { 0, REG_R5, REGTYPE_INT }, + { 0, REG_R6, REGTYPE_INT }, + { 0, REG_R7, REGTYPE_INT }, + { 0, REG_R8, REGTYPE_INT }, + { 0, REG_R9, REGTYPE_INT }, + { 0, REG_R10, REGTYPE_INT }, + { 0, REG_R11, REGTYPE_INT }, + { 0, REG_R12, REGTYPE_INT }, + { 0, REG_SP, REGTYPE_INT }, + { 0, REG_LR, REGTYPE_INT }, + { 0, REG_PC, REGTYPE_INT }, +#if HAVE_FLOAT_REGS + { 0, REG_F0, REGTYPE_FLOAT }, + { 0, REG_F1, REGTYPE_FLOAT }, + { 0, REG_F2, REGTYPE_FLOAT }, + { 0, REG_F3, REGTYPE_FLOAT }, + { 0, REG_F4, REGTYPE_FLOAT }, + { 0, REG_F5, REGTYPE_FLOAT }, + { 0, REG_F6, REGTYPE_FLOAT }, + { 0, REG_F6, REGTYPE_FLOAT }, + { 0, REG_FPS, REGTYPE_FLOAT }, +#endif + { 0, REG_CPSR, REGTYPE_INT }, + { 0, 0, 0 } /* Terminating element must be last */ +} ; + +void +initialize_mon(void) +{ + /* FIXME: Convert ALL variable initializations to assignments + in order to support ROMABLE CODE. + This includes the register table + */ + + /* + * Call arm_othernames to sync up Cygmon and the disassembler + * and ensure they are using the same set of registernames + */ + arm_othernames(); + + /* + * Call arm_othernames again to revert to the assembler + * default names + */ + arm_othernames(); + +} /* initialize_mon */ + + +/* + read_memory + write_memory + Defaults to generic_mem.c + */ + + +/* SET_BREAKPOINT - + CLEAR_BREAKPOINT + Defaults to generic_bp32.c + */ + + +#ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +/* Return the currently-saved value corresponding to register "regnum". */ +target_regval_t +get_register (int regnum) +{ + struct regstruct *p; + target_regval_t reg; + int offset, len; + char *dest = (char*)0; + + for (p = regtab; p->registername && p->registernumber != regnum; ++p) + ; + + if (p->registername) { + len = bsp_regsize(p->registernumber); + offset = bsp_regbyte(p->registernumber); + switch (p->registertype) { + case REGTYPE_INT: + dest = (char*)&(reg.i); + break; +#if HAVE_FLOAT_REGS + case REGTYPE_FLOAT: + dest = (char*)&(reg.f); + break; +#endif +#if HAVE_DOUBLE_REGS + case REGTYPE_DOUBLE: + dest = (char*)&(reg.d); + break; +#endif + } + if (dest) + memcpy(dest, (char *)mon_saved_regs + offset, len); + } else + reg.i = 0; + + return reg; +} + + + +/* Store VALUE in the register corresponding to REGNUM. */ +void +put_register (int regnum, target_regval_t value) +{ + int offset, len; + + len = bsp_regsize(regnum); + offset = bsp_regbyte(regnum); + memcpy((char *)mon_saved_regs + offset, &value, len); +} + +#endif // !CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +/* Change to the alternate register set names */ +void +arm_othernames (void) +{ + static int regset = 1; + char **name; + int i; + +#ifdef DISASSEMBLER + /* Change the disassembler */ + regset = arm_toggle_regnames(); +#else + regset = (regset == 0) ? 1 : 0; +#endif + + /* Change cygmon */ + if (regset == 1) + /* Disassembler is using apcs names. */ + name = apcs_names; + else + /* Disassembler is using standard names. */ + name = standard_names; + + for (i = 0; i < (sizeof(apcs_names)/sizeof(apcs_names[0])); i++) + regtab[i].registername = name[i]; +} + +#ifdef __ECOS__ + +#include +#include +#include "bsp/common/bsp_if.h" + +int +machine_syscall(HAL_SavedRegisters *regs) +{ + int res, err; + err = _bsp_do_syscall(regs->d[0], // Function + regs->d[1], regs->d[2], regs->d[3], 0, // arguments, + &res); + regs->d[0] = res; + regs->pc += 4; // Advance PC + return err; +} +#endif diff --git a/packages/cygmon/v2_0/misc/arm/board.h b/packages/cygmon/v2_0/misc/arm/board.h new file mode 100644 index 00000000..f84b8313 --- /dev/null +++ b/packages/cygmon/v2_0/misc/arm/board.h @@ -0,0 +1,82 @@ +#ifndef __CYGMON_ARM_BOARD_H__ +#define __CYGMON_ARM_BOARD_H__ +//========================================================================== +// +// board.h +// +// Cygmon board/platform configuration file +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= +// Hardware/platform/configuration specifics + +#include +#include + +#define HAVE_FLOAT_REGS 0 +#define HAVE_DOUBLE_REGS 0 +#define HAVE_CACHE 0 // FIXME +#define HAVE_USAGE 0 // FIXME +#define USE_CYGMON_PROTOTYPES 1 +#define NOMAIN 1 +#define CYGMON_SYSTEM_SERVICES 0 // Not used, fall back to BSP support +#ifdef CYGDAT_CYGMON_USE_HELP +#define USE_HELP 1 +#endif + +// For breakpoint support +#define NO_MALLOC 1 +#define MAX_BP_NUM 8 +#include "cpu_info.h" +#define TRAP_SIZE 4 +#define __set_breakpoint set_breakpoint +#define __remove_breakpoint clear_breakpoint +#define __write_mem_safe memcpy +#define WRITE_MEM_IS_MEMCPY +#define _breakinst bsp_breakinsn + +#endif // __CYGMON_ARM_BOARD_H__ diff --git a/packages/cygmon/v2_0/misc/arm/cpu.h b/packages/cygmon/v2_0/misc/arm/cpu.h new file mode 100644 index 00000000..607f0d58 --- /dev/null +++ b/packages/cygmon/v2_0/misc/arm/cpu.h @@ -0,0 +1,978 @@ +#ifndef __ARM_CPU_H__ +#define __ARM_CPU_H__ +//========================================================================== +// +// cpu.h +// +// ARM specific processor defines +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: ARM specific processor defines +// Description: ARM is a Registered Trademark of Advanced RISC Machines +// Limited. +// Other Brands and Trademarks are the property of their +// respective owners. +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include +#include +#ifdef __ECOS__ +#include +#endif + +/* + * Only define __NEED_UNDERSCORE__ for arm-coff targets + */ +#if !defined(__ELF__) +# define __NEED_UNDERSCORE__ +#endif + +/* + * Macros to glue together two tokens. + */ +# ifdef __STDC__ +# define XGLUE(a,b) a##b +# else +# define XGLUE(a,b) a/**/b +# endif + +# define GLUE(a,b) XGLUE(a,b) + +/* + * Symbol Names with leading underscore if necessary + */ +# ifdef __NEED_UNDERSCORE__ +# define SYM_NAME(name) GLUE(_,name) +# else +# define SYM_NAME(name) name +# endif /* __NEED_UNDERSCORE__ */ + +/* + * Various macros to better handle assembler/object format differences + */ +#if defined(__ASSEMBLER__) + +/* + * Assembly function start definition + */ +#ifdef __NEED_UNDERSCORE__ +.macro FUNC_START name + .global _\name + .align 4 + _\name: +.endm +#else +.macro FUNC_START name + .global \name + .align 4 + \name: +.endm +#endif + +/* + * Assembly function end definition + */ +#ifdef __NEED_UNDERSCORE__ +.macro FUNC_END name +.endm +#else +.macro FUNC_END name +.endm +#endif + +/* + * Register Prefix + */ +# ifndef __REGISTER_PREFIX__ +# define __REGISTER_PREFIX__ +# endif /* __REGISTER_PREFIX__ */ + +/* + * Immediate Prefix + */ +# ifndef __IMM_PREFIX__ +# define __IMM_PREFIX__ # +# endif /* __IMM_PREFIX__ */ + +/* + * use the right prefix for registers. + */ +# define REG(x) GLUE(__REGISTER_PREFIX__,x) + +/* + * use the right prefix for immediate values. + */ +# define IMM(x) GLUE(__IMM_PREFIX__,x) + +#endif /* defined(__ASSEMBLER__) */ + + +/* + * Setup register defines and such + */ +#if defined(__ASSEMBLER__) + +# define r0 REG (r0) +# define r1 REG (r1) +# define r2 REG (r2) +# define r3 REG (r3) + +# define r4 REG (r4) +# define r5 REG (r5) +# define r6 REG (r6) +# define r7 REG (r7) +# define r8 REG (r8) +# define r9 REG (r9) +# define r10 REG (r10) +# define r11 REG (r11) +# define r12 REG (r12) +# define r13 REG (r13) +# define sp REG (sp) +# define r14 REG (r14) +# define lr REG (lr) +# define pc REG (pc) + +# define f0 REG (f0) +# define f1 REG (f1) +# define f2 REG (f2) +# define f3 REG (f3) +# define f4 REG (f4) +# define f5 REG (f5) +# define f6 REG (f6) +# define f7 REG (f7) +# define fps REG (fps) + +# define cpsr REG (cpsr) +# define spsr REG (spsr) + +/* + * Register offset definitions + * These numbers are offsets into the ex_regs_t struct. + */ +# define r0_o 0 +# define r1_o 4 +# define r2_o 8 +# define r3_o 12 +# define r4_o 16 +# define r5_o 20 +# define r6_o 24 +# define r7_o 28 +# define r8_o 32 +# define r9_o 36 +# define r10_o 40 +# define r11_o 44 +# define r12_o 48 +# define r13_o 52 +# define sp_o r13_o +# define r14_o 56 +# define lr_o r14_o +# define pc_o 60 + +# define f0_o 64 +# define f1_o 76 +# define f2_o 88 +# define f3_o 100 +# define f4_o 112 +# define f5_o 124 +# define f6_o 136 +# define f7_o 148 +# define fps_o 160 + +# define cpsr_o 164 +# define spsvc_o 168 +# define ARM_EX_REGS_T_SIZE 172 + +#else /* !defined(__ASSEMBLER__) */ + + /* + * Register name that is used in help strings and such + */ +# define REGNAME_EXAMPLE "r0" + + /* + * Register numbers. These are assumed to match the + * register numbers used by GDB. + */ + enum __regnames { + REG_R0, + REG_R1, + REG_R2, + REG_R3, + REG_R4, + REG_R5, + REG_R6, + REG_R7, + REG_R8, + REG_R9, + REG_R10, + REG_R11, + REG_R12, + REG_R13, + REG_SP=REG_R13, + REG_R14, + REG_LR=REG_R14, + REG_PC, + + REG_F0, + REG_F1, + REG_F2, + REG_F3, + REG_F4, + REG_F5, + REG_F6, + REG_F7, + REG_FPS, + + REG_CPSR, + REG_SPSVC, + REG_MAX=REG_SPSVC + }; + + /* + * 12-byte struct for storing Floating point registers + */ + typedef struct + { + unsigned long high; + unsigned long middle; + unsigned long low; + } fp_reg; + + /* + * How registers are stored for exceptions. + */ +#ifdef __ECOS__ +#define ex_regs_t HAL_SavedRegisters +#define _r0 d[0] +#define _r1 d[1] +#define _r2 d[2] +#define _r3 d[3] +#define _r4 d[4] +#define _r5 d[5] +#define _r6 d[6] +#define _r7 d[7] +#define _r8 d[8] +#define _r9 d[9] +#define _r10 d[10] +#define _r11 fp +#define _r12 ip +#define _r13 sp +#define _r14 lr +#define _pc pc +#define _cpsr cpsr +#define _spsvc msr +#else + typedef struct + { + unsigned long _r0; + unsigned long _r1; + unsigned long _r2; + unsigned long _r3; + unsigned long _r4; + unsigned long _r5; + unsigned long _r6; + unsigned long _r7; + unsigned long _r8; + unsigned long _r9; + unsigned long _r10; + unsigned long _r11; + unsigned long _r12; + unsigned long _r13; + unsigned long _r14; + unsigned long _pc; + + fp_reg _f0; + fp_reg _f1; + fp_reg _f2; + fp_reg _f3; + fp_reg _f4; + fp_reg _f5; + fp_reg _f6; + fp_reg _f7; + unsigned long _fps; + unsigned long _cpsr; + + unsigned long _spsvc; /* saved svc mode sp */ + + } ex_regs_t; +#endif +# define _sp _r13 +# define _lr _r14 + +extern void __icache_flush(void *addr, int nbytes); +extern void __dcache_flush(void *addr, int nbytes); + +#endif /* __ASSEMBLER__ */ + + +/* + * Program Status Register Definitions + */ +#if defined(__ASSEMBLER__) +# define ARM_PSR_NEGATIVE 0x80000000 /* Negative Bit */ +# define ARM_PSR_ZERO 0x40000000 /* Zero Bit */ +# define ARM_PSR_CARRY 0x20000000 /* Carry Bit */ +# define ARM_PSR_OVERFLOW 0x10000000 /* Overflow Bit */ +# define ARM_PSR_IRQ 0x00000080 /* IRQ Bit */ +# define ARM_PSR_FIQ 0x00000040 /* FIQ Bit */ +# define ARM_PSR_THUMB_STATE 0x00000020 /* Thumb/ARM(R) Execution */ +# define ARM_PSR_MODE_MASK 0x0000001F /* ARM(R) Processor Mode Mask */ +#else /* ! defined(__ASSEMBLER__) */ + struct psr_struct { + unsigned mode : 5; + unsigned t_bit : 1; + unsigned f_bit : 1; + unsigned i_bit : 1; + unsigned rsv1 : 20; /* == 0x00000 */ + unsigned v_bit : 1; + unsigned c_bit : 1; + unsigned z_bit : 1; + unsigned n_bit : 1; + }; + + union arm_psr { + unsigned long word; + struct psr_struct psr; + }; +#endif /* __ASSEMBLER__ */ + +/* + * PSR Mode values + */ +#define ARM_PSR_MODE_USER 0x00000010 /* User mode */ +#define ARM_PSR_MODE_FIQ 0x00000011 /* FIQ mode */ +#define ARM_PSR_MODE_IRQ 0x00000012 /* IRQ mode */ +#define ARM_PSR_MODE_SVC 0x00000013 /* SVC mode */ +#define ARM_PSR_MODE_ABORT 0x00000017 /* ABORT mode */ +#define ARM_PSR_MODE_UNDEF 0x0000001B /* UNDEF mode */ +#define ARM_PSR_MODE_SYSTEM 0x0000001F /* System Mode */ +#define ARM_PSR_NUM_MODES 7 + +/* + * Core Exception vectors. + */ +#define BSP_CORE_EXC_RESET 0 +#define BSP_CORE_EXC_UNDEFINED_INSTRUCTION 1 +#define BSP_CORE_EXC_SOFTWARE_INTERRUPT 2 +#define BSP_CORE_EXC_PREFETCH_ABORT 3 +#define BSP_CORE_EXC_DATA_ABORT 4 +#define BSP_CORE_EXC_ADDRESS_ERROR_26_BIT 5 +#define BSP_CORE_EXC_IRQ 6 +#define BSP_CORE_EXC_FIQ 7 +#define BSP_MAX_EXCEPTIONS 8 +#define BSP_CORE_EXC(vec_num) (unsigned long*)(vec_num << 2) + +#define BREAKPOINT_INSN 0xE7FFDEFE /* Illegal inst opcode */ +#define SYSCALL_SWI 0x00180001 + +#if defined(__ASSEMBLER__) + .macro BREAKPOINT + .word BREAKPOINT_INSN + .endm + .macro SYSCALL + swi IMM(SYSCALL_SWI) + .endm + .macro __CLI + stmfd sp!, {r0} + mrs r0, cpsr + bic r0, r0, IMM(ARM_PSR_IRQ | ARM_PSR_FIQ) + msr cpsr, r0 + ldmfd sp!, {r0} + .endm + .macro __STI + stmfd sp!, {r0} + mrs r0, cpsr + orr r0, r0, IMM(ARM_PSR_IRQ | ARM_PSR_FIQ) + msr cpsr, r0 + ldmfd sp!, {r0} + .endm + +# if 0 + /* + * Use this code to verify a particular processing mode + */ + mrs r0, cpsr + and r0, r0, IMM(ARM_PSR_MODE_MASK) + ldr r1, =ARM_PSR_MODE_IRQ + cmps r0, r1 +0: bne 0b + PORT_TOGGLE_DEBUG +# endif /* 0 */ + +#else /* !defined(__ASSEMBLER__) */ + +# define BREAKPOINT() asm volatile(" .word 0xE7FFDEFE") +# define SYSCALL() asm volatile(" swi %0" : /* No outputs */ : "i" (SYSCALL_SWI)) +# define __cli() asm volatile(" + stmfd sp!, {r0} + mrs r0, cpsr + bic r0, r0, #0x000000C0 + msr cpsr, r0 + ldmfd sp!, {r0}") +# define __sti() asm volatile(" + stmfd sp!, {r0} + mrs r0, cpsr + orr r0, r0, #0x000000C0 + msr cpsr, r0 + ldmfd sp!, {r0}") +# define __mcr(cp_num, opcode1, Rd, CRn, CRm, opcode2) \ + asm volatile (" mcr " cp_num ", " \ + opcode1 ", " \ + "%0" ", " \ + CRn ", " \ + CRm ", " \ + opcode2 : /* no outputs */ : "r" (Rd)) +# define __mrc(cp_num, opcode1, Rd, CRn, CRm, opcode2) \ + asm volatile (" mrc " cp_num ", " \ + opcode1 ", " \ + "%0" ", " \ + CRn ", " \ + CRm ", " \ + opcode2 : "=r" (Rd) : /* no inputs */) + + static inline unsigned __get_cpsr(void) + { + unsigned long retval; + asm volatile (" mrs %0, cpsr" : "=r" (retval) : /* no inputs */ ); + return retval; + } + + static inline void __set_cpsr(unsigned val) + { + asm volatile (" msr cpsr, %0" : /* no outputs */ : "r" (val) ); + } + + static inline unsigned __get_spsr(void) + { + unsigned long retval; + asm volatile (" mrs %0, spsr" : "=r" (retval) : /* no inputs */ ); + return retval; + } + + static inline void __set_spsr(unsigned val) + { + asm volatile (" msr spsr, %0" : /* no outputs */ : "r" (val) ); + } + + static inline unsigned __get_sp(void) + { + unsigned long retval; + asm volatile (" mov %0, sp" : "=r" (retval) : /* no inputs */ ); + return retval; + } + + static inline void __set_sp(unsigned val) + { + asm volatile (" mov sp, %0" : /* no outputs */ : "r" (val) ); + } + + static inline unsigned __get_fp(void) + { + unsigned long retval; + asm volatile (" mov %0, fp" : "=r" (retval) : /* no inputs */ ); + return retval; + } + + static inline void __set_fp(unsigned val) + { + asm volatile (" mov fp, %0" : /* no outputs */ : "r" (val) ); + } + + static inline unsigned __get_pc(void) + { + unsigned long retval; + asm volatile (" mov %0, pc" : "=r" (retval) : /* no inputs */ ); + return retval; + } + + static inline void __set_pc(unsigned val) + { + asm volatile (" mov pc, %0" : /* no outputs */ : "r" (val) ); + } + + static inline unsigned __get_lr(void) + { + unsigned long retval; + asm volatile (" mov %0, lr" : "=r" (retval) : /* no inputs */ ); + return retval; + } + + static inline void __set_lr(unsigned val) + { + asm volatile (" mov lr, %0" : /* no outputs */ : "r" (val) ); + } + + static inline unsigned __get_r8(void) + { + unsigned long retval; + asm volatile (" mov %0, r8" : "=r" (retval) : /* no inputs */ ); + return retval; + } + + static inline void __set_r8(unsigned val) + { + asm volatile (" mov r8, %0" : /* no outputs */ : "r" (val) ); + } + + static inline unsigned __get_r9(void) + { + unsigned long retval; + asm volatile (" mov %0, r9" : "=r" (retval) : /* no inputs */ ); + return retval; + } + + static inline void __set_r9(unsigned val) + { + asm volatile (" mov r9, %0" : /* no outputs */ : "r" (val) ); + } + + static inline unsigned __get_r10(void) + { + unsigned long retval; + asm volatile (" mov %0, r10" : "=r" (retval) : /* no inputs */ ); + return retval; + } + + static inline void __set_r10(unsigned val) + { + asm volatile (" mov r10, %0" : /* no outputs */ : "r" (val) ); + } + + static inline unsigned __get_r11(void) + { + unsigned long retval; + asm volatile (" mov %0, r11" : "=r" (retval) : /* no inputs */ ); + return retval; + } + + static inline void __set_r11(unsigned val) + { + asm volatile (" mov r11, %0" : /* no outputs */ : "r" (val) ); + } + + static inline unsigned __get_r12(void) + { + unsigned long retval; + asm volatile (" mov %0, r12" : "=r" (retval) : /* no inputs */ ); + return retval; + } + + static inline void __set_r12(unsigned val) + { + asm volatile (" mov r12, %0" : /* no outputs */ : "r" (val) ); + } + +#endif /* defined(__ASSEMBLER__) */ + +#define GDB_BREAKPOINT_VECTOR BSP_CORE_EXC_UNDEFINED_INSTRUCTION +#define GDB_SYSCALL_VECTOR BSP_CORE_EXC_SOFTWARE_INTERRUPT + +#define ARM_INST_SIZE sizeof(unsigned long) +#define GDB_BREAKPOINT_INST_SIZE ARM_INST_SIZE + +#ifdef __CPU_LH77790A__ +# include +#endif /* __CPU_LH77790A__ */ + +#if !defined(__ASSEMBLER__) +/* + * Define the CPU specific data + */ +#ifdef __CPU_LH77790A__ + typedef struct { + unsigned char lh77790a_port_control_shadow; + } arm_cpu_data; +#endif /* __CPU_LH77790A__ */ +#endif /* !defined(__ASSEMBLER__) */ + +#ifdef __CPU_SA110__ +#include +#endif /* __CPU_SA110__ */ + +#ifdef __CPU_SA1100__ +#include +#endif /* __CPU_SA110__ */ + +#ifdef __CPU_710T__ +#include +#endif /* __CPU_710T__ */ + +#ifdef MMU +/* + * ARM(R) MMU Definitions + */ + +#ifndef __ASSEMBLER__ +extern void *page1; +#endif /* __ASSEMBLER__ */ + +/* + * ARM(R) Cache and MMU Control Registers + * + * Accessed through coprocessor instructions. + */ +#ifdef __ASSEMBLER__ +# define ARM_CACHE_COPROCESSOR_NUM p15 +# define ARM_COPROCESSOR_OPCODE_DONT_CARE 0x0 +# define ARM_COPROCESSOR_RM_DONT_CARE c0 +#else /* __ASSEMBLER__ */ +# define ARM_CACHE_COPROCESSOR_NUM "p15" +# define ARM_COPROCESSOR_OPCODE_DONT_CARE "0x0" +# define ARM_COPROCESSOR_RM_DONT_CARE "c0" +#endif /* __ASSEMBLER__ */ + +#ifdef __ASSEMBLER__ +# define ARM_ID_REGISTER c0 +# define ARM_CONTROL_REGISTER c1 +# define ARM_TRANSLATION_TABLE_BASE_REGISTER c2 +# define ARM_DOMAIN_ACCESS_CONTROL_REGISTER c3 +# define ARM_FAULT_STATUS_REGISTER c5 +# define ARM_FAULT_ADDRESS_REGISTER c6 +# define ARM_CACHE_OPERATIONS_REGISTER c7 +# define ARM_TLB_OPERATIONS_REGISTER c8 +# define ARM_READ_BUFFER_OPERATIONS_REGISTER c9 +#else /* __ASSEMBLER__ */ +# define ARM_ID_REGISTER "c0" +# define ARM_CONTROL_REGISTER "c1" +# define ARM_TRANSLATION_TABLE_BASE_REGISTER "c2" +# define ARM_DOMAIN_ACCESS_CONTROL_REGISTER "c3" +# define ARM_FAULT_STATUS_REGISTER "c5" +# define ARM_FAULT_ADDRESS_REGISTER "c6" +# define ARM_CACHE_OPERATIONS_REGISTER "c7" +# define ARM_TLB_OPERATIONS_REGISTER "c8" +# define ARM_READ_BUFFER_OPERATIONS_REGISTER "c9" +#endif /* __ASSEMBLER__ */ + +/* + * SA-1100 Cache and MMU ID Register value + */ +#define ARM_ID_MASK 0xFFFFFFF0 +#define ARM_ID_VALUE 0x4401a110 + +/* + * SA-1100 Cache Control Register Bit Fields and Masks + */ +#define ARM_MMU_DISABLED 0x00000000 +#define ARM_MMU_ENABLED 0x00000001 +#define ARM_MMU_MASK 0x00000001 +#define ARM_ADDRESS_FAULT_DISABLED 0x00000000 +#define ARM_ADDRESS_FAULT_ENABLED 0x00000002 +#define ARM_ADDRESS_FAULT_MASK 0x00000002 +#define ARM_DATA_CACHE_DISABLED 0x00000000 +#define ARM_DATA_CACHE_ENABLED 0x00000004 +#define ARM_DATA_CACHE_MASK 0x00000004 +#define ARM_WRITE_BUFFER_DISABLED 0x00000000 +#define ARM_WRITE_BUFFER_ENABLED 0x00000008 +#define ARM_WRITE_BUFFER_MASK 0x00000008 +#define ARM_LITTLE_ENDIAN 0x00000000 +#define ARM_BIG_ENDIAN 0x00000080 +#define ARM_ACCESS_CHECKS_NONE 0x00000000 +#define ARM_ACCESS_CHECKS_SYSTEM 0x00000100 +#define ARM_ACCESS_CHECKS_ROM 0x00000200 +#define ARM_INSTRUCTION_CACHE_DISABLED 0x00000000 +#define ARM_INSTRUCTION_CACHE_ENABLED 0x00001000 +#define ARM_INSTRUCTION_CACHE_MASK 0x00001000 +#define ARM_VIRTUAL_IVR_BASE_00000000 0x00000000 +#define ARM_VIRTUAL_IVR_BASE_FFFF0000 0x00002000 +#define ARM_CONTROL_SBZ_MASK 0x00001FFF + +/* + * SA-1100 Translation Table Base Bit Masks + */ +#define ARM_TRANSLATION_TABLE_MASK 0xFFFFC000 + +/* + * SA-1100 Domain Access Control Bit Masks + */ +#define ARM_DOMAIN_0_MASK 0x00000003 +#define ARM_DOMAIN_1_MASK 0x0000000C +#define ARM_DOMAIN_2_MASK 0x00000030 +#define ARM_DOMAIN_3_MASK 0x000000C0 +#define ARM_DOMAIN_4_MASK 0x00000300 +#define ARM_DOMAIN_5_MASK 0x00000C00 +#define ARM_DOMAIN_6_MASK 0x00003000 +#define ARM_DOMAIN_7_MASK 0x0000C000 +#define ARM_DOMAIN_8_MASK 0x00030000 +#define ARM_DOMAIN_9_MASK 0x000C0000 +#define ARM_DOMAIN_10_MASK 0x00300000 +#define ARM_DOMAIN_11_MASK 0x00C00000 +#define ARM_DOMAIN_12_MASK 0x03000000 +#define ARM_DOMAIN_13_MASK 0x0C000000 +#define ARM_DOMAIN_14_MASK 0x30000000 +#define ARM_DOMAIN_15_MASK 0xC0000000 + +#define ARM_ACCESS_TYPE_NO_ACCESS(domain_num) (0x0 << (domain_num)) +#define ARM_ACCESS_TYPE_CLIENT(domain_num) (0x1 << (domain_num)) +#define ARM_ACCESS_TYPE_MANAGER(domain_num) (0x3 << (domain_num)) + +/* + * SA-1100 Fault Status Bit Masks + */ +#define ARM_FAULT_STATUS_MASK 0x0000000F +#define ARM_DOMAIN_MASK 0x000000F0 +#define ARM_DATA_BREAKPOINT_MASK 0x00000200 + +/* + * SA-1100 Cache Control Operations Definitions + */ +#ifdef __ASSEMBLER__ +# define ARM_FLUSH_CACHE_INST_DATA_OPCODE 0x0 +# define ARM_FLUSH_CACHE_INST_DATA_RM c7 +# define ARM_FLUSH_CACHE_INST_OPCODE 0x0 +# define ARM_FLUSH_CACHE_INST_RM c5 +# define ARM_FLUSH_CACHE_DATA_OPCODE 0x0 +# define ARM_FLUSH_CACHE_DATA_RM c6 +# define ARM_FLUSH_CACHE_DATA_SINGLE_OPCODE 0x1 +# define ARM_FLUSH_CACHE_DATA_SINGLE_RM c6 +# define ARM_CLEAN_CACHE_DATA_ENTRY_OPCODE 0x1 +# define ARM_CLEAN_CACHE_DATA_ENTRY_RM c10 +# define ARM_DRAIN_CACHE_WRITE_BUFFER_OPCODE 0x4 +# define ARM_DRAIN_CACHE_WRITE_BUFFER_RM c10 +#else /* __ASSEMBLER__ */ +# define ARM_FLUSH_CACHE_INST_DATA_OPCODE "0x0" +# define ARM_FLUSH_CACHE_INST_DATA_RM "c7" +# define ARM_FLUSH_CACHE_INST_OPCODE "0x0" +# define ARM_FLUSH_CACHE_INST_RM "c5" +# define ARM_FLUSH_CACHE_DATA_OPCODE "0x0" +# define ARM_FLUSH_CACHE_DATA_RM "c6" +# define ARM_FLUSH_CACHE_DATA_SINGLE_OPCODE "0x1" +# define ARM_FLUSH_CACHE_DATA_SINGLE_RM "c6" +# define ARM_CLEAN_CACHE_DATA_ENTRY_OPCODE "0x1" +# define ARM_CLEAN_CACHE_DATA_ENTRY_RM "c10" +# define ARM_DRAIN_CACHE_WRITE_BUFFER_OPCODE "0x4" +# define ARM_DRAIN_CACHE_WRITE_BUFFER_RM "c10" +#endif /* __ASSEMBLER__ */ + +/* + * SA-1100 TLB Operations Definitions + */ +#ifdef __ASSEMBLER__ +# define ARM_FLUSH_INST_DATA_TLB_OPCODE 0x0 +# define ARM_FLUSH_INST_DATA_TLB_RM c7 +# define ARM_FLUSH_INST_TLB_OPCODE 0x0 +# define ARM_FLUSH_INST_TLB_RM c5 +# define ARM_FLUSH_DATA_TLB_OPCODE 0x0 +# define ARM_FLUSH_DATA_TLB_RM c6 +# define ARM_FLUSH_DATA_ENTRY_TLB_OPCODE 0x1 +# define ARM_FLUSH_DATA_ENTRY_TLB_RM c6 +#else /* __ASSEMBLER__ */ +# define ARM_FLUSH_INST_DATA_TLB_OPCODE "0x0" +# define ARM_FLUSH_INST_DATA_TLB_RM "c7" +# define ARM_FLUSH_INST_TLB_OPCODE "0x0" +# define ARM_FLUSH_INST_TLB_RM "c5" +# define ARM_FLUSH_DATA_TLB_OPCODE "0x0" +# define ARM_FLUSH_DATA_TLB_RM "c6" +# define ARM_FLUSH_DATA_ENTRY_TLB_OPCODE "0x1" +# define ARM_FLUSH_DATA_ENTRY_TLB_RM "c6" +#endif /* __ASSEMBLER__ */ + +/* + * SA-1100 Read-Buffer Operations Definitions + */ +#ifdef __ASSEMBLER__ +# define ARM_FLUSH_ALL_BUFFERS_OPCODE 0x0 +# define ARM_FLUSH_ALL_BUFFERS_RM c0 +# define ARM_FLUSH_BUFFER_0_OPCODE 0x1 +# define ARM_FLUSH_BUFFER_0_RM c0 +# define ARM_FLUSH_BUFFER_1_OPCODE 0x1 +# define ARM_FLUSH_BUFFER_1_RM c1 +# define ARM_FLUSH_BUFFER_2_OPCODE 0x1 +# define ARM_FLUSH_BUFFER_2_RM c2 +# define ARM_FLUSH_BUFFER_3_OPCODE 0x1 +# define ARM_FLUSH_BUFFER_3_RM c3 +# define ARM_LOAD_BUFFER_0_1_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_0_1_WORD_RM c0 +# define ARM_LOAD_BUFFER_0_4_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_0_4_WORD_RM c4 +# define ARM_LOAD_BUFFER_0_8_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_0_8_WORD_RM c8 +# define ARM_LOAD_BUFFER_1_1_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_1_1_WORD_RM c1 +# define ARM_LOAD_BUFFER_1_4_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_1_4_WORD_RM c5 +# define ARM_LOAD_BUFFER_1_8_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_1_8_WORD_RM c9 +# define ARM_LOAD_BUFFER_2_1_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_2_1_WORD_RM c2 +# define ARM_LOAD_BUFFER_2_4_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_2_4_WORD_RM c6 +# define ARM_LOAD_BUFFER_2_8_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_2_8_WORD_RM cA +# define ARM_LOAD_BUFFER_3_1_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_3_1_WORD_RM c3 +# define ARM_LOAD_BUFFER_3_4_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_3_4_WORD_RM c7 +# define ARM_LOAD_BUFFER_3_8_WORD_OPCODE 0x2 +# define ARM_LOAD_BUFFER_3_8_WORD_RM cB +# define ARM_DISABLE_USER_MCR_ACCESS_OPCODE 0x4 +# define ARM_DISABLE_USER_MCR_ACCESS_RM c0 +# define ARM_ENABLE_USER_MCR_ACCESS_OPCODE 0x5 +# define ARM_ENABLE_USER_MCR_ACCESS_RM c0 +#else /* __ASSEMBLER__ */ +# define ARM_FLUSH_ALL_BUFFERS_OPCODE "0x0" +# define ARM_FLUSH_ALL_BUFFERS_RM "c0" +# define ARM_FLUSH_BUFFER_0_OPCODE "0x1" +# define ARM_FLUSH_BUFFER_0_RM "c0" +# define ARM_FLUSH_BUFFER_1_OPCODE "0x1" +# define ARM_FLUSH_BUFFER_1_RM "c1" +# define ARM_FLUSH_BUFFER_2_OPCODE "0x1" +# define ARM_FLUSH_BUFFER_2_RM "c2" +# define ARM_FLUSH_BUFFER_3_OPCODE "0x1" +# define ARM_FLUSH_BUFFER_3_RM "c3" +# define ARM_LOAD_BUFFER_0_1_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_0_1_WORD_RM "c0" +# define ARM_LOAD_BUFFER_0_4_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_0_4_WORD_RM "c4" +# define ARM_LOAD_BUFFER_0_8_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_0_8_WORD_RM "c8" +# define ARM_LOAD_BUFFER_1_1_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_1_1_WORD_RM "c1" +# define ARM_LOAD_BUFFER_1_4_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_1_4_WORD_RM "c5" +# define ARM_LOAD_BUFFER_1_8_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_1_8_WORD_RM "c9" +# define ARM_LOAD_BUFFER_2_1_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_2_1_WORD_RM "c2" +# define ARM_LOAD_BUFFER_2_4_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_2_4_WORD_RM "c6" +# define ARM_LOAD_BUFFER_2_8_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_2_8_WORD_RM "cA" +# define ARM_LOAD_BUFFER_3_1_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_3_1_WORD_RM "c3" +# define ARM_LOAD_BUFFER_3_4_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_3_4_WORD_RM "c7" +# define ARM_LOAD_BUFFER_3_8_WORD_OPCODE "0x2" +# define ARM_LOAD_BUFFER_3_8_WORD_RM "cB" +# define ARM_DISABLE_USER_MCR_ACCESS_OPCODE "0x4" +# define ARM_DISABLE_USER_MCR_ACCESS_RM "c0" +# define ARM_ENABLE_USER_MCR_ACCESS_OPCODE "0x5" +# define ARM_ENABLE_USER_MCR_ACCESS_RM "c0" +#endif /* __ASSEMBLER__ */ + +/* + * ARM(R) First Level Descriptor Format Definitions + */ +#ifndef __ASSEMBLER__ +struct ARM_MMU_FIRST_LEVEL_FAULT { + int id : 2; + int sbz : 30; +}; +#define ARM_MMU_FIRST_LEVEL_FAULT_ID 0x0 + +struct ARM_MMU_FIRST_LEVEL_PAGE_TABLE { + int id : 2; + int imp : 2; + int domain : 4; + int sbz : 1; + int base_address : 23; +}; +#define ARM_MMU_FIRST_LEVEL_PAGE_TABLE_ID 0x1 + +struct ARM_MMU_FIRST_LEVEL_SECTION { + int id : 2; + int b : 1; + int c : 1; + int imp : 1; + int domain : 4; + int sbz0 : 1; + int ap : 2; + int sbz1 : 8; + int base_address : 12; +}; +#define ARM_MMU_FIRST_LEVEL_SECTION_ID 0x2 + +struct ARM_MMU_FIRST_LEVEL_RESERVED { + int id : 2; + int sbz : 30; +}; +#define ARM_MMU_FIRST_LEVEL_RESERVED_ID 0x3 + +#define ARM_MMU_FIRST_LEVEL_DESCRIPTOR_ADDRESS(ttb_base, table_index) \ + (unsigned long *)((unsigned long)(ttb_base) + ((table_index) << 2)) +#define ARM_MMU_SECTION(ttb_base, actual_base, virtual_base, cacheable, bufferable, perm) \ + { \ + register union ARM_MMU_FIRST_LEVEL_DESCRIPTOR desc; \ + \ + desc.word = 0; \ + desc.section.id = ARM_MMU_FIRST_LEVEL_SECTION_ID; \ + desc.section.domain = 0; \ + desc.section.c = (cacheable); \ + desc.section.b = (bufferable); \ + desc.section.ap = (perm); \ + desc.section.base_address = (actual_base); \ + *ARM_MMU_FIRST_LEVEL_DESCRIPTOR_ADDRESS(ttb_base, (virtual_base)) = desc.word; \ + } + +union ARM_MMU_FIRST_LEVEL_DESCRIPTOR { + unsigned long word; + struct ARM_MMU_FIRST_LEVEL_FAULT fault; + struct ARM_MMU_FIRST_LEVEL_PAGE_TABLE page_table; + struct ARM_MMU_FIRST_LEVEL_SECTION section; + struct ARM_MMU_FIRST_LEVEL_RESERVED reserved; +}; + +#endif /* __ASSEMBLER__ */ + +#define ARM_UNCACHEABLE 0 +#define ARM_CACHEABLE 1 +#define ARM_UNBUFFERABLE 0 +#define ARM_BUFFERABLE 1 + +#define ARM_ACCESS_PERM_NONE_NONE 0 +#define ARM_ACCESS_PERM_RO_NONE 0 +#define ARM_ACCESS_PERM_RO_RO 0 +#define ARM_ACCESS_PERM_RW_NONE 1 +#define ARM_ACCESS_PERM_RW_RO 2 +#define ARM_ACCESS_PERM_RW_RW 3 + +#define ARM_SECTION_SIZE SZ_1M +#define ARM_SMALL_PAGE_SIZE SZ_4K +#define ARM_LARGE_PAGE_SIZE SZ_64K + +#define ARM_FIRST_LEVEL_PAGE_TABLE_SIZE SZ_16K +#define ARM_SECOND_LEVEL_PAGE_TABLE_SIZE SZ_1K + +#endif /* MMU */ + +#endif // __ARM_CPU_H__ diff --git a/packages/cygmon/v2_0/misc/arm/cpu_info.h b/packages/cygmon/v2_0/misc/arm/cpu_info.h new file mode 100644 index 00000000..e7fff004 --- /dev/null +++ b/packages/cygmon/v2_0/misc/arm/cpu_info.h @@ -0,0 +1,100 @@ +#ifndef __ARM_CPU_INFO_H__ +#define __ARM_CPU_INFO_H__ +//========================================================================== +// +// cpu_info.h +// +// Architecture information for ARM processors +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: ARM is a Registered Trademark of Advanced RISC Machines +// Limited. +// Other Brands and Trademarks are the property of their +// respective owners. +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#define IS_ARM 1 + +#ifndef __CYGMON_TYPES +#define __CYGMON_TYPES +typedef unsigned int uint32; +typedef int int32; +#endif // __CYGMON_TYPES + + +/* Temporary as long a multiple protypes are copied in multiple files */ +/* This variation does NOT clone the prototypes */ +#define NO_MALLOC 1 +#define MAX_NUM_BP 32 +#define MAX_HIST_ENTS 10 + +/* big enuf to store a trap in the BP structure */ + +#define BP_INST_T_DEFINED 1 +typedef unsigned long bp_inst_t ; + +#define MEM_ADDR_DEFINED 1 +typedef struct mem_addr { + unsigned long addr; +} mem_addr_t ; + +#ifndef TARGET_REGISTER_T_DEFINED +#define TARGET_REGISTER_T_DEFINED +typedef unsigned long target_register_t; +#endif + +#if defined(__ARMEB__) +#define PRINT_INSN print_insn_big_arm +#else +#define PRINT_INSN print_insn_little_arm +#endif + +#define OTHERNAMES_CMD arm_othernames +extern void arm_othernames (void); + +#undef BFD_MACH +#define BFD_MACH 0 + +#endif // __ARM_CPU_INFO_H__ diff --git a/packages/cygmon/v2_0/misc/board.h b/packages/cygmon/v2_0/misc/board.h new file mode 100644 index 00000000..f843f085 --- /dev/null +++ b/packages/cygmon/v2_0/misc/board.h @@ -0,0 +1,72 @@ +#ifndef __CYGMON_BOARD_H__ +#define __CYGMON_BOARD_H__ +//========================================================================== +// +// board.h +// +// Cygmon board/platform configuration file +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas, dmoseley +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= +// Hardware/platform/configuration specifics + +#include +#include + +#ifdef CYGPKG_HAL_ARM +#include "arm/board.h" +#endif + +#ifdef CYGPKG_HAL_MIPS +#include "mips/board.h" +#endif + +#ifdef CYGPKG_HAL_MN10300 +#include "mn10300/board.h" +#endif + +#endif // __CYGMON_BOARD_H__ diff --git a/packages/cygmon/v2_0/misc/bplist-dynamic.c b/packages/cygmon/v2_0/misc/bplist-dynamic.c new file mode 100644 index 00000000..1c9a8646 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bplist-dynamic.c @@ -0,0 +1,234 @@ +//========================================================================== +// +// bplist-dynamic.c +// +// Breakpoint list using dynamic memory. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Breakpoint list using dynamic memory. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include "board.h" + +#ifndef USE_ECOS_HAL_BREAKPOINTS + +#include + +#ifndef NO_MALLOC +#ifndef NO_MALLOC_H +#include "malloc.h" +#else +void free (); +char *malloc (); +#endif +#endif + +#ifdef __ECOS__ +#include +#endif /* __ECOS__ */ + +/* + * A simple target breakpoint list using malloc. + * To use this package, you must define TRAP_SIZE to be the size + * in bytes of a trap instruction (max if there's more than one), + * and export a char array called _breakinst that contains a + * breakpoint trap. This package will copy trap instructions + * from _breakinst into the breakpoint locations. + */ + +static struct breakpoint_list { + target_register_t addr; + char old_contents [TRAP_SIZE]; + struct breakpoint_list *next; + char in_memory; +} *breakpoint_list = NULL; + +#ifdef NO_MALLOC +static struct breakpoint_list bp_list [MAX_BP_NUM]; +static struct breakpoint_list *free_bp_list = NULL; +static int curr_bp_num = 0; +#endif + +#ifndef BREAKINST_DEFINED +#define BREAKINST_DEFINED +extern unsigned char _breakinst[]; +#endif + +int +__set_breakpoint (target_register_t addr) +{ + struct breakpoint_list **addent = &breakpoint_list; + struct breakpoint_list *l = breakpoint_list; + struct breakpoint_list *newent; + + while (l != NULL && l->addr < addr) + { + addent = &l->next; + l = l->next; + } + + if (l != NULL && l->addr == addr) + return 2; + +#ifdef NO_MALLOC + if (free_bp_list != NULL) + { + newent = free_bp_list; + free_bp_list = free_bp_list->next; + } + else + { + if (curr_bp_num < MAX_BP_NUM) + { + newent = &bp_list[curr_bp_num++]; + } + else + { + return 1; + } + } +#else + newent = (struct breakpoint_list *) malloc (sizeof (struct breakpoint_list)); +#endif + newent->addr = addr; + newent->in_memory = 0; + newent->next = l; + *addent = newent; + return 0; +} + +int +__remove_breakpoint (target_register_t addr) +{ + struct breakpoint_list *l = breakpoint_list; + struct breakpoint_list *prev = NULL; + + while (l != NULL && l->addr < addr) + { + prev = l; + l = l->next; + } + + if (l == NULL) + return 1; + + if (l->in_memory) + { + __write_mem_safe (&l->old_contents[0], + (void*)l->addr, + sizeof (l->old_contents)); + } + + if (prev == NULL) + breakpoint_list = l->next; + else + prev->next = l->next; + +#ifdef NO_MALLOC + l->next = free_bp_list; + free_bp_list = l; +#else + free (l); +#endif + return 0; +} + +#include +#include +void +__cygmon_install_breakpoints (void) +{ + struct breakpoint_list *l = breakpoint_list; + + while (l != NULL) + { + if (! l->in_memory) + { + int len = sizeof (l->old_contents); + + if (__read_mem_safe (&l->old_contents[0], (void*)l->addr, len) == len) + { +#ifdef WRITE_MEM_IS_MEMCPY + if (__write_mem_safe (_breakinst, (void*)l->addr, len) == (void*)l->addr) +#else + if (__write_mem_safe (_breakinst, (void*)l->addr, len) == len) +#endif + { + l->in_memory = 1; + } + } + } + l = l->next; + } + flush_i_cache (); +} + +void +__cygmon_clear_breakpoints (void) +{ + struct breakpoint_list *l = breakpoint_list; + + while (l != NULL) + { + if (l->in_memory) + { + int len = sizeof (l->old_contents); + +#ifdef WRITE_MEM_IS_MEMCPY + if (__write_mem_safe (_breakinst, (void*)l->addr, len) == (void*)l->addr) +#else + if (__write_mem_safe (&l->old_contents[0], (void*)l->addr, len) == len) +#endif + { + l->in_memory = 0; + } + } + l = l->next; + } + flush_i_cache (); +} + +#endif // USE_ECOS_HAL_BREAKPOINTS diff --git a/packages/cygmon/v2_0/misc/breakpoints.c b/packages/cygmon/v2_0/misc/breakpoints.c new file mode 100644 index 00000000..0a489d37 --- /dev/null +++ b/packages/cygmon/v2_0/misc/breakpoints.c @@ -0,0 +1,220 @@ +//========================================================================== +// +// breakpoints.c +// +// Support aribtrary set of breakpoints. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include "board.h" + +#ifndef USE_ECOS_HAL_BREAKPOINTS + +#include +#ifdef HAVE_BSP +#include +#include +#endif + +#include "monitor.h" +#include "tservice.h" +#include "stub-tservice.h" + +#include "fmt_util.h" + + +static struct bp *last_bp_ptr; +static struct bp *first_bp_ptr; + +#ifdef NO_MALLOC +static struct bp *free_bp_list; +static struct bp bp_list[MAX_NUM_BP]; +static int curr_bp_num; +#endif + +int +add_mon_breakpoint (mem_addr_t location) +{ + struct bp *ptr; + struct bp *new_bp_ptr; + + for (ptr = first_bp_ptr; ptr != NULL; ptr = ptr->next) + { + if (MEM_ADDR_EQ_P (ptr->address, location)) + return 1; + } +#ifdef NO_MALLOC + if (free_bp_list != NULL) + { + new_bp_ptr = free_bp_list; + free_bp_list = new_bp_ptr->next; + } + else + { + if (curr_bp_num < MAX_NUM_BP) + { + new_bp_ptr = &bp_list[curr_bp_num++]; + } + else + { + xprintf ("No more breakpoints\n"); + return 1; + } + } +#else + new_bp_ptr = (struct bp *)malloc (sizeof (struct bp)); +#endif + + if (first_bp_ptr == NULL) + { + first_bp_ptr = new_bp_ptr; + } + else + { + last_bp_ptr->next = new_bp_ptr; + } + last_bp_ptr = new_bp_ptr; + + last_bp_ptr->next = NULL; + last_bp_ptr->address = location; + last_bp_ptr->in_memory = 0; + return 0; +} + + +void +install_breakpoints (void) +{ + struct bp *ptr = first_bp_ptr; + while (ptr != NULL) + { + set_breakpoint (ptr); + ptr = ptr->next; + } +} + + +void +clear_breakpoints (void) +{ + struct bp *ptr = first_bp_ptr; + + while (ptr != NULL) + { + clear_breakpoint (ptr); + ptr = ptr->next; + } +} + +int +show_breakpoints (void) +{ + struct bp *ptr; + + for (ptr = first_bp_ptr; ptr != NULL; ptr = ptr->next) + { + char buf[20]; + + addr2str (&ptr->address, buf); + xprintf ("%s\n", buf); + } + + return 0; +} + + + +int +clear_mon_breakpoint (mem_addr_t location) +{ + int error = 0; + struct bp *ptr = first_bp_ptr; + struct bp *prev_ptr = NULL; + + /* Scan the list looking for the address to clear */ + while (ptr != NULL && !MEM_ADDR_EQ_P (ptr->address, location)) + { + /* keep a pointer one behind the current position */ + prev_ptr = ptr; + ptr = ptr->next; + } + if (ptr == NULL) + { + xprintf ("That address has no breakpoint on it.\n"); + error = 1; + } + else + { + /* Just in case it's still in memory. */ + clear_breakpoint (ptr); + + /* now we'll point the previous bp->next at the one after the one + we're deleting, unless there is no previous bp. */ + if (prev_ptr != NULL) + { + prev_ptr->next = ptr->next; + } + + if (first_bp_ptr == ptr) + first_bp_ptr = ptr->next; + + if (last_bp_ptr == ptr) + last_bp_ptr = prev_ptr; + + /* eliminate the offending bp struct */ +#ifdef NO_MALLOC + ptr->next = free_bp_list; + free_bp_list = ptr; +#else + free (ptr); +#endif + } + return error; +} + +#endif /* USE_ECOS_HAL_BREAKPOINTS */ diff --git a/packages/cygmon/v2_0/misc/bsp/arm/gdb-cpu.c b/packages/cygmon/v2_0/misc/bsp/arm/gdb-cpu.c new file mode 100644 index 00000000..00309828 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/arm/gdb-cpu.c @@ -0,0 +1,208 @@ +//========================================================================== +// +// gdb-cpu.c +// +// CPU specific support for GDB stub. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: CPU specific support for GDB stub. +// Description: ARM is a Registered Trademark of Advanced RISC Machines +// Limited. +// Other Brands and Trademarks are the property of their +// respective owners. +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include +#include +#include "insn.h" +#include "gdb.h" + +/* + * Return byte offset within the saved register area of the + * given register. + */ +int +bsp_regbyte(int regno) +{ + switch(regno) + { + case REG_R0: return (int)&(((ex_regs_t*)0)->_r0); break; + case REG_R1: return (int)&(((ex_regs_t*)0)->_r1); break; + case REG_R2: return (int)&(((ex_regs_t*)0)->_r2); break; + case REG_R3: return (int)&(((ex_regs_t*)0)->_r3); break; + case REG_R4: return (int)&(((ex_regs_t*)0)->_r4); break; + case REG_R5: return (int)&(((ex_regs_t*)0)->_r5); break; + case REG_R6: return (int)&(((ex_regs_t*)0)->_r6); break; + case REG_R7: return (int)&(((ex_regs_t*)0)->_r7); break; + case REG_R8: return (int)&(((ex_regs_t*)0)->_r8); break; + case REG_R9: return (int)&(((ex_regs_t*)0)->_r9); break; + case REG_R10: return (int)&(((ex_regs_t*)0)->_r10); break; + case REG_R11: return (int)&(((ex_regs_t*)0)->_r11); break; + case REG_R12: return (int)&(((ex_regs_t*)0)->_r12); break; + case REG_SP: return (int)&(((ex_regs_t*)0)->_sp); break; + case REG_LR: return (int)&(((ex_regs_t*)0)->_lr); break; + case REG_PC: return (int)&(((ex_regs_t*)0)->_pc); break; + +#ifndef __ECOS__ + case REG_F0: return (int)&(((ex_regs_t*)0)->_f0); break; + case REG_F1: return (int)&(((ex_regs_t*)0)->_f1); break; + case REG_F2: return (int)&(((ex_regs_t*)0)->_f2); break; + case REG_F3: return (int)&(((ex_regs_t*)0)->_f3); break; + case REG_F4: return (int)&(((ex_regs_t*)0)->_f4); break; + case REG_F5: return (int)&(((ex_regs_t*)0)->_f5); break; + case REG_F6: return (int)&(((ex_regs_t*)0)->_f6); break; + case REG_F7: return (int)&(((ex_regs_t*)0)->_f7); break; + case REG_FPS: return (int)&(((ex_regs_t*)0)->_fps); break; +#endif + + case REG_CPSR: return (int)&(((ex_regs_t*)0)->_cpsr); break; + case REG_SPSVC: return (int)&(((ex_regs_t*)0)->_spsvc); break; + } + + return 0; +} + + +/* + * Return size in bytes of given register. + */ +int +bsp_regsize(int regno) +{ + switch(regno) + { + case REG_R0: return (sizeof (((ex_regs_t*)0)->_r0)); break; + case REG_R1: return (sizeof (((ex_regs_t*)0)->_r1)); break; + case REG_R2: return (sizeof (((ex_regs_t*)0)->_r2)); break; + case REG_R3: return (sizeof (((ex_regs_t*)0)->_r3)); break; + case REG_R4: return (sizeof (((ex_regs_t*)0)->_r4)); break; + case REG_R5: return (sizeof (((ex_regs_t*)0)->_r5)); break; + case REG_R6: return (sizeof (((ex_regs_t*)0)->_r6)); break; + case REG_R7: return (sizeof (((ex_regs_t*)0)->_r7)); break; + case REG_R8: return (sizeof (((ex_regs_t*)0)->_r8)); break; + case REG_R9: return (sizeof (((ex_regs_t*)0)->_r9)); break; + case REG_R10: return (sizeof (((ex_regs_t*)0)->_r10)); break; + case REG_R11: return (sizeof (((ex_regs_t*)0)->_r11)); break; + case REG_R12: return (sizeof (((ex_regs_t*)0)->_r12)); break; + case REG_SP: return (sizeof (((ex_regs_t*)0)->_sp)); break; + case REG_LR: return (sizeof (((ex_regs_t*)0)->_lr)); break; + case REG_PC: return (sizeof (((ex_regs_t*)0)->_pc)); break; + +#ifndef __ECOS__ + case REG_F0: return (sizeof (((ex_regs_t*)0)->_f0)); break; + case REG_F1: return (sizeof (((ex_regs_t*)0)->_f1)); break; + case REG_F2: return (sizeof (((ex_regs_t*)0)->_f2)); break; + case REG_F3: return (sizeof (((ex_regs_t*)0)->_f3)); break; + case REG_F4: return (sizeof (((ex_regs_t*)0)->_f4)); break; + case REG_F5: return (sizeof (((ex_regs_t*)0)->_f5)); break; + case REG_F6: return (sizeof (((ex_regs_t*)0)->_f6)); break; + case REG_F7: return (sizeof (((ex_regs_t*)0)->_f7)); break; + case REG_FPS: return (sizeof (((ex_regs_t*)0)->_fps)); break; +#endif + + case REG_CPSR: return (sizeof (((ex_regs_t*)0)->_cpsr)); break; + case REG_SPSVC: return (sizeof (((ex_regs_t*)0)->_spsvc)); break; + } + + return 0; +} + + +/* + * Given an exception number and a pointer to saved registers, + * return a GDB signal value. + */ +int +bsp_get_signal(int exc_nr, void *saved_regs) +{ + int sig = TARGET_SIGNAL_TRAP; + ex_regs_t *regs = (ex_regs_t *)saved_regs; + + switch (exc_nr) { + case BSP_CORE_EXC_UNDEFINED_INSTRUCTION: + { + union arm_insn inst; + if (bsp_memory_read((void *)regs->_pc, 0, ARM_INST_SIZE * 8, 1, &(inst.word)) != 0) + { + /* + * We were able to read this address. It must be a valid address. + */ + if (inst.word == BREAKPOINT_INSN) + sig = TARGET_SIGNAL_TRAP; + } + else + sig = TARGET_SIGNAL_ILL; + } + break; + case BSP_CORE_EXC_SOFTWARE_INTERRUPT: sig = TARGET_SIGNAL_TRAP; break; + case BSP_CORE_EXC_PREFETCH_ABORT: sig = TARGET_SIGNAL_BUS; break; + case BSP_CORE_EXC_DATA_ABORT: sig = TARGET_SIGNAL_BUS; break; + case BSP_CORE_EXC_ADDRESS_ERROR_26_BIT: sig = TARGET_SIGNAL_BUS; break; + case BSP_CORE_EXC_IRQ: sig = TARGET_SIGNAL_INT; break; + case BSP_CORE_EXC_FIQ: sig = TARGET_SIGNAL_INT; break; + default: sig = TARGET_SIGNAL_TRAP; break; + } + + return sig; +} + + +/* + * Set the PC value in the saved registers. + */ +void +bsp_set_pc(unsigned long pc, void *saved_regs) +{ + ((ex_regs_t *)saved_regs)->_pc = pc; +} + + +/* + * Get the PC value from the saved registers. + */ +unsigned long +bsp_get_pc(void *saved_regs) +{ + return ((ex_regs_t *)saved_regs)->_pc; +} diff --git a/packages/cygmon/v2_0/misc/bsp/arm/gdb-cpu.h b/packages/cygmon/v2_0/misc/bsp/arm/gdb-cpu.h new file mode 100644 index 00000000..9ee631b9 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/arm/gdb-cpu.h @@ -0,0 +1,61 @@ +#ifndef __BSP_ARM_GDB_CPU_H__ +#define __BSP_ARM_GDB_CPU_H__ +//========================================================================== +// +// gdb-cpu.h +// +// CPU specific definitions for GDB stub. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: CPU specific definitions for GDB stub. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +/* + * Number of registers that gdb is interested in. + */ +#define NUMREGS 26 + +#endif // __BSP_ARM_GDB_CPU_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/arm/gdb.h b/packages/cygmon/v2_0/misc/bsp/arm/gdb.h new file mode 100644 index 00000000..37906d84 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/arm/gdb.h @@ -0,0 +1,58 @@ +#ifndef __BSP_ARM_GDB_H__ +#define __BSP_ARM_GDB_H__ +//========================================================================== +// +// gdb.h +// +// +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include "../common/gdb.h" + +#endif // __BSP_ARM_GDB_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/arm/insn.h b/packages/cygmon/v2_0/misc/bsp/arm/insn.h new file mode 100644 index 00000000..44dc3de0 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/arm/insn.h @@ -0,0 +1,482 @@ +#ifndef __BSP_ARM_INSN_H__ +#define __BSP_ARM_INSN_H__ +//========================================================================== +// +// insn.h +// +// ARM(R) instruction descriptions. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: ARM(R) instruction descriptions. +// Description: ARM is a Registered Trademark of Advanced RISC Machines +// Limited. +// Other Brands and Trademarks are the property of their +// respective owners. +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +/* Data Processing Immediate Type */ +struct dpi_type { + unsigned immediate : 8; + unsigned rotate : 4; + unsigned Rd : 4; + unsigned Rn : 4; + unsigned S_bit : 1; + unsigned opcode : 4; + unsigned rsv1 : 3; /* == 001b */ + unsigned cond : 4; +}; +#define DPI_RSV1_VALUE 0x1 + +/* Data Processing Immediate Shift Type */ +struct dpis_type { + unsigned Rm : 4; + unsigned rsv2 : 1; /* == 0b */ + unsigned shift : 2; + unsigned shift_immed : 5; + unsigned Rd : 4; + unsigned Rn : 4; + unsigned S_bit : 1; + unsigned opcode : 4; + unsigned rsv1 : 3; /* == 000b */ + unsigned cond : 4; +}; +#define DPIS_RSV1_VALUE 0x0 +#define DPIS_RSV2_VALUE 0x0 + +/* Data Processing Register Shift Type */ +struct dprs_type { + unsigned Rm : 4; + unsigned rsv3 : 1; /* == 1b */ + unsigned shift : 2; + unsigned rsv2 : 1; /* == 0b */ + unsigned Rs : 4; + unsigned Rd : 4; + unsigned Rn : 4; + unsigned S_bit : 1; + unsigned opcode : 4; + unsigned rsv1 : 3; /* == 000b */ + unsigned cond : 4; +}; +#define DPRS_RSV1_VALUE 0x0 +#define DPRS_RSV2_VALUE 0x0 +#define DPRS_RSV3_VALUE 0x1 + +/* Multiply Type */ +struct m_type { + unsigned Rm : 4; + unsigned rsv2 : 4; /* == 1001b */ + unsigned Rs : 4; + unsigned Rn : 4; + unsigned Rd : 4; + unsigned S_bit : 1; + unsigned A_bit : 1; + unsigned rsv1 : 6; /* == 000000b */ + unsigned cond : 4; +}; +#define M_RSV1_VALUE 0x0 +#define M_RSV2_VALUE 0x9 + +/* Multiply Long Type */ +struct ml_type { + unsigned Rm : 4; + unsigned rsv2 : 4; /* == 1001b */ + unsigned Rs : 4; + unsigned RdLo : 4; + unsigned RdHi : 4; + unsigned S_bit : 1; + unsigned A_bit : 1; + unsigned U_bit : 1; + unsigned rsv1 : 5; /* == 00001b */ + unsigned cond : 4; +}; +#define ML_RSV1_VALUE 0x1 +#define ML_RSV2_VALUE 0x9 + +/* Move from status register Type */ +struct mrs_type { + unsigned SBZ : 12; + unsigned Rd : 4; + unsigned SBO : 4; + unsigned rsv2 : 2; /* == 00b */ + unsigned R_bit : 1; + unsigned rsv1 : 5; /* == 00010b */ + unsigned cond : 4; +}; +#define MRS_RSV1_VALUE 0x2 +#define MRS_RSV2_VALUE 0x0 + +/* Move Immediate to status register Type */ +struct misr_type { + unsigned immediate : 8; + unsigned rotate : 4; + unsigned SBO : 4; + unsigned mask : 4; + unsigned rsv2 : 2; /* == 10b */ + unsigned R_bit : 1; + unsigned rsv1 : 5; /* == 00110b */ + unsigned cond : 4; +}; +#define MISR_RSV1_VALUE 0x6 +#define MISR_RSV2_VALUE 0x2 + +/* Move register to status register Type */ +struct mrsr_type { + unsigned Rm : 4; + unsigned rsv3 : 1; /* == 0b */ + unsigned SBZ : 7; + unsigned SBO : 4; + unsigned mask : 4; + unsigned rsv2 : 2; /* == 10b */ + unsigned R_bit : 1; + unsigned rsv1 : 5; /* == 00010b */ + unsigned cond : 4; +}; +#define MRSR_RSV1_VALUE 0x2 +#define MRSR_RSV2_VALUE 0x2 +#define MRSR_RSV3_VALUE 0x0 + +/* Branch/Exchange Type */ +struct bx_type { + unsigned Rm : 4; + unsigned rsv2 : 4; /* == 0001b */ + unsigned SBO3 : 4; + unsigned SBO2 : 4; + unsigned SBO1 : 4; + unsigned rsv1 : 8; /* == 00010010b */ + unsigned cond : 4; +}; +#define BX_RSV1_VALUE 0x12 +#define BX_RSV2_VALUE 0x1 + +/* Load/Store Immediate Offset Type */ +struct lsio_type { + unsigned immediate : 12; + unsigned Rd : 4; + unsigned Rn : 4; + unsigned L_bit : 1; + unsigned W_bit : 1; + unsigned B_bit : 1; + unsigned U_bit : 1; + unsigned P_bit : 1; + unsigned rsv1 : 3; /* == 010b */ + unsigned cond : 4; +}; +#define LSIO_RSV1_VALUE 0x2 + +/* Load/Store Register Offset Type */ +struct lsro_type { + unsigned Rm : 4; + unsigned rsv2 : 1; /* == 0b */ + unsigned shift : 2; + unsigned shift_immed : 5; + unsigned Rd : 4; + unsigned Rn : 4; + unsigned L_bit : 1; + unsigned W_bit : 1; + unsigned B_bit : 1; + unsigned U_bit : 1; + unsigned P_bit : 1; + unsigned rsv1 : 3; /* == 011b */ + unsigned cond : 4; +}; +#define LSRO_RSV1_VALUE 0x3 +#define LSRO_RSV2_VALUE 0x0 + +/* Load/Store halfword/signed byte Immediate Offset Type */ +struct lshwi_type { + unsigned Lo_Offset : 4; + unsigned rsv4 : 1; /* == 1b */ + unsigned H_bit : 1; + unsigned S_bit : 1; + unsigned rsv3 : 1; /* == 1b */ + unsigned Hi_Offset : 4; + unsigned Rd : 4; + unsigned Rn : 4; + unsigned L_bit : 1; + unsigned W_bit : 1; + unsigned rsv2 : 1; /* == 1b */ + unsigned U_bit : 1; + unsigned P_bit : 1; + unsigned rsv1 : 3; /* == 000b */ + unsigned cond : 4; +}; +#define LSHWI_RSV1_VALUE 0x0 +#define LSHWI_RSV2_VALUE 0x1 +#define LSHWI_RSV3_VALUE 0x1 +#define LSHWI_RSV4_VALUE 0x1 + +/* Load/Store halfword/signed byte Register Offset Type */ +struct lshwr_type { + unsigned Rm : 4; + unsigned rsv4 : 1; /* == 1b */ + unsigned H_bit : 1; + unsigned S_bit : 1; + unsigned rsv3 : 1; /* == 1b */ + unsigned SBZ : 4; + unsigned Rd : 4; + unsigned Rn : 4; + unsigned L_bit : 1; + unsigned W_bit : 1; + unsigned rsv2 : 1; /* == 0b */ + unsigned U_bit : 1; + unsigned P_bit : 1; + unsigned rsv1 : 3; /* == 000b */ + unsigned cond : 4; +}; +#define LSHWR_RSV1_VALUE 0x3 +#define LSHWR_RSV2_VALUE 0x1 +#define LSHWR_RSV3_VALUE 0x1 +#define LSHWR_RSV4_VALUE 0x1 + +/* Swap/Swap Byte Type */ +struct swap_type { + unsigned Rm : 4; + unsigned rsv3 : 4; /* == 1001b */ + unsigned SBZ : 4; + unsigned Rd : 4; + unsigned Rn : 4; + unsigned rsv2 : 2; /* == 00b */ + unsigned B_bit : 1; + unsigned rsv1 : 5; /* == 00010b */ + unsigned cond : 4; +}; +#define SWAP_RSV1_VALUE 0x2 +#define SWAP_RSV2_VALUE 0x0 +#define SWAP_RSV3_VALUE 0x9 + +/* Load/Store Multiple Type */ +struct lsm_type { + unsigned Reg_List : 16 ; + unsigned Rn : 4; + unsigned L_bit : 1; + unsigned W_bit : 1; + unsigned S_bit : 1; + unsigned U_bit : 1; + unsigned P_bit : 1; + unsigned rsv1 : 3; /* == 100b */ + unsigned cond : 4; +}; +#define LSM_RSV1_VALUE 0x4 + +/* Coprocessor Data Processing Type */ +struct cpdp_type { + unsigned CRm : 4; + unsigned rsv2 : 1; /* == 0b */ + unsigned op2 : 3; + unsigned cp_num : 4; + unsigned CRd : 4; + unsigned CRn : 4; + unsigned op1 : 4; + unsigned rsv1 : 4; /* == 1110b */ + unsigned cond : 4; +}; +#define CPDP_RSV1_VALUE 0xE +#define CPDP_RSV2_VALUE 0x0 + +/* Coprocessor Register Transfer Type */ +struct cprt_type { + unsigned CRm : 4; + unsigned rsv2 : 1; /* == 1b */ + unsigned op2 : 3; + unsigned cp_num : 4; + unsigned Rd : 4; + unsigned CRn : 4; + unsigned L_bit : 1; + unsigned op1 : 3; + unsigned rsv1 : 4; /* == 1110b */ + unsigned cond : 4; +}; +#define CPRT_RSV1_VALUE 0xE +#define CPRT_RSV2_VALUE 0x1 + +/* Coprocessor Load/Store Type */ +struct cpls_type { + unsigned offset : 8; + unsigned cp_num : 4; + unsigned CRd : 4; + unsigned Rn : 4; + unsigned L_bit : 1; + unsigned W_bit : 1; + unsigned N_bit : 1; + unsigned U_bit : 1; + unsigned P_bit : 1; + unsigned rsv1 : 3; /* == 110b */ + unsigned cond : 4; +}; +#define CPLS_RSV1_VALUE 0x6 + +/* Branch/Branch w/ Link Type */ +struct bbl_type { + unsigned offset : 24; + unsigned L_bit : 1; + unsigned rsv1 : 3; /* == 101b */ + unsigned cond : 4; +}; +#define BBL_RSV1_VALUE 0x5 + +/* SWI Type */ +struct swi_type { + unsigned swi_number : 24; + unsigned rsv1 : 4; /* == 1111b */ + unsigned cond : 4; +}; +#define SWI_RSV1_VALUE 0xF + +/* Undefined Instruction Type */ +struct undef_type { + unsigned pad2 : 4; + unsigned rsv2 : 1; /* == 1b */ + unsigned pad1 : 20; + unsigned rsv1 : 3; /* == 011b */ + unsigned cond : 4; +}; +#define UNDEF_RSV1_VALUE 0x3 +#define UNDEF_RSV2_VALUE 0x1 + +union arm_insn { + unsigned long word; + struct dpi_type dpi; + struct dpis_type dpis; + struct dprs_type dprs; + struct m_type m; + struct ml_type ml; + struct mrs_type mrs; + struct misr_type misr; + struct mrsr_type mrsr; + struct bx_type bx; + struct lsio_type lsio; + struct lsro_type lsro; + struct lshwi_type lshwi; + struct lshwr_type lshwr; + struct swap_type swap; + struct lsm_type lsm; + struct cpdp_type cpdp; + struct cprt_type cprt; + struct cpls_type cpls; + struct bbl_type bbl; + struct swi_type swi; + struct undef_type undef; +}; + +/* + * Conditional field values + */ +#define COND_EQ 0x0 +#define COND_NE 0x1 +#define COND_CS_HI 0x2 +#define COND_CC_LO 0x3 +#define COND_MI 0x4 +#define COND_PL 0x5 +#define COND_VS 0x6 +#define COND_VC 0x7 +#define COND_HI 0x8 +#define COND_LS 0x9 +#define COND_GE 0xA +#define COND_LT 0xB +#define COND_GT 0xC +#define COND_LE 0xD +#define COND_AL 0xE +#define COND_NV 0xF + +/* + * Data Processiong Opcode field values + */ +#define DP_OPCODE_MOV 0xD +#define DP_OPCODE_MVN 0xF +#define DP_OPCODE_ADD 0x4 +#define DP_OPCODE_ADC 0x5 +#define DP_OPCODE_SUB 0x2 +#define DP_OPCODE_SBC 0x6 +#define DP_OPCODE_RSB 0x3 +#define DP_OPCODE_RSC 0x7 +#define DP_OPCODE_AND 0x0 +#define DP_OPCODE_EOR 0x1 +#define DP_OPCODE_ORR 0xC +#define DP_OPCODE_BIC 0xE +#define DP_OPCODE_CMP 0xA +#define DP_OPCODE_CMN 0xB +#define DP_OPCODE_TST 0x8 +#define DP_OPCODE_TEQ 0x9 + +/* + * Shift field values + */ +#define SHIFT_LSL 0x0 +#define SHIFT_LSR 0x1 +#define SHIFT_ASR 0x2 +#define SHIFT_ROR 0x3 +#define SHIFT_RRX 0x3 /* Special case: ROR(0) implies RRX */ + +/* + * Load/Store indexing definitions + */ +#define LS_INDEX_POST 0x0 +#define LS_INDEX_PRE 0x1 + +/* + * Load/Store offset operation definitions + */ +#define LS_OFFSET_SUB 0x0 +#define LS_OFFSET_ADD 0x1 + +/* + * Load/Store size definitions + */ +#define LS_SIZE_WORD 0x0 +#define LS_SIZE_BYTE 0x1 + +/* + * Load/Store Update definitions + */ +#define LS_NO_UPDATE 0x0 +#define LS_UPDATE 0x1 + +/* + * Load/Store Opcode definitions + */ +#define LS_STORE 0x0 +#define LS_LOAD 0x1 + +#endif // __BSP_ARM_INSN_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/arm/singlestep.c b/packages/cygmon/v2_0/misc/bsp/arm/singlestep.c new file mode 100644 index 00000000..76e994c2 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/arm/singlestep.c @@ -0,0 +1,1320 @@ +//========================================================================== +// +// singlestep.c +// +// ARM(R) specific single-step support. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: ARM(R) specific single-step support. +// Description: ARM is a Registered Trademark of Advanced RISC Machines Limited. +// Other Brands and Trademarks are the property of their +// respective owners. +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include +#include +#include +#include "insn.h" + +#define DEBUG_SINGLESTEP 0 +#define DEBUG_SINGLESTEP_VERBOSE 0 + +/* + * Structure to hold opcodes hoisted when breakpoints are + * set for single-stepping or async interruption. + */ +struct _bp_save { + unsigned long *addr; + unsigned long opcode; +}; + +#define NUM_BREAKS_SAVED 2 +static struct _bp_save _breaks[NUM_BREAKS_SAVED]; + +/* + * Insert a breakpoint at 'pc' using first available + * _bp_save struct. + */ +static void +insert_ss_break(unsigned long *pc) +{ + struct _bp_save *p = _breaks; + union arm_insn inst; + + if (p->addr && (++p)->addr) + return; + + /* + * We can't set a breakpoint at 0 + */ + if (pc == 0) + { +#if DEBUG_SINGLESTEP + bsp_printf("Setting BP at <0x%08lx>: Error\n", pc); +#endif /* DEBUG_SINGLESTEP */ + return; + } + + /* + * Make sure we are on a long word boundary. + */ + if (((unsigned long)pc & 0x3) != 0) + { + /* + * All ARM(R) instructions are on a word boundary. + * This would be invalid. Don't set a bkpt here. + */ +#if DEBUG_SINGLESTEP + bsp_printf("Setting BP at <0x%08lx>: Error\n", pc); +#endif /* DEBUG_SINGLESTEP */ + return; + } + + + /* + * What is the current instruction + */ + if (bsp_memory_read(pc, 0, ARM_INST_SIZE * 8, 1, &(inst.word)) == 0) + { + /* + * Unable to read this address, probably an invalid address. + * Don't set a breakpoint here, as it will likely cause a bus error + */ +#if DEBUG_SINGLESTEP + bsp_printf("Setting BP at <0x%08lx>: Error\n", pc); +#endif /* DEBUG_SINGLESTEP */ + return; + } + + if (inst.word != BREAKPOINT_INSN) + { + /* + * Only insert a breakpoint if we haven't done so already + * + * We may try to insert 2 breakpoints if we to a branch to + * the immediately following instruction. + */ +#if DEBUG_SINGLESTEP + bsp_printf("Setting BP at <0x%08lx>: inst <0x%08lx>\n", pc, inst.word); +#endif /* DEBUG_SINGLESTEP */ + + p->addr = pc; + p->opcode = inst.word; + inst.word = BREAKPOINT_INSN; + if (bsp_memory_write(pc, 0, ARM_INST_SIZE * 8, 1, &(inst.word)) == 0) + { + /* + * Unable to write this address, probably an invalid address. + * Don't set a breakpoint here, as it will likely cause a bus error + */ +#if DEBUG_SINGLESTEP + bsp_printf("Setting BP at <0x%08lx>: Error\n", pc); +#endif /* DEBUG_SINGLESTEP */ + return; + } + + /* flush icache and dcache, now */ + bsp_flush_dcache((void *)pc, ARM_INST_SIZE); + bsp_flush_icache((void *)pc, ARM_INST_SIZE); + +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Done setting BP at <0x%08lx>: inst <0x%08lx>\n", pc, *pc); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + } +} + +/* + * Cleanup after a singlestep. + */ +void +bsp_singlestep_cleanup(void *registers) +{ + struct _bp_save *p = _breaks; + int i; + + for (i = 0; i < NUM_BREAKS_SAVED; i++, p++) + { + if (p->addr) + { + unsigned long *old_addr = p->addr; + +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Remove BP at <0x%08lx>: inst <0x%08lx>\n", old_addr, *old_addr); +#endif /* DEBUG_SINGLESTEP */ + *(p->addr) = p->opcode; + p->addr = NULL; + + /* flush icache and dcache, now */ + bsp_flush_dcache((void *)old_addr, ARM_INST_SIZE); + bsp_flush_icache((void *)old_addr, ARM_INST_SIZE); + +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Done removing BP at <0x%08lx>: inst <0x%08lx>\n", old_addr, *old_addr); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + } + } +} + +/* + * Rotate right a value by count + */ +static unsigned long ror(unsigned long value, unsigned count) +{ + while (count-- > 0) + { + if (value & 0x1) + value = (value >> 1) | 0x80000000; + else + value = (value >> 1); + } + + return(value); +} + +/* + * Rotate right a value by 1 with extend + */ +static unsigned long rrx(union arm_psr sr, unsigned long value) +{ + if (sr.psr.c_bit) + value = (value >> 1) | 0x80000000; + else + value = (value >> 1); + + return(value); +} + +/* + * Logical shift left by count + */ +static unsigned long lsl(unsigned long value, unsigned count) +{ + value <<= count; + + return(value); +} + +/* + * Logical shift right by count + */ +static unsigned long lsr(unsigned long value, unsigned count) +{ + value >>= count; + + return(value); +} + +/* + * Arithmetic shift right by count + */ +static unsigned long asr(unsigned long value, unsigned count) +{ + unsigned long sign_ext_mask = 0; + + if (value & 0x80000000) + { + if (count >= sizeof(value)*8) + sign_ext_mask = ~0; + else + sign_ext_mask = (~0 << (sizeof(value)*8 - count)); + } + value = (value >> count) | sign_ext_mask; + + return(value); +} + +/* + * Calculate an immediate shift operand based on input shift operand, + * shift value and register address. + */ +static unsigned long immediate_shift_operand(ex_regs_t *regs, unsigned shift_immediate, + unsigned shift, unsigned Rm) +{ + unsigned char *regs_array = (unsigned char *)regs; + unsigned char *reg_ptr = ®s_array[bsp_regbyte(Rm)]; + unsigned long reg_value = *((unsigned long *)(reg_ptr)); + unsigned long rc = 0; + + BSP_ASSERT((shift_immediate >= 0) && (shift_immediate <= 0x1f)); + BSP_ASSERT((shift >= 0) && (shift <= 0x3)); + BSP_ASSERT((Rm >= 0) && (Rm <= 0xf)); + BSP_ASSERT(bsp_regsize(Rm) == sizeof(unsigned long)); + + /* + * According to the ARM(R) Manual, if Rm is PC then, + * the value used is the address of the current instruction + * plus 8 + */ + if (Rm == REG_PC) + reg_value += 8; + + switch (shift) + { + case SHIFT_LSL: + rc = lsl(reg_value, shift_immediate); + break; + + case SHIFT_LSR: + if (shift_immediate == 0) + { + /* + * Special Case: LSR IMM(0) == 0 + */ + rc = 0; + } else { + rc = lsr(reg_value, shift_immediate); + } + break; + + case SHIFT_ASR: + if (shift_immediate == 0) + { + /* + * Special Case: ASR IMM(0) + */ + if (reg_value & 0x80000000) + { + rc = 0xFFFFFFFF; + } else { + rc = 0; + } + } else { + rc = asr(reg_value, shift_immediate); + } + break; + + case SHIFT_ROR: + if (shift_immediate == 0) + { + /* + * SHIFT_RRX + * Special case: ROR(0) implies RRX + */ + rc = rrx((union arm_psr)(unsigned long)regs->_cpsr, reg_value); + } else { + rc = ror(reg_value, shift_immediate); + } + break; + + default: + BSP_ASSERT(0); + break; + } + + return (rc); +} + +/* + * Calculate a register shift operand based on input shift operand, + * and target registers. + */ +static unsigned long register_shift_operand(ex_regs_t *regs, unsigned Rs, + unsigned shift, unsigned Rm) +{ + unsigned char *regs_array = (unsigned char *)regs; + unsigned char *Rs_ptr = ®s_array[bsp_regbyte(Rs)]; + unsigned char *Rm_ptr = ®s_array[bsp_regbyte(Rm)]; + unsigned long Rs_val = *((unsigned long *)(Rs_ptr)); + unsigned long Rm_val = *((unsigned long *)(Rm_ptr)); + unsigned long rc = 0; + + /* + * Use only the least significant byte of Rs + */ + Rs_val &= 0xFF; + + BSP_ASSERT((Rs >= 0) && (Rs <= 0xf)); + BSP_ASSERT((shift >= 0) && (shift <= 0x3)); + BSP_ASSERT((Rm >= 0) && (Rm <= 0xf)); + BSP_ASSERT(bsp_regsize(Rs) == sizeof(unsigned long)); + BSP_ASSERT(bsp_regsize(Rm) == sizeof(unsigned long)); + BSP_ASSERT((Rs_val >=0) && (Rs_val <= 0xff)); + + /* + * According to the ARM(R) Manual, if Rm is PC then, + * the value used is the address of the current instruction + * plus 8 + */ + if (Rm == REG_PC) + Rm_val += 8; + + switch (shift) + { + case SHIFT_LSL: rc = lsl(Rm_val, Rs_val); break; + case SHIFT_LSR: rc = lsr(Rm_val, Rs_val); break; + case SHIFT_ASR: rc = asr(Rm_val, Rs_val); break; + case SHIFT_ROR: rc = ror(Rm_val, Rs_val); break; + default: BSP_ASSERT(0); break; + } + + return (rc); +} + +/* + * Calculate a branch exchange operand based on input destination register + */ +static unsigned long branch_exchange_operand(ex_regs_t *regs, unsigned Rm) +{ + unsigned char *regs_array = (unsigned char *)regs; + unsigned char *reg_ptr = ®s_array[bsp_regbyte(Rm)]; + unsigned long reg_value = *((unsigned long *)(reg_ptr)); + + BSP_ASSERT((Rm >= 0) && (Rm <= 0xf)); + BSP_ASSERT(bsp_regsize(Rm) == sizeof(unsigned long)); + + /* + * Clear the low-order bit + */ + return (reg_value & ~0x1); +} + +/* + * Handle a load to the PC + */ +static void handle_pc_load(unsigned size, unsigned long operand) +{ + unsigned long mem_value = 0; + + if (size == LS_SIZE_WORD) + { + if (bsp_memory_read((void*)(operand & ~0x3), 0, 32, 1, &mem_value) == 0) + { + /* + * Unable to read the memory address. + * Don't try any further. + */ +#if DEBUG_SINGLESTEP + bsp_printf("Setting BP at *(0x%08lx): Error\n", operand & ~0x3); +#endif /* DEBUG_SINGLESTEP */ + return; + } else { +#if DEBUG_SINGLESTEP + bsp_printf("Setting BP at *(0x%08lx): data <0x%08lx>\n", operand & ~0x3, mem_value); +#endif /* DEBUG_SINGLESTEP */ + } + + /* + * Handle rotations if required + */ + switch (operand & 0x3) + { + case 0x0: break; + case 0x1: mem_value = ror(mem_value, 8); break; + case 0x2: mem_value = ror(mem_value, 16); break; + case 0x3: mem_value = ror(mem_value, 24); break; + } + } else { + /* + * Byte load of the PC + */ + if (bsp_memory_read((void*)operand, 0, 8, 1, &mem_value) == 0) + { + /* + * Unable to read the memory address. + * Don't try any further. + */ +#if DEBUG_SINGLESTEP + bsp_printf("Setting BP at *(0x%08lx): Error\n", operand & ~0x3); +#endif /* DEBUG_SINGLESTEP */ + return; + } else { +#if DEBUG_SINGLESTEP + bsp_printf("Setting BP at *(0x%08lx): data <0x%08lx>\n", operand & ~0x3, mem_value); +#endif /* DEBUG_SINGLESTEP */ + } + } + + insert_ss_break((unsigned long *)mem_value); +} + +/* + * Calculate a load/store w/ Immediate offset operand based on input + * source register, offset value, and opcode (add/sub) + */ +static unsigned long load_store_immediate_operand(ex_regs_t *regs, + unsigned p_bit, + unsigned u_bit, + unsigned Rn, + unsigned offset) +{ + unsigned char *regs_array = (unsigned char *)regs; + unsigned char *reg_ptr = ®s_array[bsp_regbyte(Rn)]; + unsigned long rc = *((unsigned long *)(reg_ptr)); + + BSP_ASSERT((Rn >= 0) && (Rn <= 0xf)); + BSP_ASSERT(bsp_regsize(Rn) == sizeof(unsigned long)); + BSP_ASSERT((offset >= 0) && (offset <= 0xfff)); + BSP_ASSERT((p_bit >= 0) && (p_bit <= 1)); + BSP_ASSERT((u_bit >= 0) && (u_bit <= 1)); + + /* + * According to the ARM(R) Manual, if Rn is PC then, + * the value used is the address of the current instruction + * plus 8 + */ + if (Rn == REG_PC) + rc += 8; + + /* + * Do the update pre-index update + */ + if (p_bit == LS_INDEX_PRE) + { + if (u_bit == LS_OFFSET_SUB) + rc -= offset; + else /* opcode == LS_OFFSET_ADD */ + rc += offset; + } + + return (rc); +} + +/* + * Calculate a load/store w/ Register offset operand based on input + * source register, offset value, and opcode (add/sub) + * + * This calculates the appropriate pre-indexed operand + */ +static unsigned long load_store_register_operand(ex_regs_t *regs, + unsigned p_bit, + unsigned u_bit, + unsigned Rn, + unsigned Rm, + unsigned shift, + unsigned shift_immed) +{ + unsigned char *regs_array = (unsigned char *)regs; + unsigned char *Rn_ptr = ®s_array[bsp_regbyte(Rn)]; + unsigned long Rn_val = *((unsigned long *)(Rn_ptr)); + unsigned long rc, index; + + BSP_ASSERT((Rn >= 0) && (Rn <= 0xf)); + BSP_ASSERT((Rm >= 0) && (Rm <= 0xf)); + BSP_ASSERT(bsp_regsize(Rn) == sizeof(unsigned long)); + BSP_ASSERT(bsp_regsize(Rm) == sizeof(unsigned long)); + BSP_ASSERT((p_bit >= 0) && (p_bit <= 1)); + BSP_ASSERT((u_bit >= 0) && (u_bit <= 1)); + BSP_ASSERT((shift >= 0) && (shift <= 0x3)); + BSP_ASSERT((shift_immed >= 0) && (shift_immed <= 0x1F)); + + /* + * According to the ARM(R) Manual, if Rn is PC then + * the value used is the address of the current + * instruction plus 8 + */ + if (Rn == REG_PC) + Rn_val += 8; + + /* + * According to the ARM(R) Manual, if Rm is PC then + * the result is unpredictable. Don't do anything + * here. Just return. + */ + if (Rm == REG_PC) + return 0; + + index = immediate_shift_operand(regs, shift_immed, shift, Rm); + + rc = Rn_val; + + /* + * Do the update pre-index update + */ + if (p_bit == LS_INDEX_PRE) + { + if (u_bit == LS_OFFSET_SUB) + rc = Rn_val - index; + else /* opcode == LS_OFFSET_ADD */ + rc = Rn_val + index; + } + + return (rc); +} + +/* + * Decode all data processing immediate instructions + */ +static void decode_dpi_inst(ex_regs_t *regs, union arm_insn inst) +{ + if (inst.dpi.Rd == REG_PC) + { + unsigned long operand = ror(inst.dpi.immediate, (inst.dpi.rotate << 1)); + unsigned long *dest = 0; + unsigned carry = ((union arm_psr)(unsigned long)(regs->_cpsr)).psr.c_bit; + unsigned char *regs_array = (unsigned char *)regs; + unsigned char *Rn_ptr = ®s_array[bsp_regbyte(inst.dpi.Rn)]; + unsigned long Rn_val = *((unsigned long *)(Rn_ptr)); + +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Decoded an data processing immediate instruction.\n"); + bsp_printf("inst.dpi.immediate = 0x%x\n", inst.dpi.immediate); + bsp_printf("inst.dpi.rotate = 0x%x\n", inst.dpi.rotate); + bsp_printf("inst.dpi.Rd = 0x%x\n", inst.dpi.Rd); + bsp_printf("inst.dpi.Rn = 0x%x\n", inst.dpi.Rn); + bsp_printf("inst.dpi.S_bit = 0x%x\n", inst.dpi.S_bit); + bsp_printf("inst.dpi.opcode = 0x%x\n", inst.dpi.opcode); + bsp_printf("inst.dpi.cond = 0x%x\n", inst.dpi.cond); + bsp_printf("operand = 0x%x\n", operand); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + + /* + * According to the ARM(R) Manual, if Rn is PC then + * the value used is the address of the current + * instruction plus 8 + */ + if (inst.dpi.Rn == REG_PC) + Rn_val += 8; + + switch (inst.dpi.opcode) { + case DP_OPCODE_ADC: dest = (unsigned long *)(Rn_val + operand + carry); break; + case DP_OPCODE_ADD: dest = (unsigned long *)(Rn_val + operand); break; + case DP_OPCODE_AND: dest = (unsigned long *)(Rn_val & operand); break; + case DP_OPCODE_BIC: dest = (unsigned long *)(Rn_val & ~operand); break; + case DP_OPCODE_EOR: dest = (unsigned long *)(Rn_val ^ operand); break; + case DP_OPCODE_MOV: dest = (unsigned long *)operand; break; + case DP_OPCODE_MVN: dest = (unsigned long *)(~operand); break; + case DP_OPCODE_ORR: dest = (unsigned long *)(Rn_val | operand); break; + case DP_OPCODE_RSB: dest = (unsigned long *)(operand - Rn_val); break; + case DP_OPCODE_RSC: dest = (unsigned long *)(operand - Rn_val - !carry); break; + case DP_OPCODE_SBC: dest = (unsigned long *)(Rn_val - operand - !carry); break; + case DP_OPCODE_SUB: dest = (unsigned long *)(Rn_val - operand); break; + default: dest = (unsigned long *)0; break; + } + dest = (unsigned long *)((unsigned long)dest & ~0x3); + insert_ss_break(dest); + } +} + +/* + * Decode all data processing immediate w/ shift instructions + */ +static void decode_dpis_inst(ex_regs_t *regs, union arm_insn inst) +{ + if (inst.dpis.Rd == REG_PC) + { + unsigned long operand = immediate_shift_operand(regs, inst.dpis.shift_immed, + inst.dpis.shift, inst.dpis.Rm); + unsigned long *dest = 0; + unsigned carry = ((union arm_psr)(unsigned long)(regs->_cpsr)).psr.c_bit; + unsigned char *regs_array = (unsigned char *)regs; + unsigned char *Rn_ptr = ®s_array[bsp_regbyte(inst.dpis.Rn)]; + unsigned long Rn_val = *((unsigned long *)(Rn_ptr)); + +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Decoded an data processing immediate shift instruction.\n"); + bsp_printf("inst.dpis.Rm = 0x%x\n", inst.dpis.Rm); + bsp_printf("inst.dpis.shift = 0x%x\n", inst.dpis.shift); + bsp_printf("inst.dpis.shift_immed = 0x%x\n", inst.dpis.shift_immed); + bsp_printf("inst.dpis.Rd = 0x%x\n", inst.dpis.Rd); + bsp_printf("inst.dpis.Rn = 0x%x\n", inst.dpis.Rn); + bsp_printf("inst.dpis.S_bit = 0x%x\n", inst.dpis.S_bit); + bsp_printf("inst.dpis.opcode = 0x%x\n", inst.dpis.opcode); + bsp_printf("inst.dpis.cond = 0x%x\n", inst.dpis.cond); + bsp_printf("operand = 0x%x\n", operand); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + + /* + * According to the ARM(R) Manual, if Rn is PC then + * the value used is the address of the current + * instruction plus 8 + */ + if (inst.dpis.Rn == REG_PC) + Rn_val += 8; + + switch (inst.dpis.opcode) { + case DP_OPCODE_ADC: dest = (unsigned long *)(Rn_val + operand + carry); break; + case DP_OPCODE_ADD: dest = (unsigned long *)(Rn_val + operand); break; + case DP_OPCODE_AND: dest = (unsigned long *)(Rn_val & operand); break; + case DP_OPCODE_BIC: dest = (unsigned long *)(Rn_val & ~operand); break; + case DP_OPCODE_EOR: dest = (unsigned long *)(Rn_val ^ operand); break; + case DP_OPCODE_MOV: dest = (unsigned long *)operand; break; + case DP_OPCODE_MVN: dest = (unsigned long *)(~operand); break; + case DP_OPCODE_ORR: dest = (unsigned long *)(Rn_val | operand); break; + case DP_OPCODE_RSB: dest = (unsigned long *)(operand - Rn_val); break; + case DP_OPCODE_RSC: dest = (unsigned long *)(operand - Rn_val - !carry); break; + case DP_OPCODE_SBC: dest = (unsigned long *)(Rn_val - operand - !carry); break; + case DP_OPCODE_SUB: dest = (unsigned long *)(Rn_val - operand); break; + default: dest = (unsigned long *)0; break; + } + dest = (unsigned long *)((unsigned long)dest & ~0x3); + insert_ss_break(dest); + } +} + +/* + * Decode all data processing register w/ shift instructions + */ +static void decode_dprs_inst(ex_regs_t *regs, union arm_insn inst) +{ + if (inst.dprs.Rd == REG_PC) + { + unsigned long operand = register_shift_operand(regs, inst.dprs.Rs, + inst.dprs.shift, inst.dprs.Rm); + unsigned long *dest = 0; + unsigned carry = ((union arm_psr)(unsigned long)(regs->_cpsr)).psr.c_bit; + unsigned char *regs_array = (unsigned char *)regs; + unsigned char *Rn_ptr = ®s_array[bsp_regbyte(inst.dprs.Rn)]; + unsigned long Rn_val = *((unsigned long *)(Rn_ptr)); + +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Decoded an data processing register shift instruction.\n"); + bsp_printf("inst.dprs.Rm = 0x%x\n", inst.dprs.Rm); + bsp_printf("inst.dprs.rsv3 = 0x%x\n", inst.dprs.rsv3); + bsp_printf("inst.dprs.shift = 0x%x\n", inst.dprs.shift); + bsp_printf("inst.dprs.rsv2 = 0x%x\n", inst.dprs.rsv2); + bsp_printf("inst.dprs.Rs = 0x%x\n", inst.dprs.Rs); + bsp_printf("inst.dprs.Rd = 0x%x\n", inst.dprs.Rd); + bsp_printf("inst.dprs.Rn = 0x%x\n", inst.dprs.Rn); + bsp_printf("inst.dprs.S_bit = 0x%x\n", inst.dprs.S_bit); + bsp_printf("inst.dprs.opcode = 0x%x\n", inst.dprs.opcode); + bsp_printf("inst.dprs.rsv1 = 0x%x\n", inst.dprs.rsv1); + bsp_printf("inst.dprs.cond = 0x%x\n", inst.dprs.cond); + bsp_printf("operand = 0x%x\n", operand); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + + /* + * According to the ARM(R) Manual, if Rn is PC then + * the value used is the address of the current + * instruction plus 8 + */ + if (inst.dprs.Rn == REG_PC) + Rn_val += 8; + + switch (inst.dprs.opcode) { + case DP_OPCODE_ADC: dest = (unsigned long *)(Rn_val + operand + carry); break; + case DP_OPCODE_ADD: dest = (unsigned long *)(Rn_val + operand); break; + case DP_OPCODE_AND: dest = (unsigned long *)(Rn_val & operand); break; + case DP_OPCODE_BIC: dest = (unsigned long *)(Rn_val & ~operand); break; + case DP_OPCODE_EOR: dest = (unsigned long *)(Rn_val ^ operand); break; + case DP_OPCODE_MOV: dest = (unsigned long *)operand; break; + case DP_OPCODE_MVN: dest = (unsigned long *)(~operand); break; + case DP_OPCODE_ORR: dest = (unsigned long *)(Rn_val | operand); break; + case DP_OPCODE_RSB: dest = (unsigned long *)(operand - Rn_val); break; + case DP_OPCODE_RSC: dest = (unsigned long *)(operand - Rn_val - !carry); break; + case DP_OPCODE_SBC: dest = (unsigned long *)(Rn_val - operand - !carry); break; + case DP_OPCODE_SUB: dest = (unsigned long *)(Rn_val - operand); break; + default: dest = (unsigned long *)0; break; + } + + dest = (unsigned long *)((unsigned long)dest & ~0x3); + insert_ss_break(dest); + } +} + +/* + * Decode all multiply instructions + */ +static void decode_m_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * According to the ARM(R) Manual, if Rd is PC then + * the result is unpredictable. Don't do anything + * here. Just return. + */ +} + +/* + * Decode all multiply long instructions + */ +static void decode_ml_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * According to the ARM(R) Manual, if Rd is PC then + * the result is unpredictable. Don't do anything + * here. Just return. + */ +} + + +/* + * Decode all move from status register instructions + */ +static void decode_mrs_inst(ex_regs_t *regs, union arm_insn inst) +{ +#if 0 + if (inst.mrs.Rd == REG_PC) + { + unsigned long *dest = 0; + +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Decoded an move from status register instruction.\n"); + bsp_printf("inst.mrs.SBZ = 0x%x\n", inst.mrs.SBZ); + bsp_printf("inst.mrs.Rd = 0x%x\n", inst.mrs.Rd); + bsp_printf("inst.mrs.SBO = 0x%x\n", inst.mrs.SBO); + bsp_printf("inst.mrs.rsv2 = 0x%x\n", inst.mrs.rsv2); + bsp_printf("inst.mrs.R_bit = 0x%x\n", inst.mrs.R_bit); + bsp_printf("inst.mrs.rsv1 = 0x%x\n", inst.mrs.rsv1); + bsp_printf("inst.mrs.cond = 0x%x\n", inst.mrs.cond); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + + if (inst.mrs.R_bit == 1) + dest = (unsigned long *)regs->_spsr; + else + dest = (unsigned long *)regs->_cpsr; + + dest = (unsigned long *)((unsigned long)dest & ~0x3); + insert_ss_break(dest); + } +#endif +} + + +/* + * Decode all move immediate to status register instructions + */ +static void decode_misr_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * Can't update the PC w/ this instruction. + * Don't set any more breakpoints + */ +} + + +/* + * Decode all move register to status registers instructions + */ +static void decode_mrsr_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * Can't update the PC w/ this instruction. + * Don't set any more breakpoints + */ +} + + +/* + * Decode all branch/exchange instructions + */ +static void decode_bx_inst(ex_regs_t *regs, union arm_insn inst) +{ + unsigned long operand = branch_exchange_operand(regs, inst.bx.Rm); + +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Decoded an branch/exchange shift instruction.\n"); + bsp_printf("inst.bx.Rm = 0x%x\n", inst.bx.Rm); + bsp_printf("inst.bx.rsv2 = 0x%x\n", inst.bx.rsv2); + bsp_printf("inst.bx.SBO3 = 0x%x\n", inst.bx.SBO3); + bsp_printf("inst.bx.SBO2 = 0x%x\n", inst.bx.SBO2); + bsp_printf("inst.bx.SBO1 = 0x%x\n", inst.bx.SBO1); + bsp_printf("inst.bx.rsv1 = 0x%x\n", inst.bx.rsv1); + bsp_printf("inst.bx.cond = 0x%x\n", inst.bx.cond); + bsp_printf("operand = 0x%x\n", operand); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + + insert_ss_break((unsigned long *)operand); +} + + +/* + * Decode all load/store immediate offset instructions + */ +static void decode_lsio_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * Only support direct loads of the PC + * + * According to the ARM(R) manual, automatic updates of the PC + * are UNPREDICTABLE (ie implementation defined). + */ + if ((inst.lsio.Rd == REG_PC) && (inst.lsio.L_bit == LS_LOAD)) + { + unsigned long operand = load_store_immediate_operand(regs, inst.lsio.P_bit, + inst.lsio.U_bit, inst.lsio.Rn, + inst.lsio.immediate); + +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Decoded an load/store w/ immediate offset instruction.\n"); + bsp_printf("inst.lsio.immediate = 0x%x\n", inst.lsio.immediate); + bsp_printf("inst.lsio.Rd = 0x%x\n", inst.lsio.Rd); + bsp_printf("inst.lsio.Rn = 0x%x\n", inst.lsio.Rn); + bsp_printf("inst.lsio.L_bit = 0x%x\n", inst.lsio.L_bit); + bsp_printf("inst.lsio.W_bit = 0x%x\n", inst.lsio.W_bit); + bsp_printf("inst.lsio.B_bit = 0x%x\n", inst.lsio.B_bit); + bsp_printf("inst.lsio.U_bit = 0x%x\n", inst.lsio.U_bit); + bsp_printf("inst.lsio.P_bit = 0x%x\n", inst.lsio.P_bit); + bsp_printf("inst.lsio.rsv1 = 0x%x\n", inst.lsio.rsv1); + bsp_printf("inst.lsio.cond = 0x%x\n", inst.lsio.cond); + bsp_printf("operand = 0x%x\n", operand); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + + handle_pc_load(inst.lsio.B_bit, operand); + } +} + + +/* + * Decode all load/store register offset instructions + */ +static void decode_lsro_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * Only support direct loads of the PC + * + * According to the ARM(R) manual, automatic updates of the PC + * are UNPREDICTABLE (ie implementation defined). + */ + if ((inst.lsro.Rd == REG_PC) && (inst.lsro.L_bit == LS_LOAD)) + { + unsigned long operand = load_store_register_operand(regs, + inst.lsro.P_bit, + inst.lsro.U_bit, + inst.lsro.Rn, + inst.lsro.Rm, + inst.lsro.shift, + inst.lsro.shift_immed); +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Decoded an load/store w/ register offset instruction.\n"); + bsp_printf("inst.lsro.Rm = 0x%x\n", inst.lsro.Rm); + bsp_printf("inst.lsro.rsv2 = 0x%x\n", inst.lsro.rsv2); + bsp_printf("inst.lsro.shift = 0x%x\n", inst.lsro.shift); + bsp_printf("inst.lsro.shift_immed = 0x%x\n", inst.lsro.shift_immed); + bsp_printf("inst.lsro.Rd = 0x%x\n", inst.lsro.Rd); + bsp_printf("inst.lsro.Rn = 0x%x\n", inst.lsro.Rn); + bsp_printf("inst.lsro.L_bit = 0x%x\n", inst.lsro.L_bit); + bsp_printf("inst.lsro.W_bit = 0x%x\n", inst.lsro.W_bit); + bsp_printf("inst.lsro.B_bit = 0x%x\n", inst.lsro.B_bit); + bsp_printf("inst.lsro.U_bit = 0x%x\n", inst.lsro.U_bit); + bsp_printf("inst.lsro.P_bit = 0x%x\n", inst.lsro.P_bit); + bsp_printf("inst.lsro.rsv1 = 0x%x\n", inst.lsro.rsv1); + bsp_printf("inst.lsro.cond = 0x%x\n", inst.lsro.cond); + bsp_printf("operand = 0x%x\n", operand); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + + handle_pc_load(inst.lsro.B_bit, operand); + } +} + + +/* + * Decode all load/store halfword/signed byte immediate offset instructions + */ +static void decode_lshwi_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * According to the ARM(R) Manual, if Rd is PC then + * the result is unpredictable. Don't do anything + * here. Just return. + */ +} + + +/* + * Decode all load/store halfword/signed byte register offset instructions + */ +static void decode_lshwr_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * According to the ARM(R) Manual, if Rd is PC then + * the result is unpredictable. Don't do anything + * here. Just return. + */ +} + + +/* + * Decode all swap/swap byte instructions + */ +static void decode_swap_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * According to the ARM(R) Manual, if Rd is PC then + * the result is unpredictable. Don't do anything + * here. Just return. + */ +} + + +/* + * Decode all load/store multiple instructions + */ +static void decode_lsm_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * Only support direct load multiples where the PC is in the + * register list. + * + * According to the ARM(R) manual, automatic updates of the PC + * are UNPREDICTABLE (ie implementation defined). + */ + if ((inst.lsm.L_bit == LS_LOAD) && (inst.lsm.Reg_List & (0x1 << REG_PC))) + { + unsigned char *regs_array = (unsigned char *)regs; + unsigned char *Rn_ptr = ®s_array[bsp_regbyte(inst.lsm.Rn)]; + unsigned long Rn_val = *((unsigned long *)(Rn_ptr)); + unsigned long offset_to_pc = 0; + int i; + unsigned long **dest = 0; + +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Decoded an load multiple instruction.\n"); + bsp_printf("inst.lsm.Reg_List = 0x%x\n", inst.lsm.Reg_List); + + bsp_printf("inst.lsm.Rn = 0x%x\n", inst.lsm.Rn); + bsp_printf("inst.lsm.L_bit = 0x%x\n", inst.lsm.L_bit); + bsp_printf("inst.lsm.W_bit = 0x%x\n", inst.lsm.W_bit); + bsp_printf("inst.lsm.S_bit = 0x%x\n", inst.lsm.S_bit); + bsp_printf("inst.lsm.U_bit = 0x%x\n", inst.lsm.U_bit); + bsp_printf("inst.lsm.P_bit = 0x%x\n", inst.lsm.P_bit); + bsp_printf("inst.lsm.rsv1 = 0x%x\n", inst.lsm.rsv1); + bsp_printf("inst.lsm.cond = 0x%x\n", inst.lsm.cond); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + + if (inst.lsm.U_bit == 0) + { + /* + * We are using a ascending stack. + * That means the PC is actually the register + * nearest to Rn currently. + */ + if (inst.lsm.P_bit == 1) + /* + * Using a pre-decrement. + */ + offset_to_pc = -bsp_regsize(REG_PC); + else + offset_to_pc = 0; + } else { + /* + * We are using an descending stack. + * That means the PC is actually the register + * farthest from Rn currently. + * + * Find the number of registers stored before the PC + */ + for (i = 0; i < REG_PC; i++) + { + if ((inst.lsm.Reg_List & (0x1 << i)) != 0) + { + /* + * Bit #i is set. Increment our count. + */ + offset_to_pc += bsp_regsize(i); + } + } + + /* + * Adjust the offset if we do a decrement/increment __BEFORE__ + * the write. + */ + if (inst.lsm.P_bit == 1) + offset_to_pc += bsp_regsize(REG_PC); + } + + /* + * Now let's calculate the real address of the stored PC + * making sure to mask out the two LO bits. + */ + dest = (unsigned long **)((Rn_val + offset_to_pc) & ~0x3); + +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Rn_val = 0x%08lx\n", Rn_val); + bsp_printf("offset_to_pc = 0x%08lx\n", offset_to_pc); + bsp_printf("dest = 0x%08lx\n", dest); + bsp_printf("*dest = 0x%08lx\n", *dest); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + + insert_ss_break(*dest); + } +} + + +/* + * Decode all coprocessor data processing instructions + */ +static void decode_cpdp_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * Can't possibly predict what this instruction will do. + * Don't do anything here. Just return. + */ +} + + +/* + * Decode all coprocessor register transfer instructions + */ +static void decode_cprt_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * Can't possibly predict what this instruction will do. + * Don't do anything here. Just return. + */ +} + + +/* + * Decode all coprocessor load/store instructions + */ +static void decode_cpls_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * Can't possibly predict what this instruction will do. + * Don't do anything here. Just return. + */ +} + + +/* + * Decode all branch/branch w/ link instructions + */ +static void decode_bbl_inst(ex_regs_t *regs, union arm_insn inst) +{ + unsigned long disp = inst.bbl.offset; + + /* + * Sign extend the 24 bit value + */ + if (disp & 0x00800000) + disp |= 0xff000000; + + /* + * Convert to long words + */ + disp <<= 2; + + /* + * Note: when the processor actually executes this instruction, the pc + * will point to the address of the current instruction + 8 because + * of the fetch/decode/execute cycle + */ + disp += 8; + + insert_ss_break((unsigned long *)(regs->_pc + disp)); +} + + +/* + * Decode all swi instructions + */ +static void decode_swi_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * Can't possibly predict where we should set the breakpoint for this. + * Don't do anything here. Just return. + */ +} + + +/* + * Decode all undefined instructions + */ +static void decode_undef_inst(ex_regs_t *regs, union arm_insn inst) +{ + /* + * Can't possibly predict what this instruction will do. + * Don't do anything here. Just return. + */ +} + + +/* + * Set breakpoint instructions for single stepping. + */ +void +bsp_singlestep_setup(void *registers) +{ + ex_regs_t *regs = (ex_regs_t *)registers; + union arm_insn inst; + + if (bsp_memory_read((void*)(regs->_pc), 0, ARM_INST_SIZE * 8, 1, &(inst.word)) == 0) + { + /* + * Unable to read the instruction at the current address. + * Let's not do anything with this. We can't set breakpoints + * so let's get out now. + */ + return; + } + + /* + * Handle the simple case -- linear code + */ + insert_ss_break((unsigned long *)(regs->_pc + ARM_INST_SIZE)); + + /* + * Now, we need to decode the instructions and figure out what + * they would do. + */ + if ((inst.mrs.rsv1 == MRS_RSV1_VALUE) && + (inst.mrs.rsv2 == MRS_RSV2_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("MRS type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_mrs_inst(regs, inst); + } else if ((inst.misr.rsv1 == MISR_RSV1_VALUE) && + (inst.misr.rsv2 == MISR_RSV2_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("MISR type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_misr_inst(regs, inst); + } else if ((inst.mrsr.rsv1 == MRSR_RSV1_VALUE) && + (inst.mrsr.rsv2 == MRSR_RSV2_VALUE) && + (inst.mrsr.rsv3 == MRSR_RSV3_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("MRSR type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_mrsr_inst(regs, inst); + } else if (inst.dpi.rsv1 == DPI_RSV1_VALUE) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("DPI type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_dpi_inst(regs, inst); + } else if ((inst.bx.rsv1 == BX_RSV1_VALUE) && + (inst.bx.rsv2 == BX_RSV2_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("BX type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_bx_inst(regs, inst); + } else if ((inst.dpis.rsv1 == DPIS_RSV1_VALUE) && + (inst.dpis.rsv2 == DPIS_RSV2_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("DPIS type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_dpis_inst(regs, inst); + } else if ((inst.dprs.rsv1 == DPRS_RSV1_VALUE) && + (inst.dprs.rsv2 == DPRS_RSV2_VALUE) && + (inst.dprs.rsv3 == DPRS_RSV3_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("DPRS type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_dprs_inst(regs, inst); + } else if ((inst.m.rsv1 == M_RSV1_VALUE) && + (inst.m.rsv2 == M_RSV2_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("M type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_m_inst(regs, inst); + } else if ((inst.ml.rsv1 == ML_RSV1_VALUE) && + (inst.ml.rsv2 == ML_RSV2_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("ML type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_ml_inst(regs, inst); + } else if (inst.lsio.rsv1 == LSIO_RSV1_VALUE) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("LSIO type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_lsio_inst(regs, inst); + } else if ((inst.lsro.rsv1 == LSRO_RSV1_VALUE) && + (inst.lsro.rsv2 == LSRO_RSV2_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("LSRO type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_lsro_inst(regs, inst); + } else if ((inst.lshwi.rsv1 == LSHWI_RSV1_VALUE) && + (inst.lshwi.rsv2 == LSHWI_RSV2_VALUE) && + (inst.lshwi.rsv3 == LSHWI_RSV3_VALUE) && + (inst.lshwi.rsv4 == LSHWI_RSV4_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("LSHWI type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_lshwi_inst(regs, inst); + } else if ((inst.lshwr.rsv1 == LSHWR_RSV1_VALUE) && + (inst.lshwr.rsv2 == LSHWR_RSV2_VALUE) && + (inst.lshwr.rsv3 == LSHWR_RSV3_VALUE) && + (inst.lshwr.rsv4 == LSHWR_RSV4_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("LSHWR type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_lshwr_inst(regs, inst); + } else if ((inst.swap.rsv1 == SWAP_RSV1_VALUE) && + (inst.swap.rsv2 == SWAP_RSV2_VALUE) && + (inst.swap.rsv3 == SWAP_RSV3_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("SWAP type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_swap_inst(regs, inst); + } else if (inst.lsm.rsv1 == LSM_RSV1_VALUE) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("LSM type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_lsm_inst(regs, inst); + } else if ((inst.cpdp.rsv1 == CPDP_RSV1_VALUE) && + (inst.cpdp.rsv2 == CPDP_RSV2_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("CPDP type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_cpdp_inst(regs, inst); + } else if ((inst.cprt.rsv1 == CPRT_RSV1_VALUE) && + (inst.cprt.rsv2 == CPRT_RSV2_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("CPRT type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_cprt_inst(regs, inst); + } else if (inst.cpls.rsv1 == CPLS_RSV1_VALUE) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("CPLS type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_cpls_inst(regs, inst); + } else if (inst.bbl.rsv1 == BBL_RSV1_VALUE) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("BBL type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_bbl_inst(regs, inst); + } else if (inst.swi.rsv1 == SWI_RSV1_VALUE) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("SWI type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_swi_inst(regs, inst); + } else if ((inst.undef.rsv1 == UNDEF_RSV1_VALUE) && + (inst.undef.rsv2 == UNDEF_RSV2_VALUE)) { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("UNDEF type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + decode_undef_inst(regs, inst); + } else { +#if DEBUG_SINGLESTEP_VERBOSE + bsp_printf("Unknown instruction type: 0x%08lx\n", inst.word); +#endif /* DEBUG_SINGLESTEP_VERBOSE */ + } +} + +void +bsp_skip_instruction(void *registers) +{ + ex_regs_t *regs = (ex_regs_t *)registers; + regs->_pc += ARM_INST_SIZE; +} diff --git a/packages/cygmon/v2_0/misc/bsp/bsp.h b/packages/cygmon/v2_0/misc/bsp/bsp.h new file mode 100644 index 00000000..ce52e74c --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/bsp.h @@ -0,0 +1,445 @@ +#ifndef __BSP_BSP_H__ +#define __BSP_BSP_H__ +//========================================================================== +// +// bsp.h +// +// Public interface to Red Hat BSP. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Public interface to Red Hat BSP. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#ifndef __ASSEMBLER__ + +/* needed for _bsp_vsprintf() */ +#include + +/* + * Exception and interrupt handler type. + */ +#ifndef _BSP_HANDLER_T_DEFINED +#define _BSP_HANDLER_T_DEFINED +typedef int (*bsp_handler_t)(int __irq_nr, void *__regs); +#endif // _BSP_HANDLER_T_DEFINED + +/* + * Vector descriptor. This is needed for chaining vectors. The interfaces use + * bsp_vec structure pointers instead of direct pointers to handlers. This + * puts the responsibility for allocating the bsp_vec structures on the + * caller, rather than the BSP code. + */ +typedef struct bsp_vec { + bsp_handler_t handler; /* pointer to actual ISR */ + struct bsp_vec *next; /* for chaining */ +} bsp_vec_t; + +/* + * Valid op values for vector install routines. + */ +#define BSP_VEC_REPLACE 0 +#define BSP_VEC_CHAIN_FIRST 1 +#define BSP_VEC_CHAIN_LAST 2 + +/* + * Valid kinds of vectors supported by vector install and remove + * routines. + */ +#define BSP_VEC_EXCEPTION 0 +#define BSP_VEC_INTERRUPT 1 + +/* + * Routine to cause a breakpoint exception. + */ +extern void bsp_breakpoint(void); + +/* + * Dummy function whose address is the address of + * the breakpoint caused by calling bsp_breakpoint(). + */ +extern void bsp_breakinsn(void); + +/* + * Enable given irq. + */ +extern void bsp_enable_irq(int __irq_nr); + +/* + * Disable given irq. Returns true if irq was enabled. + */ +extern int bsp_disable_irq(int __irq_nr); + +/* + * Remove given vector from vector chain. + */ +extern void bsp_remove_vec(int __vec_kind, + int __vec_nr, + bsp_vec_t *__vec); + +/* + * Install a vector chain. + * + * vec_kind may be BSP_VEC_EXCEPTION or BSP_VEC_INTERRUPT. + * vec_nr is the exception or interrupt number. + * op may be one of: + * BSP_VEC_REPLACE - replace existing chain. + * BSP_VEC_CHAIN_FIRST - install at head of chain. + * BSP_VEC_CHAIN_LAST - install at tail of chain. + * + */ +extern bsp_vec_t *bsp_install_vec(int __vec_kind, + int __vec_nr, + int __op, + bsp_vec_t *__vec); + +/* + * Install a debug handler. + * Returns old handler being replaced. + */ +extern bsp_handler_t bsp_install_dbg_handler(bsp_handler_t __new_handler); + +/* + * Sometimes it is desireable to call the debug handler directly. This routine + * accomplishes that. It is the responsibility of the caller to insure that + * interrupts are disabled before calling this routine. + */ +extern void bsp_invoke_dbg_handler(int __exc_nr, void *__regs); + +/* + * Install a 'kill' handler. This handler is called when debugger + * issues a kill command. + * Returns old handler being replaced. + */ +extern bsp_handler_t bsp_install_kill_handler(bsp_handler_t __new_handler); + +/* + * Architecure specific routine to prepare CPU to execute + * a single machine instruction. + */ +#ifndef USE_ECOS_HAL_SINGLESTEP +extern void bsp_singlestep_setup(void *__saved_regs); +#endif /* USE_ECOS_HAL_SINGLESTEP */ + +/* + * Architecure specific routine to cleanup after a single-step + * completes. + */ +#ifndef USE_ECOS_HAL_SINGLESTEP +extern void bsp_singlestep_cleanup(void *__saved_regs); +#endif /* USE_ECOS_HAL_SINGLESTEP */ + +/* + * Architecture specific routine to skip past the current machine instruction. + */ +#ifndef USE_ECOS_HAL_SINGLESTEP +extern void bsp_skip_instruction(void *__saved_regs); +#endif /* USE_ECOS_HAL_SINGLESTEP */ + +/* + * Return byte offset within the saved register area of the + * given register. + */ +extern int bsp_regbyte(int __regno); + +/* + * Return size in bytes of given register. + */ +extern int bsp_regsize(int __regno); + +/* + * Setup the saved registered to establish the given Program Counter. + */ +#ifndef bsp_set_pc +extern void bsp_set_pc(unsigned long __pc, void *__saved_regs); +#endif + +/* + * Get the current Program Counter from the saved registers. + */ +#ifndef bsp_get_pc +unsigned long bsp_get_pc(void *__saved_regs); +#endif + +extern int bsp_memory_read(void *__addr, /* start addr of memory to read */ + int __asid, /* address space id */ + int __rsize, /* size of individual read ops */ + int __nreads, /* number of read operations */ + void *__buf); /* result buffer */ + +extern int bsp_memory_write(void *__addr, /* start addr of memory to write */ + int __asid, /* address space id */ + int __wsize, /* size of individual write ops */ + int __nwrites, /* number of write operations */ + void *__buf); /* source buffer for write data */ + +/* + * Architecture specific routines to read and write CPU registers. + */ +extern void bsp_set_register(int __regno, void *__saved_regs, void *__val); +extern void bsp_get_register(int __regno, void *__saved_regs, void *__val); + + +/* + * Architecture specific conversion of raw exception info into + * a signal value. + */ +#ifndef bsp_get_signal +extern int bsp_get_signal(int __exc_nr, void *__saved_regs); +#endif + +/* light-weight bsp printf to console port */ +extern void bsp_printf(const char *__fmt, ...); + +/* light-weight bsp printf to debug port */ +extern void bsp_dprintf(const char *__fmt, ...); + +/* bsp vsprintf */ +extern int bsp_vsprintf(char *__str, const char *__fmt, va_list __ap); + +/* bsp vprintf to console port */ +extern void bsp_vprintf(const char *__fmt, va_list __ap); + +/* bsp vprintf to debug port */ +extern void bsp_dvprintf(const char *__fmt, va_list __ap); + +/* bsp sprintf */ +extern void bsp_sprintf(char *str, const char *fmt, ...); + +#ifdef NDEBUG +#define BSP_ASSERT(e) ((void)0) +#else /* NDEBUG */ +extern void _bsp_assert(const char *, const int, const char *); +#define BSP_ASSERT(e) ((e) ? (void)0 : _bsp_assert(__FILE__, __LINE__, #e)) +#endif /* NDEBUG */ + +/* + * Functions for low-level console and debug i/o. + */ +extern void bsp_console_write(const char *__p, int __len); +extern void bsp_console_putc(char __ch); +extern int bsp_console_read(char *__p, int __len); +extern int bsp_console_getc(void); +extern void bsp_console_ungetc(char ch); +extern void bsp_debug_write(const char *__p, int __len); +extern int bsp_debug_read(char *__p, int __len); +extern void bsp_debug_putc(char __ch); +extern int bsp_debug_getc(void); +extern void bsp_debug_ungetc(char ch); + +/* + * Disable interrupts for debug comm channel. + * Returns true if interrupts were previously enabled, + * false if interrupts were already disabled. + */ +extern int bsp_debug_irq_disable(void); +extern void bsp_debug_irq_enable(void); + +/* + * Cache control functions. May be noops for architectures not + * supporting caches. + * + * The icache flush simply invalidates _at_least_ the range of + * addresses specified. + * + * The dcache flush writes back (if write-back cache) and invalidates + * _at_least_ the range of addresses specified. + * + */ +extern void bsp_flush_dcache(void *__p, int __nbytes); +extern void bsp_flush_icache(void *__p, int __nbytes); + +/* + * Reset function. May be noops for architectures not + * supporting software reset. + */ +extern void bsp_reset(void); + +/* + * Generic data (board and CPU specific) handling + */ +extern void *bsp_cpu_data(void); +extern void *bsp_board_data(void); + +/* + * List of board characteristics which can be read queried by BSP clients. These + * information IDs are passed to: + * + * int bsp_sysinfo(enum bsp_info_id id, ...); + * + * Some pieces of information may have more than one instance. For example, the + * BSP will likely have information on multiple memory regions. In those cases, + * a particular instance may be accessed using a small integer index argument. + * + * The following comments indicate what additional arguments are needed + * to access the specific information. + */ +enum bsp_info_id { + /* + * CPU and board names. + * + * err = bsp_sysinfo(BSP_INFO_PLATFORM, + * struct bsp_platform_info *result) + * + * err => zero if successful, -1 if unsupported. + */ + BSP_INFO_PLATFORM, + + /* + * Data, instruction, and secondary caches. + * + * err = bsp_sysinfo(BSP_INFO_[DIS]CACHE, + * struct bsp_cache_info *result) + * + * err => zero if successful, -1 if unsupported. + * + */ + BSP_INFO_DCACHE, + BSP_INFO_ICACHE, + BSP_INFO_SCACHE, + + /* + * Memory region info. + * + * err = bsp_sysinfo(BSP_INFO_MEMORY, + * int index, + * struct bsp_mem_info *result) + * + * err => zero if successful, -1 if invalid index. + * + * Caller should start index at zero, then increment index for subsequent + * calls until error return indicates no more memory regions. + */ + BSP_INFO_MEMORY, + + /* + * Communication channel info. + * + * err = bsp_sysinfo(BSP_INFO_COMM, + * int index, + * struct bsp_comm_info *result) + * + * err => zero if successful, -1 if invalid index. + * + * Caller should start index at zero, then increment index for subsequent + * calls until error return indicates no more comm channels. + */ + BSP_INFO_COMM +}; + + +/* + * Platform info. + */ +struct bsp_platform_info { + const char *cpu; /* CPU name*/ + const char *board; /* board name */ + const char *extra; /* extra info */ +}; + + +/* + * Cache size info. + */ +struct bsp_cachesize_info { + int size; /* total size in bytes */ + short linesize; /* width of cacheline in bytes */ + short ways; /* number of ways per line */ +}; + + +/* + * Memory region info. + * The BSP may describe multiple memory regions. For example, + * DRAM may be comprised of several non-contiguous regions. + * ROM and FLASH regions may also be described. + * + */ +struct bsp_mem_info { + void *phys_start; /* physical start address */ + void *virt_start; /* virtual start address */ + int virt_asid; /* some architectures also use an address space id */ + long nbytes; /* length of region in bytes */ + int kind; /* kind of memory */ +#define BSP_MEM_RAM 1 +#define BSP_MEM_FLASH 2 +#define BSP_MEM_ROM 3 +}; + + +struct bsp_comm_info { + char *name; + short kind; +#define BSP_COMM_SERIAL 1 +#define BSP_COMM_ENET 2 + short protocol; +#define BSP_PROTO_NONE 0 +#define BSP_PROTO_UDP 1 +#define BSP_PROTO_TCP 2 +}; + + +extern int bsp_sysinfo(enum bsp_info_id __id, ...); + +/* + * Set or get active debug and console channels. + * Returns -1 if unsucessful. + * If the passed in __comm_id is -1, then the id of the current channel + * is returned. + */ +extern int bsp_set_debug_comm(int __comm_id); +extern int bsp_set_console_comm(int __comm_id); + +/* + * Set or get the current baud rate of a serial comm channel. + * Returns -1 on if unsuccessful. + * If the given baud is -1, then the current baudrate is returned. + */ +extern int bsp_set_serial_baud(int __comm_id, int baud); + +#endif + +#endif // __BSP_BSP_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/common/breakpoint.c b/packages/cygmon/v2_0/misc/bsp/common/breakpoint.c new file mode 100644 index 00000000..d893ce0b --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/breakpoint.c @@ -0,0 +1,97 @@ +//========================================================================== +// +// breakpoint.c +// +// Breakpoint generation. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Breakpoint generation. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include +#include + +#ifndef DEBUG_BREAKPOINT +#define DEBUG_BREAKPOINT 0 +#endif + +#ifdef __ECOS__ +#include +#endif /* __ECOS__ */ + +/* + * Trigger a breakpoint exception. + */ +void +bsp_breakpoint(void) +{ +#if DEBUG_BREAKPOINT + bsp_printf("Before BP\n"); +#endif + +#ifdef __ECOS__ +# ifdef __NEED_UNDERSCORE__ + HAL_BREAKPOINT(_bsp_breakinsn); +# else + HAL_BREAKPOINT(bsp_breakinsn); +# endif +#else +# ifdef __NEED_UNDERSCORE__ + asm volatile (".globl _bsp_breakinsn\n" + "_bsp_breakinsn:\n"); +# else + asm volatile (".globl bsp_breakinsn\n" + "bsp_breakinsn:\n"); +# endif + BREAKPOINT(); +#endif + +#if DEBUG_BREAKPOINT + bsp_printf("After BP\n"); +#endif +} + diff --git a/packages/cygmon/v2_0/misc/bsp/common/bsp.c b/packages/cygmon/v2_0/misc/bsp/common/bsp.c new file mode 100644 index 00000000..6b77289b --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/bsp.c @@ -0,0 +1,341 @@ +//========================================================================== +// +// bsp.c +// +// General BSP support. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: General BSP support. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include +#include +#include +#include "bsp_if.h" +#include "gdb.h" + +#ifndef DEBUG_BSP_INIT +#define DEBUG_BSP_INIT 0 +#endif + +struct bsp_comm_channel *_bsp_net_channel = NULL; + +/* + * This is the array of pointers to interrupt controller descriptors. + */ +static struct bsp_irq_controller *_bsp_ictrl_table[BSP_MAX_IRQ_CONTROLLERS]; + +/* + * This is the array of second-level exception vectors. + */ +static bsp_vec_t *_bsp_exc_table[BSP_MAX_EXCEPTIONS]; + + +/* + * Debug (default exception) handler vector. + */ +bsp_handler_t _bsp_dbg_vector; + + +static bsp_shared_t __bsp_shared = { + BSP_SHARED_DATA_VERSION, /* version */ + (const struct bsp_irq_controller **)&_bsp_ictrl_table[0], /* __ictrl_table */ + &_bsp_exc_table[0], /* __exc_table */ + &_bsp_dbg_vector, /* __dbg_vector */ + (bsp_handler_t)0, /* __kill_vector */ + (struct bsp_comm_procs *)NULL, /* __console_procs */ + (struct bsp_comm_procs *)NULL, /* __debug_procs */ + (void (*)(void *, int ))NULL, /* __flush_dcache */ + (void (*)(void *, int ))NULL, /* __flush_icache */ + (void (*)(void ))NULL, /* __reset */ + (void*)NULL, /* __cpu_data */ + (void*)NULL /* __board_data */ +}; + + +static void +default_cache_proc(void *p, int nbytes) +{ + /* do nothing */ +} + + +static void +default_reset_proc(void) +{ + /* do nothing */ +} + + +static int +find_comm_id(struct bsp_comm_procs *procs) +{ + int i; + + for (i = 0; i < _bsp_num_comms; i++) + if (&_bsp_comm_list[i].procs == procs) + return i; + + if (procs == &_bsp_net_channel->procs) + return _bsp_num_comms; + + return -1; +} + + +/* + * Set or get active debug channel. + * Returns -1 if unsucessful. + * If the passed in comm id is -1, then the id of the current channel + * is returned. + */ +static int +set_debug_comm(int id) +{ + struct bsp_comm_channel *chan; + struct bsp_comm_procs *procs; + int current_chan = find_comm_id(bsp_shared_data->__debug_procs); + + if (id < 0) + return current_chan; + + if (id > _bsp_num_comms) + return -1; + + if (id == _bsp_num_comms && _bsp_net_channel == NULL) + return -1; + + if (id == current_chan) + return 0; + + /* Remove existing channel */ + if ((procs = bsp_shared_data->__debug_procs) != NULL) + (*procs->__control)(procs->ch_data, COMMCTL_REMOVE_DBG_ISR); + + /* Install new channel */ + if (id == _bsp_num_comms) + chan = _bsp_net_channel; + else + chan = &_bsp_comm_list[id]; + bsp_shared_data->__debug_procs = &chan->procs; + (*chan->procs.__control)(chan->procs.ch_data, COMMCTL_INSTALL_DBG_ISR); + + return 0; +} + + +/* + * Set or get active console channel. + * Returns -1 if unsucessful. + * If the passed in comm id is -1, then the id of the current channel + * is returned. + */ +static int +set_console_comm(int id) +{ + int current_chan = find_comm_id(bsp_shared_data->__console_procs); + + if (id < 0) + return current_chan; + + if (id > _bsp_num_comms) + return -1; + + if (id == _bsp_num_comms && _bsp_net_channel == NULL) + return -1; + + if (id == current_chan) + return 0; + + /* + * Install new channel. If its the same as the debug channel, + * just clear the __console_procs and the bsp_console_* + * interface functions will take care of the rest. + */ + if (id == _bsp_num_comms) + bsp_shared_data->__console_procs = &_bsp_net_channel->procs; + else + bsp_shared_data->__console_procs = &_bsp_comm_list[id].procs; + + if (bsp_shared_data->__console_procs == bsp_shared_data->__debug_procs) + bsp_shared_data->__console_procs = NULL; + + return 0; +} + + +/* + * Set or get the current baud rate of a serial comm channel. + * Returns -1 on if unsuccessful. + * If the given baud is -1, then the current baudrate is returned. + */ +int +set_serial_baud(int id, int baud) +{ + struct bsp_comm_channel *chan; + + if (id < 0 || id >= _bsp_num_comms) + return -1; + + chan = &_bsp_comm_list[id]; + + if (chan->info.kind != BSP_COMM_SERIAL) + return -1; + + if (baud == -1) + return (*chan->procs.__control)(chan->procs.ch_data, + COMMCTL_GETBAUD); + + return (*chan->procs.__control)(chan->procs.ch_data, + COMMCTL_SETBAUD, baud); +} + +/* + * Final initialization before calling main. + */ +void +_bsp_init(void) +{ + struct bsp_comm_procs *com; + extern void __init_irq_controllers(void); + + bsp_shared_data = &__bsp_shared; + _bsp_dbg_vector = (bsp_handler_t)_bsp_gdb_handler; + bsp_shared_data->__dbg_data = &_bsp_gdb_data; + + bsp_shared_data->__flush_dcache = default_cache_proc; + bsp_shared_data->__flush_icache = default_cache_proc; + + bsp_shared_data->__reset = default_reset_proc; + + /* + * General BSP information access. + */ + bsp_shared_data->__sysinfo = _bsp_sysinfo; + + /* + * Setup comm port handlers. + */ + bsp_shared_data->__set_debug_comm = set_debug_comm; + bsp_shared_data->__set_console_comm = set_console_comm; + bsp_shared_data->__set_serial_baud = set_serial_baud; + + /* + * Very first thing is to initialize comm channels so + * we can have debug printfs working. None of this + * must rely on interrupts until interrupt controllers + * are initialized below. + */ + _bsp_init_board_comm(); + + /* + * Assume first comm channel is the default. + */ + bsp_shared_data->__debug_procs = &_bsp_comm_list[0].procs; + + /* + * By default, console i/o goes through the debug channel. + * We indicate this by making the console i/o procs + * pointer NULL. + */ + bsp_shared_data->__console_procs = NULL; + + /* + * Install interrupt controllers. + */ +#if DEBUG_BSP_INIT + bsp_printf("Installing interrupt controllers...\n"); +#endif + + _bsp_install_cpu_irq_controllers(); + _bsp_install_board_irq_controllers(); + +#if DEBUG_BSP_INIT + bsp_printf("Done installing interrupt controllers.\n"); + bsp_printf("Initializing interrupt controllers...\n"); +#endif + /* + * Actually run the init routines for all installed + * interrupt controllers. + */ + __init_irq_controllers(); + +#if DEBUG_BSP_INIT + bsp_printf("Done initializing interrupt controllers.\n"); + bsp_printf("CPU-specific initialization...\n"); +#endif + + /* + * Final architecture specific initialization. + */ + _bsp_cpu_init(); + +#if DEBUG_BSP_INIT + bsp_printf("Done w/ CPU-specific initialization.\n"); + bsp_printf("Board specific initialization...\n"); +#endif + /* + * Final board specific initialization. + */ + _bsp_board_init(); + +#if DEBUG_BSP_INIT + bsp_printf("Done w/ board specific initialization.\n"); +#endif + + /* + * Now we can install the debug interrupt handler on the debug channel. + */ + com = bsp_shared_data->__debug_procs; + (*com->__control)(com->ch_data, COMMCTL_INSTALL_DBG_ISR); + + + if (_bsp_net_channel != NULL) { + set_debug_comm(_bsp_num_comms); + set_console_comm(0); + } +} diff --git a/packages/cygmon/v2_0/misc/bsp/common/bsp_cache.c b/packages/cygmon/v2_0/misc/bsp/common/bsp_cache.c new file mode 100644 index 00000000..c9a59077 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/bsp_cache.c @@ -0,0 +1,70 @@ +//========================================================================== +// +// bsp_cache.c +// +// BSP Cache Interfaces. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: BSP Cache Interfaces. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include "bsp_if.h" + +void +bsp_flush_dcache(void *p, int nbytes) +{ + bsp_shared_data->__flush_dcache(p, nbytes); +} + + +void +bsp_flush_icache(void *p, int nbytes) +{ + bsp_shared_data->__flush_icache(p, nbytes); +} + + diff --git a/packages/cygmon/v2_0/misc/bsp/common/bsp_if.c b/packages/cygmon/v2_0/misc/bsp/common/bsp_if.c new file mode 100644 index 00000000..9b13c824 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/bsp_if.c @@ -0,0 +1,160 @@ +//========================================================================== +// +// bsp_if.c +// +// Miscellaneous BSP Interfaces. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Miscellaneous BSP Interfaces. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include +#include "bsp_if.h" + +/* + * Install a debug handler. + * Returns old handler being replaced. + */ +bsp_handler_t +bsp_install_dbg_handler(bsp_handler_t new_handler) +{ + bsp_handler_t old_handler; + + old_handler = *bsp_shared_data->__dbg_vector; + *bsp_shared_data->__dbg_vector = new_handler; + + return old_handler; +} + +/* + * Sometimes it is desireable to call the debug handler directly. This routine + * accomplishes that. It is the responsibility of the caller to insure that + * interrupts are disabled before calling this routine. + */ +void +bsp_invoke_dbg_handler(int exc_nr, void *regs) +{ + (*bsp_shared_data->__dbg_vector)(exc_nr, regs); +} + +/* + * Install a 'kill' handler. + * Returns old handler being replaced. + */ +bsp_handler_t +bsp_install_kill_handler(bsp_handler_t new_handler) +{ + bsp_handler_t old_handler; + + old_handler = bsp_shared_data->__kill_vector; + bsp_shared_data->__kill_vector = new_handler; + + return old_handler; +} + + +void * +bsp_cpu_data(void) +{ + return bsp_shared_data->__cpu_data; +} + + +void * +bsp_board_data(void) +{ + return bsp_shared_data->__board_data; +} + + +int +bsp_sysinfo(enum bsp_info_id id, ...) +{ + int retval; + va_list ap; + + va_start (ap, id); + retval = bsp_shared_data->__sysinfo(id, ap); + va_end(ap); + return retval; +} + +int +bsp_set_debug_comm(int id) +{ + return bsp_shared_data->__set_debug_comm(id); +} + +int +bsp_set_console_comm(int id) +{ + return bsp_shared_data->__set_console_comm(id); +} + +int +bsp_set_serial_baud(int id, int baud) +{ + return bsp_shared_data->__set_serial_baud(id, baud); +} + + +#if !defined(NDEBUG) + +void _bsp_assert(const char *file, const int line, const char *condition) +{ + bsp_printf("Assertion \"%s\" failed\n", condition); + bsp_printf("File \"%s\"\n", file); + bsp_printf("Line %d\n", line); +#if defined(PORT_TOGGLE_DEBUG) + PORT_TOGGLE_DEBUG(); +#else + while(1) ; +#endif /* defined(PORT_TOGGLE_DEBUG) */ +} + +#endif /* !defined(NDEBUG) */ + diff --git a/packages/cygmon/v2_0/misc/bsp/common/bsp_if.h b/packages/cygmon/v2_0/misc/bsp/common/bsp_if.h new file mode 100644 index 00000000..268b1965 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/bsp_if.h @@ -0,0 +1,433 @@ +#ifndef __BSP_COMMON_BSP_IF_H__ +#define __BSP_COMMON_BSP_IF_H__ +//========================================================================== +// +// bsp_if.h +// +// BSP interface definitions. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: BSP interface definitions. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include + +/* + * Maximum number of interrupt controllers supported by + * this bsp. + */ +#define BSP_MAX_IRQ_CONTROLLERS 8 + +#ifndef __ASSEMBLER__ + + +/* + * Interrupt controller abstraction. + * Each interrupt controller on a given board should be described using + * this data structure. + */ +struct bsp_irq_controller { + /* + * First and last irqs handled by this controller. + */ + short first; + short last; + + /* + * pointer to array of bsp_vec struct pointers. These are + * the heads of the linked list of ISRs for each irq handled + * by this controller. + */ + bsp_vec_t **vec_list; + + /* + * Pointer to initialization routine which is run once at boot time. + */ + void (*init)(const struct bsp_irq_controller *__ic); + + /* + * Pointer to routines used to disable and enable interrupts handled + * by this controller. + */ + int (*disable)(const struct bsp_irq_controller *__ic, + int __irq_nr); + void (*enable)(const struct bsp_irq_controller *__ic, + int __irq_nr); +}; + + +/* + * Board specific code needs to provide at least one communication channel + * for use as the debug and console (stdio) channel. For each channel, + * there must be a set of function vectors for the common BSP code to + * control the channel. + */ +struct bsp_comm_procs { + /* + * Implementation dependent data pointer passed to the following procs. + */ + void *ch_data; + + /* + * Write a buffer of the given length. All of buffer is sent before + * the write call returns. + */ + void (*__write)(void *ch_data, const char *buf, int len); + + /* + * Fill a buffer with up to the given length. Returns the actual number + * of characters read. + */ + int (*__read)(void *ch_data, char *buf, int len); + + /* + * Send a single character. + */ + void (*__putc)(void *ch_data, char ch); + + /* + * Read a single character. If no character is immediately available, will + * block until one becomes available. + */ + int (*__getc)(void *ch_data); + + /* + * Catchall comm port control. + */ + int (*__control)(void *ch_data, int func, ...); + + /* + * For serial ports, the control function may be used to set and get the + * current baud rate. Usage: + * + * err = (*__control)(COMMCTL_SETBAUD, int bits_per_second); + * err => Zero if successful, -1 if error. + * + * baud = (*__control)(COMMCTL_GETBAUD); + * baud => -1 if error, current baud otherwise. + */ +#define COMMCTL_SETBAUD 0 +#define COMMCTL_GETBAUD 1 + + /* + * Install and remove debugger interrupt handlers. These are the receiver + * interrupt routines which are used to change control from a running + * program to the debugger stub. + */ +#define COMMCTL_INSTALL_DBG_ISR 2 +#define COMMCTL_REMOVE_DBG_ISR 3 + + /* + * Disable comm port interrupt. Returns TRUE if interrupt was enabled, + * FALSE otherwise. + */ +#define COMMCTL_IRQ_DISABLE 4 + /* + * Enable comm port interrupt. + */ +#define COMMCTL_IRQ_ENABLE 5 +}; + + +/* + * The board specific code uses this data structure to provide information + * about and procedure vectors for each supported communication channel. + * See _bsp_comm_list below. + */ +struct bsp_comm_channel { + struct bsp_comm_info info; + struct bsp_comm_procs procs; +}; + + +/* + * Number to place in the version field. If structure is changed + * in a way which is not backwards compatible, this number should + * be incremented. + */ +#define BSP_SHARED_DATA_VERSION 2 + +/* + * Clients of this BSP will need to have access to BSP functions and + * data structures. Because, the client and the BSP may not be linked + * together, a structure of vectors is used to gain this access. A + * pointer to this structure can be gotten via a syscall. This syscall + * is made automatically from within the crt0.o file. + */ +typedef struct { + int version; /* version number for future expansion */ + + /* + * Pointer to the array of pointers to interrupt controller descriptors. + */ + const struct bsp_irq_controller **__ictrl_table; + + /* + * Pointer to the array of exception vectors. + */ + bsp_vec_t **__exc_table; + + /* + * Pointer to debug handler vector. + */ + bsp_handler_t *__dbg_vector; + + /* + * User hook to catch debugger 'kill' command. + */ + bsp_handler_t __kill_vector; + + /* + * Vectored functions for console and debug i/o. + */ + struct bsp_comm_procs *__console_procs; + struct bsp_comm_procs *__debug_procs; + + /* + * Vectored cache control functions. + */ + void (*__flush_dcache)(void *__p, int __nbytes); + void (*__flush_icache)(void *__p, int __nbytes); + + /* + * Generic data pointers + */ + void *__cpu_data; + void *__board_data; + + /* + * General BSP information access. + * See bsp.h for details. + */ + int (*__sysinfo)(enum bsp_info_id __id, va_list __ap); + + /* + * Set or get active debug and console channels. + * Returns -1 if unsucessful. + * If the passed in __comm_id is -1, then the id of the current channel + * is returned. + */ + int (*__set_debug_comm)(int __comm_id); + int (*__set_console_comm)(int __comm_id); + + /* + * Set or get the current baud rate of a serial comm channel. + * Returns -1 on if unsuccessful. + * If the given baud is -1, then the current baudrate is returned. + */ + int (*__set_serial_baud)(int __comm_id, int baud); + + /* + * Debug agent data. + */ + void *__dbg_data; + + /* + * Reset function + * We want to avoid calling this with a trap since + * we may be calling it from SWI mode (in cygmon). + * That is problematic, as nested SWI's are not + * very good. + */ + void (*__reset)(void); + + /* + * TRUE if console interrupt detected during program output. + */ + int __console_interrupt_flag; + +} bsp_shared_t; + + +extern bsp_shared_t *bsp_shared_data; + +/* + * Platform info which may be overriden/modified by arch/board specific code. + */ +extern struct bsp_platform_info _bsp_platform_info; + +/* + * Cache info which may be overriden/modified by arch/board specific code. + */ +extern struct bsp_cachesize_info _bsp_dcache_info; +extern struct bsp_cachesize_info _bsp_icache_info; +extern struct bsp_cachesize_info _bsp_scache_info; + +/* + * Array of comm channel descriptors which must be provided by board specific + * code. + */ +extern struct bsp_comm_channel _bsp_comm_list[]; + +/* + * Number of comm channel descriptors which must be provided by board specific + * code. + */ +extern int _bsp_num_comms; + + +/* + * Array of memory region descriptors which must be provided by board specific + * code. + */ +extern struct bsp_mem_info _bsp_memory_list[]; + +/* + * Number of memory region descriptors which must be provided by board specific + * code. + */ +extern int _bsp_num_mem_regions; + +/* + * In order to construct the above _bsp_memory_list, some board specific + * code may have to size RAM regions. To do this easily and reliably, + * the code needs to run from ROM before .bss and .data sections are + * initialized. This leads to the problem of where to store the results + * of the memory sizing tests. In this case, the _bsp_init_stack routine + * which sizes memory and sets up the stack will place the board-specific + * information on the stack and return with the stack pointer pointing to + * a pointer to the information. That is, addr_of_info = *(void **)sp. + * The architecture specific code will then copy that pointer to the + * _bsp_ram_info_ptr variable after initializing the .data and .bss sections. + */ +extern void *_bsp_ram_info_ptr; + +/* + * Generic bsp initialization. Called by low level startup code + */ +extern void _bsp_init(void); + +/* + * Initialize board communication in polling mode. This enables + * debugging printf for later initializations. Interrupts for + * comm channels may be set up later in _bsp_board_init(). + */ +extern void _bsp_init_board_comm(void); + +/* + * Make generic BSP aware of CPU/MCU specific interrupt controllers. + */ +extern void _bsp_install_cpu_irq_controllers(void); + +/* + * Make generic BSP aware of board specific interrupt controllers. + */ +extern void _bsp_install_board_irq_controllers(void); + +/* + * Callback used by above two routines to install a single + * interrupt controller. + */ +extern void _bsp_install_irq_controller(const struct bsp_irq_controller *__ic); + +/* + * Generic exception dispatch routine. Usually called from asm-level + * exception handler to call vectors in vector chain for the given + * exception number. Stops traversing vector chain when a called + * vector returns a non-zero value. If no vector returns non-zero, + * a default error message and register dump is printed. + */ +extern int _bsp_exc_dispatch(int __exc_number, void *__regs); + + +/* + * Architecture specific routine to dump register values. + */ +extern void _bsp_dump_regs(void *__regs); + + +/* + * Generic syscall handler called by architecture specific handler. + * Returns non-zero if given 'func' number was handled by the generic + * code, zero otherwise. If handled, the syscall error is returned + * via the err_ptr. + */ +extern int _bsp_do_syscall(int __func, + long __arg1, long __arg2, long __arg3, long __arg4, + int *__err_ptr); + + +extern void _bsp_cpu_init(void); +extern void _bsp_board_init(void); + + +/* + * General interface for getting certain BSP parameters. + * See bsp.h for details. + */ +extern int _bsp_sysinfo(enum bsp_info_id __id, va_list __ap); + +/* + * Called from comm channel when a connection to host is closed. + */ +extern void _bsp_dbg_connect_abort(void); + + +/* + * Pointer to a network channel. NULL if no network channel + * exists. + */ +extern struct bsp_comm_channel *_bsp_net_channel; + + +/* + * Formatted output primitive. + */ +extern void __vprintf(void (*putc_func)(char c), const char *fmt0, va_list ap); + + + +#endif /* !__ASSEMBLER__ */ + +/* + * SYSCALL number to use to get pointer to above bsp_shared_t structure. + */ +#define BSP_GET_SHARED 0xbaad + +#endif // __BSP_COMMON_BSP_IF_H__ + + diff --git a/packages/cygmon/v2_0/misc/bsp/common/console-io.c b/packages/cygmon/v2_0/misc/bsp/common/console-io.c new file mode 100644 index 00000000..ad0450a3 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/console-io.c @@ -0,0 +1,140 @@ +//========================================================================== +// +// console-io.c +// +// BSP Console Channel Interfaces. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: BSP Console Channel Interfaces. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include +#include +#include "bsp_if.h" + +static unsigned char __console_ungetc; + +void +bsp_console_write(const char *p, int len) +{ + struct bsp_comm_procs *com; + + if ((com = bsp_shared_data->__console_procs) != NULL) + com->__write(com->ch_data, p, len); + else + bsp_debug_write(p, len); +} + + +int +bsp_console_read(char *p, int len) +{ + struct bsp_comm_procs *com; + + if (len <= 0) + return 0; + + if ((com = bsp_shared_data->__console_procs) != NULL) { + if (__console_ungetc) { + *p = __console_ungetc; + __console_ungetc = 0; + return 1; + } + return com->__read(com->ch_data, p, len); + } else + return bsp_debug_read(p, len); +} + +/*#define PRINTABLE_ONLY*/ +#ifdef PRINTABLE_ONLY +#include +#endif /* PRINTABLE_ONLY */ + +void +bsp_console_putc(char ch) +{ + struct bsp_comm_procs *com; + +#ifdef PRINTABLE_ONLY + if ((!isprint(ch)) && (!isspace(ch))) + ch = '.'; +#endif /* PRINTABLE_ONLY */ + + if ((com = bsp_shared_data->__console_procs) != NULL) + com->__putc(com->ch_data, ch); + else + bsp_debug_putc(ch); +} + +int +bsp_console_getc(void) +{ + struct bsp_comm_procs *com; + int ch; + + if ((com = bsp_shared_data->__console_procs) != NULL) { + if (__console_ungetc) { + ch = __console_ungetc; + __console_ungetc = 0; + return ch; + } + return com->__getc(com->ch_data); + } else + return bsp_debug_getc(); +} + + +void +bsp_console_ungetc(char ch) +{ + if (bsp_shared_data->__console_procs != NULL) + __console_ungetc = (unsigned char)ch; + else + bsp_debug_ungetc(ch); +} + + diff --git a/packages/cygmon/v2_0/misc/bsp/common/debug-io.c b/packages/cygmon/v2_0/misc/bsp/common/debug-io.c new file mode 100644 index 00000000..6d66771d --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/debug-io.c @@ -0,0 +1,142 @@ +//========================================================================== +// +// debug-io.c +// +// BSP Debug Channel Interfaces. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: BSP Debug Channel Interfaces. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include +#include +#include "bsp_if.h" + +static unsigned char __debug_ungetc; + +extern int stub_is_active; +extern int __output_gdb_string (const char *str, int string_len); +void +bsp_debug_write(const char *p, int len) +{ + struct bsp_comm_procs *com = bsp_shared_data->__debug_procs; + if (stub_is_active) { + // We are running in 'GDB' mode + __output_gdb_string(p, len); + } else { + com->__write(com->ch_data, p, len); + } +} + + +int +bsp_debug_read(char *p, int len) +{ + struct bsp_comm_procs *com = bsp_shared_data->__debug_procs; + + if (len <= 0) + return 0; + + if (__debug_ungetc) { + *p = __debug_ungetc; + __debug_ungetc = 0; + return 1; + } + + return com->__read(com->ch_data, p, len); +} + + +void +bsp_debug_putc(char ch) +{ + struct bsp_comm_procs *com = bsp_shared_data->__debug_procs; + + com->__putc(com->ch_data, ch); +} + +int +bsp_debug_getc(void) +{ + struct bsp_comm_procs *com = bsp_shared_data->__debug_procs; + int ch; + + if (__debug_ungetc) { + ch = __debug_ungetc; + __debug_ungetc = 0; + } else + ch = com->__getc(com->ch_data); + + return ch; +} + + +void +bsp_debug_ungetc(char ch) +{ + __debug_ungetc = (unsigned char)ch; +} + + +int +bsp_debug_irq_disable(void) +{ + struct bsp_comm_procs *com = bsp_shared_data->__debug_procs; + + return com->__control(com->ch_data, COMMCTL_IRQ_DISABLE); +} + + +void +bsp_debug_irq_enable(void) +{ + struct bsp_comm_procs *com = bsp_shared_data->__debug_procs; + + com->__control(com->ch_data, COMMCTL_IRQ_ENABLE); +} + + diff --git a/packages/cygmon/v2_0/misc/bsp/common/gdb-cpu.c b/packages/cygmon/v2_0/misc/bsp/common/gdb-cpu.c new file mode 100644 index 00000000..610b6b50 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/gdb-cpu.c @@ -0,0 +1,61 @@ +//========================================================================== +// +// gdb-cpu.c +// +// Architecture specific support for GDB +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= +#include + +#ifdef CYGPKG_HAL_ARM +#include "bsp/arm/gdb-cpu.c" +#endif + +#ifdef CYGPKG_HAL_MIPS +#include "bsp/mips/gdb-cpu.c" +#endif diff --git a/packages/cygmon/v2_0/misc/bsp/common/gdb-cpu.h b/packages/cygmon/v2_0/misc/bsp/common/gdb-cpu.h new file mode 100644 index 00000000..75821cba --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/gdb-cpu.h @@ -0,0 +1,65 @@ +#ifndef __BSP_COMMON_GDB_CPU_H__ +#define __BSP_COMMON_GDB_CPU_H__ +//========================================================================== +// +// gdb-cpu.h +// +// CPU specifics for GDB +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= +#include + +#ifdef CYGPKG_HAL_ARM +#include "../arm/gdb-cpu.h" +#endif + +#ifdef CYGPKG_HAL_MIPS +#include "../mips/gdb-cpu.h" +#endif + +#endif // __BSP_COMMON_GDB_CPU_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/common/gdb.h b/packages/cygmon/v2_0/misc/bsp/common/gdb.h new file mode 100644 index 00000000..1ade0ff0 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/gdb.h @@ -0,0 +1,103 @@ +#ifndef __BSP_COMMON_GDB_H__ +#define __BSP_COMMON_GDB_H__ +//========================================================================== +// +// gdb.h +// +// Definitions for GDB stub. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Definitions for GDB stub. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include "gdb-cpu.h" +#include + +#ifndef DEBUG_STUB +#define DEBUG_STUB 0 +#endif + +/* + * These need to match the same in devo/gdb/target.h + */ +#define TARGET_SIGNAL_INT 2 +#define TARGET_SIGNAL_ILL 4 +#define TARGET_SIGNAL_TRAP 5 +#define TARGET_SIGNAL_ABRT 6 +#define TARGET_SIGNAL_FPE 8 +#define TARGET_SIGNAL_BUS 10 +#define TARGET_SIGNAL_SEGV 11 + + +/* + * Socket to use for tcp/ip debug channel. + */ +#define GDB_TCP_SOCKET 1000 + + +#ifndef __ASSEMBLER__ + +/* generic gdb protocol handler */ +extern void _bsp_gdb_handler(int exc_nr, void *saved_regs); +extern gdb_data_t _bsp_gdb_data; + + +/* start forming an outgoing gdb packet */ +/* if ack is true, prepend an ack character */ +extern void _gdb_pkt_start(int ack); + +/* Append data to packet using formatted string. */ +extern void _gdb_pkt_append(char *fmt, ...); + +/* Calculate checksum and append to end of packet. */ +extern void _gdb_pkt_end(void); + +/* Send the packet. Blocks waiting for ACK */ +extern void _gdb_pkt_send(void); +#endif + +#endif //__BSP_COMMON_GDB_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/common/generic-mem.c b/packages/cygmon/v2_0/misc/bsp/common/generic-mem.c new file mode 100644 index 00000000..53c1985a --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/generic-mem.c @@ -0,0 +1,194 @@ +//========================================================================== +// +// generic-mem.c +// +// Generic support for safe memory read/write. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Generic support for safe memory read/write. +// Description: Some targets may need to provide their own version. +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include +#include +#include + +typedef void (*moveproc_t)(void *s, void *d); + +static jmp_buf __errjmp; + +/* + * These are globals because we want them preserved + * across function calls. + */ +static bsp_handler_t __oldtrap; +static int __done; + + +static void +move_8(void *src, void *dest) +{ + *(char *)dest = *(char *)src; +} + + +static void +move_16(void *src, void *dest) +{ + *(short *)dest = *(short *)src; +} + + +static void +move_32(void *src, void *dest) +{ + *(int *)dest = *(int *)src; +} + + +static int +err_trap(int exc_nr, void *regs) +{ + longjmp(__errjmp, 1); +} + + +int +bsp_memory_read(void *addr, /* start addr of memory to read */ + int asid, /* address space id */ + int rsize, /* size of individual read operation */ + int nreads, /* number of read operations */ + void *buf) /* result buffer */ +{ + if (nreads <= 0) + return 0; + + __oldtrap = bsp_install_dbg_handler(err_trap); + + if (setjmp(__errjmp) == 0) { + moveproc_t move_mem; + int incr; + char *src, *dest; + + switch (rsize) { + case 8: + move_mem = move_8; + incr = 1; + break; + case 16: + move_mem = move_16; + incr = 2; + break; + case 32: + move_mem = move_32; + incr = 4; + break; + default: + (void)bsp_install_dbg_handler(__oldtrap); + return 0; + } + + src = addr; + dest = buf; + + for (__done = 0; __done < nreads; __done++) { + move_mem(src, dest); + src += incr; + dest += incr; + } + } + + (void)bsp_install_dbg_handler(__oldtrap); + return __done; +} + + +int bsp_memory_write(void *addr, /* start addr of memory to write */ + int asid, /* address space id */ + int wsize, /* size of individual write operation */ + int nwrites, /* number of write operations */ + void *buf) /* source buffer for write data */ +{ + if (nwrites <= 0) + return 0; + + __oldtrap = bsp_install_dbg_handler(err_trap); + + if (setjmp(__errjmp) == 0) { + moveproc_t move_mem; + int incr; + char *src, *dest; + + switch (wsize) { + case 8: + move_mem = move_8; + incr = 1; + break; + case 16: + move_mem = move_16; + incr = 2; + break; + case 32: + move_mem = move_32; + incr = 4; + break; + default: + (void)bsp_install_dbg_handler(__oldtrap); + return 0; + } + + src = buf; + dest = addr; + + for (__done = 0; __done < nwrites; __done++) { + move_mem(src, dest); + src += incr; + dest += incr; + } + } + + (void)bsp_install_dbg_handler(__oldtrap); + return __done; +} diff --git a/packages/cygmon/v2_0/misc/bsp/common/hex-utils.c b/packages/cygmon/v2_0/misc/bsp/common/hex-utils.c new file mode 100644 index 00000000..5cb2c4cb --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/hex-utils.c @@ -0,0 +1,126 @@ +//========================================================================== +// +// hex-utils.c +// +// Utilities for dealing with hexadecimal strings. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include + +int +__hex(char ch) +{ + if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10); + if ((ch >= '0') && (ch <= '9')) return (ch-'0'); + if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10); + return (-1); +} + + +/* + * Convert the hex data in 'buf' into 'count' bytes to be placed in 'mem'. + * Returns a pointer to the character in mem AFTER the last byte written. + */ +char * +__unpack_bytes_to_mem(char *buf, char *mem, int count) +{ + int i; + char ch; + + for (i = 0; i < count; i++) { + ch = __hex(*buf++) << 4; + ch = ch + __hex(*buf++); + *mem++ = ch; + } + return(mem); +} + +/* + * While finding valid hex chars, build an unsigned long int. + * Return number of hex chars processed. + */ +int +__unpack_ulong(char **ptr, unsigned long *val) +{ + int numChars = 0; + int hexValue; + + *val = 0; + + while (**ptr) { + hexValue = __hex(**ptr); + if (hexValue >= 0) { + *val = (*val << 4) | hexValue; + numChars ++; + } else + break; + (*ptr)++; + } + return (numChars); +} + + +/* + * Unpack 'count' hex characters, forming them into a binary value. + * Return that value as an int. Adjust the source pointer accordingly. + */ +int +__unpack_nibbles(char **ptr, int count) +{ + int value = 0; + + while (--count >= 0) { + value = (value << 4) | __hex(**ptr); + (*ptr)++; + } + return value; +} + + diff --git a/packages/cygmon/v2_0/misc/bsp/common/printf.c b/packages/cygmon/v2_0/misc/bsp/common/printf.c new file mode 100644 index 00000000..d8fdea13 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/printf.c @@ -0,0 +1,95 @@ +//========================================================================== +// +// printf.c +// +// Light-weight BSP printf. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Light-weight BSP printf. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include +#include "bsp_if.h" + + +void +bsp_vprintf(const char *fmt, va_list ap) +{ + __vprintf(bsp_console_putc, fmt, ap); +} + + +void +bsp_dvprintf(const char *fmt, va_list ap) +{ + __vprintf(bsp_debug_putc, fmt, ap); +} + + +void +bsp_printf(const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + __vprintf(bsp_console_putc, fmt, ap); + va_end (ap); +} + + +void +bsp_dprintf(const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + __vprintf(bsp_debug_putc, fmt, ap); + va_end (ap); +} + + + diff --git a/packages/cygmon/v2_0/misc/bsp/common/shared-data.c b/packages/cygmon/v2_0/misc/bsp/common/shared-data.c new file mode 100644 index 00000000..281a1032 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/shared-data.c @@ -0,0 +1,59 @@ +//========================================================================== +// +// shared-data.c +// +// Declaration of bsp shared data pointer. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Declaration of bsp shared data pointer. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include "bsp_if.h" + +bsp_shared_t *bsp_shared_data; + + diff --git a/packages/cygmon/v2_0/misc/bsp/common/singlestep.c b/packages/cygmon/v2_0/misc/bsp/common/singlestep.c new file mode 100644 index 00000000..04cbc0be --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/singlestep.c @@ -0,0 +1,61 @@ +//========================================================================== +// +// singlestep.c +// +// Architecture specific single-step support +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= +#include + +#ifdef CYGPKG_HAL_ARM +#include "bsp/arm/singlestep.c" +#endif + +#ifdef CYGPKG_HAL_MIPS +#include "bsp/mips/singlestep.c" +#endif diff --git a/packages/cygmon/v2_0/misc/bsp/common/sprintf.c b/packages/cygmon/v2_0/misc/bsp/common/sprintf.c new file mode 100644 index 00000000..b05645bd --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/sprintf.c @@ -0,0 +1,86 @@ +//========================================================================== +// +// sprintf.c +// +// Light-weight BSP sprintf. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Light-weight BSP sprintf. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include +#include "bsp_if.h" + +static char *str_ptr; + +static void +str_putc(char ch) +{ + *str_ptr++ = ch; +} + +int +bsp_vsprintf(char *str, const char *fmt, va_list ap) +{ + str_ptr = str; + __vprintf(str_putc, fmt, ap); + *str_ptr = '\0'; + return str_ptr - str; +} + + +void +bsp_sprintf(char *str, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + bsp_vsprintf(str, fmt, ap); + va_end (ap); +} + + diff --git a/packages/cygmon/v2_0/misc/bsp/common/syscall.c b/packages/cygmon/v2_0/misc/bsp/common/syscall.c new file mode 100644 index 00000000..120f7221 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/syscall.c @@ -0,0 +1,218 @@ +//========================================================================== +// +// syscall.c +// +// Minimal generic syscall support. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Minimal generic syscall support. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include +#include +#include +#include "bsp_if.h" +#include "syscall.h" + +/* + * read -- read bytes from the serial port. Ignore fd, since + * we only have stdin. + */ +static int +sys_read(int fd, char *buf, int nbytes) +{ + int i = 0; + + for (i = 0; i < nbytes; i++) { + *(buf + i) = bsp_console_getc(); + if ((*(buf + i) == '\n') || (*(buf + i) == '\r')) { + (*(buf + i + 1)) = 0; + break; + } + } + return (i); +} + + +/* + * write -- write bytes to the serial port. Ignore fd, since + * stdout and stderr are the same. Since we have no filesystem, + * open will only return an error. + */ +static int +sys_write(int fd, char *buf, int nbytes) +{ +#define WBUFSIZE 256 + char ch, lbuf[WBUFSIZE]; + int i, tosend; + + tosend = nbytes; + + while (tosend > 0) { + for (i = 0; tosend > 0 && i < (WBUFSIZE-2); tosend--) { + ch = *buf++; + if (ch == '\n') + lbuf[i++] = '\r'; + lbuf[i++] = ch; + } + bsp_console_write(lbuf, i); + } + + return (nbytes); +} + + +/* + * open -- open a file descriptor. We don't have a filesystem, so + * we return an error. + */ +static int +sys_open (const char *buf, int flags, int mode) +{ + return (-EIO); +} + + +/* + * close -- We don't need to do anything, but pretend we did. + */ +static int +sys_close(int fd) +{ + return (0); +} + + +/* + * lseek -- Since a serial port is non-seekable, we return an error. + */ +static int +sys_lseek(int fd, int offset, int whence) +{ +#ifdef ESPIPE + return (-ESPIPE); +#else + return (-EIO); +#endif +} + + +/* + * Generic syscall handler. + * + * Returns 0 if syscall number is not handled by this + * module, 1 otherwise. This allows applications to + * extend the syscall handler by using exception chaining. + */ +int +_bsp_do_syscall(int func, /* syscall function number */ + long arg1, long arg2, /* up to four args. */ + long arg3, long arg4, + int *retval) /* syscall return value */ +{ + int err = 0; + + switch (func) { + + case SYS_read: + err = sys_read((int)arg1, (char *)arg2, (int)arg3); + break; + + case SYS_write: + err = sys_write((int)arg1, (char *)arg2, (int)arg3); + break; + + case SYS_open: + err = sys_open((const char *)arg1, (int)arg2, (int)arg3); + break; + + case SYS_close: + err = sys_close((int)arg1); + break; + + case SYS_lseek: + err = sys_lseek((int)arg1, (int)arg2, (int)arg3); + break; + + case BSP_GET_SHARED: + *(bsp_shared_t **)arg1 = bsp_shared_data; + break; + + case SYS_meminfo: + { + // Return the top and size of memory. + struct bsp_mem_info mem; + int i; + unsigned long u, totmem, topmem, numbanks; + + i = totmem = topmem = numbanks = 0; + while (bsp_sysinfo(BSP_INFO_MEMORY, i++, &mem) == 0) + { + if (mem.kind == BSP_MEM_RAM) + { + numbanks++; + totmem += mem.nbytes; + u = (unsigned long)mem.virt_start + mem.nbytes; + if (u > topmem) + topmem = u; + } + } + *(unsigned long *)arg1 = totmem; + *(unsigned long *)arg2 = topmem; + *retval = numbanks; + } + return 1; + break; + + default: + return 0; + } + + *retval = err; + return 1; +} + + diff --git a/packages/cygmon/v2_0/misc/bsp/common/syscall.h b/packages/cygmon/v2_0/misc/bsp/common/syscall.h new file mode 100644 index 00000000..00d555f5 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/syscall.h @@ -0,0 +1,50 @@ +/* General use syscall.h file. + The more ports that use this file, the simpler sim/common/nltvals.def + remains. */ + +#ifndef LIBGLOSS_SYSCALL_H +#define LIBGLOSS_SYSCALL_H + +/* Note: This file may be included by assembler source. */ + +/* These should be as small as possible to allow a port to use a trap type + instruction, which the system call # as the trap (the d10v for instance + supports traps 0..31). An alternative would be to define one trap for doing + system calls, and put the system call number in a register that is not used + for the normal calling sequence (so that you don't have to shift down the + arguments to add the system call number). Obviously, if these system call + numbers are ever changed, all of the simulators and potentially user code + will need to be updated. */ + +/* There is no current need for the following: SYS_execv, SYS_creat, SYS_wait, + etc. etc. Don't add them. */ + +/* These are required by the ANSI C part of newlib (excluding system() of + course). */ +#define SYS_exit 1 +#define SYS_open 2 +#define SYS_close 3 +#define SYS_read 4 +#define SYS_write 5 +#define SYS_lseek 6 +#define SYS_unlink 7 +#define SYS_getpid 8 +#define SYS_kill 9 +#define SYS_fstat 10 +/*#define SYS_sbrk 11 - not currently a system call, but reserved. */ + +/* ARGV support. */ +#define SYS_argvlen 12 +#define SYS_argv 13 + +/* These are extras added for one reason or another. */ +#define SYS_chdir 14 +#define SYS_stat 15 +#define SYS_chmod 16 +#define SYS_utime 17 +#define SYS_time 18 + +#define SYS_interrupt 1000 + +#define SYS_meminfo 1001 +#endif diff --git a/packages/cygmon/v2_0/misc/bsp/common/sysinfo.c b/packages/cygmon/v2_0/misc/bsp/common/sysinfo.c new file mode 100644 index 00000000..cc15801a --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/sysinfo.c @@ -0,0 +1,170 @@ +//========================================================================== +// +// sysinfo.c +// +// Interface for getting system information. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Interface for getting system information. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include +#include +#include "bsp_if.h" + + +/* + * In order to construct the _bsp_memory_list, some board specific code + * may have to size RAM regions. To do this easily and reliably, the code + * needs to run from ROM before .bss and .data sections are initialized. + * This leads to the problem of where to store the results of the memory + * sizing tests. In this case, the _bsp_init_stack routine which sizes + * memory and sets up the stack will place the board-specific information + * on the stack and return with the stack pointer pointing to a pointer to + * the information. That is, addr_of_info = *(void **)sp. The architecture + * specific code will then copy that pointer to the _bsp_ram_info_ptr variable + * after initializing the .data and .bss sections. + */ +void *_bsp_ram_info_ptr; + +/* + * Name of CPU and board. Should be overridden by arch/board specific + * code. + */ +struct bsp_platform_info _bsp_platform_info = { + "Unknown", /* cpu name */ + "Unknown", /* board name */ + "" /* extra info */ +}; + + +/* + * Information about possible data cache. Should be overridden by + * by arch/board specific code. + */ +struct bsp_cachesize_info _bsp_dcache_info = { + 0, 0, 0 +}; + + +/* + * Information about possible instruction cache. Should be overridden by + * by arch/board specific code. + */ +struct bsp_cachesize_info _bsp_icache_info = { + 0, 0, 0 +}; + + +/* + * Information about possible secondary cache. Should be overridden by + * by arch/board specific code. + */ +struct bsp_cachesize_info _bsp_scache_info = { + 0, 0, 0 +}; + + + +int +_bsp_sysinfo(enum bsp_info_id id, va_list ap) +{ + int index, rval = 0; + void *p; + + switch (id) { + case BSP_INFO_PLATFORM: + p = va_arg(ap, void *); + *(struct bsp_platform_info *)p = _bsp_platform_info; + break; + + case BSP_INFO_DCACHE: + p = va_arg(ap, void *); + *(struct bsp_cachesize_info *)p = _bsp_dcache_info; + break; + + case BSP_INFO_ICACHE: + p = va_arg(ap, void *); + *(struct bsp_cachesize_info *)p = _bsp_icache_info; + break; + + case BSP_INFO_SCACHE: + p = va_arg(ap, void *); + *(struct bsp_cachesize_info *)p = _bsp_scache_info; + break; + + case BSP_INFO_MEMORY: + index = va_arg(ap, int); + p = va_arg(ap, void *); + + if (index >= 0 && index < _bsp_num_mem_regions) + *(struct bsp_mem_info *)p = _bsp_memory_list[index]; + else + rval = -1; + break; + + case BSP_INFO_COMM: + index = va_arg(ap, int); + p = va_arg(ap, void *); + + if (index >= 0 && index < _bsp_num_comms) + *(struct bsp_comm_info *)p = _bsp_comm_list[index].info; + else if (index == _bsp_num_comms && _bsp_net_channel != NULL) + *(struct bsp_comm_info *)p = _bsp_net_channel->info; + else + rval = -1; + break; + + default: + rval = -1; + } + + return rval; +} + + + diff --git a/packages/cygmon/v2_0/misc/bsp/common/vprintf.c b/packages/cygmon/v2_0/misc/bsp/common/vprintf.c new file mode 100644 index 00000000..5d1a7e7d --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/common/vprintf.c @@ -0,0 +1,445 @@ +//========================================================================== +// +// vprintf.c +// +// Stripped down (no floating point) for debugging printf in ROMable BSP. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +/* + * Copyright (c) 1990, 1999 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Stripped down (no floating point) for debugging printf in ROMable BSP. + */ +#include +#include + +#define BUF 40 + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* + * Macros for converting digits to letters and vice versa + */ +#define to_digit(c) ((c) - '0') +#define is_digit(c) ((unsigned)to_digit(c) <= 9) +#define to_char(n) ((n) + '0') + +/* + * Flags used during conversion. + */ +#define ALT 0x001 /* alternate form */ +#define HEXPREFIX 0x002 /* add 0x or 0X prefix */ +#define LADJUST 0x004 /* left adjustment */ +#define LONGDBL 0x008 /* long double; unimplemented */ +#define LONGINT 0x010 /* long integer */ +#define QUADINT 0x020 /* quad integer */ +#define SHORTINT 0x040 /* short integer */ +#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ +#define FPT 0x100 /* Floating point number */ + + +void +__vprintf(void (*putc_func)(char c), const char *fmt0, va_list ap) +{ + char *fmt; /* format string */ + int ch; /* character from fmt */ + int n, m; /* handy integers (short term usage) */ + char *cp; /* handy char pointer (short term usage) */ + int flags; /* flags as above */ + int width; /* width from format (%8d), or 0 */ + int prec; /* precision from format (%.3d), or -1 */ + char sign; /* sign prefix (' ', '+', '-', or \0) */ + unsigned long _uquad; + enum {OCT, DEC, HEX} base; /* base for [diouxX] conversion */ + int dprec; /* a copy of prec if [diouxX], 0 otherwise */ + int realsz; /* field size expanded by dprec */ + int size; /* size of converted field or string */ + char *xdigs = NULL; /* digits for [xX] conversion */ + char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ + char ox[2]; /* space for 0x hex-prefix */ + +#define PRINT(ptr, len) { \ + for(n=0;n<(len);n++) { \ + if((ptr)[n] == '\n') \ + (*putc_func)('\r'); \ + (*putc_func)((ptr)[n]); \ + } \ +} + +#define PAD(howmany, with) { \ + if ((n = (howmany)) > 0) { \ + while (n--) \ + (*putc_func)(with); \ + } \ +} + + /* + * To extend shorts properly, we need both signed and unsigned + * argument extraction methods. + */ +#define SARG() \ + (flags&LONGINT ? va_arg(ap, long) : \ + flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ + (long)va_arg(ap, int)) + +#define UARG() \ + (flags&LONGINT ? va_arg(ap, unsigned long) : \ + flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \ + (unsigned long)va_arg(ap, unsigned int)) + + fmt = (char *)fmt0; + + /* + * Scan the format for conversions (`%' character). + */ + for (;;) { + cp = fmt; + while (*fmt && *fmt != '%') + fmt++; + if ((m = fmt - cp) != 0) { + PRINT(cp, m); + } + + if (*fmt) + fmt++; /* skip over '%' */ + else + goto done; + + flags = 0; + dprec = 0; + width = 0; + prec = -1; + sign = '\0'; + + rflag: + ch = *fmt++; + reswitch: + switch (ch) { + case ' ': + /* + * ``If the space and + flags both appear, the space + * flag will be ignored.'' + * -- ANSI X3J11 + */ + if (!sign) + sign = ' '; + goto rflag; + case '#': + flags |= ALT; + goto rflag; + case '*': + /* + * ``A negative field width argument is taken as a + * - flag followed by a positive field width.'' + * -- ANSI X3J11 + * They don't exclude field widths read from args. + */ + if ((width = va_arg(ap, int)) >= 0) + goto rflag; + width = -width; + /* FALLTHROUGH */ + case '-': + flags |= LADJUST; + goto rflag; + case '+': + sign = '+'; + goto rflag; + case '.': + if ((ch = *fmt++) == '*') { + n = va_arg(ap, int); + prec = n < 0 ? -1 : n; + goto rflag; + } + n = 0; + while (is_digit(ch)) { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } + prec = n < 0 ? -1 : n; + goto reswitch; + case '0': + /* + * ``Note that 0 is taken as a flag, not as the + * beginning of a field width.'' + * -- ANSI X3J11 + */ + flags |= ZEROPAD; + goto rflag; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n = 0; + do { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } while (is_digit(ch)); + width = n; + goto reswitch; + case 'h': + flags |= SHORTINT; + goto rflag; + case 'l': + if (*fmt == 'l') { + fmt++; + flags |= QUADINT; + } else { + flags |= LONGINT; + } + goto rflag; + case 'c': + *(cp = buf) = va_arg(ap, int); + size = 1; + sign = '\0'; + break; + case 'd': + case 'i': + _uquad = SARG(); + if ((long) _uquad < 0) + { + + _uquad = -_uquad; + sign = '-'; + } + base = DEC; + goto number; + case 'o': + _uquad = UARG(); + base = OCT; + goto nosign; + case 's': + if ((cp = va_arg(ap, char *)) == NULL) + cp = "(null)"; + if (prec >= 0) { + /* + * can't use strlen; can only look for the + * NUL in the first `prec' characters, and + * strlen() will go further. + */ + char *p = memchr(cp, 0, prec); + + if (p != NULL) { + size = p - cp; + if (size > prec) + size = prec; + } else + size = prec; + } else + size = strlen(cp); + sign = '\0'; + break; + case 'u': + _uquad = UARG(); + base = DEC; + goto nosign; + case 'X': + xdigs = "0123456789ABCDEF"; + goto hex; + case 'x': + xdigs = "0123456789abcdef"; + hex: _uquad = UARG(); + base = HEX; + /* leading 0x/X only if non-zero */ + if (flags & ALT && _uquad != 0) + flags |= HEXPREFIX; + + /* unsigned conversions */ + nosign: sign = '\0'; + /* + * ``... diouXx conversions ... if a precision is + * specified, the 0 flag will be ignored.'' + * -- ANSI X3J11 + */ + number: if ((dprec = prec) >= 0) + flags &= ~ZEROPAD; + + /* + * ``The result of converting a zero value with an + * explicit precision of zero is no characters.'' + * -- ANSI X3J11 + */ + cp = buf + BUF; + if (_uquad != 0 || prec != 0) { + /* + * Unsigned mod is hard, and unsigned mod + * by a constant is easier than that by + * a variable; hence this switch. + */ + switch (base) { + case OCT: + do { + *--cp = to_char(_uquad & 7); + _uquad >>= 3; + } while (_uquad); + /* handle octal leading 0 */ + if (flags & ALT && *cp != '0') + *--cp = '0'; + break; + + case DEC: + /* many numbers are 1 digit */ + while (_uquad >= 10) { + *--cp = to_char(_uquad % 10); + _uquad /= 10; + } + *--cp = to_char(_uquad); + break; + + case HEX: + do { + *--cp = xdigs[_uquad & 15]; + _uquad >>= 4; + } while (_uquad); + break; + + default: + cp = "bug in vfprintf: bad base"; + size = strlen(cp); + goto skipsize; + } + } + size = buf + BUF - cp; + skipsize: + break; + default: /* "%?" prints ?, unless ? is NUL */ + if (ch == '\0') + goto done; + /* pretend it was %c with argument ch */ + cp = buf; + *cp = ch; + size = 1; + sign = '\0'; + break; + } + + /* + * All reasonable formats wind up here. At this point, `cp' + * points to a string which (if not flags&LADJUST) should be + * padded out to `width' places. If flags&ZEROPAD, it should + * first be prefixed by any sign or other prefix; otherwise, + * it should be blank padded before the prefix is emitted. + * After any left-hand padding and prefixing, emit zeroes + * required by a decimal [diouxX] precision, then print the + * string proper, then emit zeroes required by any leftover + * floating precision; finally, if LADJUST, pad with blanks. + * + * Compute actual size, so we know how much to pad. + * size excludes decimal prec; realsz includes it. + */ + realsz = dprec > size ? dprec : size; + if (sign) + realsz++; + else if (flags & HEXPREFIX) + realsz+= 2; + + /* right-adjusting blank padding */ + if ((flags & (LADJUST|ZEROPAD)) == 0) + PAD(width - realsz, ' '); + + /* prefix */ + if (sign) { + PRINT(&sign, 1); + } else if (flags & HEXPREFIX) { + ox[0] = '0'; + ox[1] = ch; + PRINT(ox, 2); + } + + /* right-adjusting zero padding */ + if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) + PAD(width - realsz, '0'); + + /* leading zeroes from decimal precision */ + PAD(dprec - size, '0'); + + /* the string or number proper */ + PRINT(cp, size); + + /* left-adjusting padding (always blank) */ + if (flags & LADJUST) + PAD(width - realsz, ' '); + } + done: +} + + diff --git a/packages/cygmon/v2_0/misc/bsp/cpu.h b/packages/cygmon/v2_0/misc/bsp/cpu.h new file mode 100644 index 00000000..66ea53a7 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/cpu.h @@ -0,0 +1,71 @@ +#ifndef __BSP_CPU_H__ +#define __BSP_CPU_H__ +//========================================================================== +// +// cpu.h +// +// Architecture/processor specifics +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas, dmoseley +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= +// Pick up architecture info + +#include + +#ifdef CYGPKG_HAL_ARM +#include "arm/cpu.h" +#endif + +#ifdef CYGPKG_HAL_MIPS +#include "mips/cpu.h" +#endif + +#ifdef CYGPKG_HAL_MN10300 +#include "mn10300/cpu.h" +#endif + +#endif // __BSP_CPU_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/dbg-threads-api.h b/packages/cygmon/v2_0/misc/bsp/dbg-threads-api.h new file mode 100644 index 00000000..8eb1bd75 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/dbg-threads-api.h @@ -0,0 +1,148 @@ +#ifndef __BSP_DBG_THREADS_API_H__ +#define __BSP_DBG_THREADS_API_H__ +//========================================================================== +// +// dbg-threads-api.h +// +// +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: These are the calls used to extract operating system +// specific information used in supporting thread aware +// debugging. +// The Operating Environment being debugged needs to supply +// these functions. +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#define has_thread_void 0 +#define has_thread_current 1 +#define has_thread_registers 2 +#define has_thread_reg_change 4 +#define has_thread_list 8 +#define has_thread_info 16 + +typedef unsigned char threadref[8] ; + +struct dbg_capabilities +{ + unsigned long mask1; +}; + +/* fill in the list of thread aware capabilities */ +extern int dbg_thread_capabilities(struct dbg_capabilities *cbp); + + +/* Fill in the identifier of the current thread */ +/* return 1 if defined, 0 if not defined */ +extern int dbg_currthread(threadref *varparm); + +/* get the first or next member of the list of known threads */ +extern int dbg_threadlist(int startflag, + threadref *lastthreadid, + threadref *next_thread); + +/* return 1 if next_threadid has been filled in with a value */ +/* return 0 if there are none or no more */ + +/* The O.S can fill in the following information about a thread when queried. + The structure of thise strings is determined by the O.S. + It is display oriented, so figure out what the users need to see. + Nulls are OK but GDB will fill some not so meaningful data. + These pointers may be in the calles private structures, the info will + get copied immediatly after the call to retreive it. + */ +struct cygmon_thread_debug_info +{ + threadref thread_id ; + int context_exists ; /* To the point where examining its state, + registers and stack makes sense to GDB */ + char * thread_display ; /* As shown in thread status window, name, state */ + char * unique_thread_name ; /* human readable identifier, window label */ + char * more_display ; /* more detailed info about thread. + priority, queuedepth, state, stack usage, statistics */ +} ; + + + + +extern int dbg_threadinfo(threadref *threadid, + struct cygmon_thread_debug_info *info); + +/* Return 1 if threadid is defined and info copied, 0 otherwise */ + +/* The O.S should fillin the array of registers using values from the +saves context. The array MUST be in GDB register save order even if +the saved context is different or smaller. Do not alter the values of +registers which are NOT in the O.S. thread context. Their default values +have already been assigned. +*/ + +extern int dbg_getthreadreg(threadref *osthreadid, + int regcount, /* count of registers in the array */ + void * regval); /* fillin this array */ + + +/* The O.S. should scan through this list of registers which are in +GDB order and the O.S. should replace the values of all registers +which are defined in the saved context of thread or process identified +by osthreadid. Return 0 if the threadis does not map to a known +process or other error. Return 1 if the setting is successful. */ + +extern int dbg_setthreadreg(threadref *osthreadid, + int regcount, /* number of registers */ + void *regval) ; + + +extern int dbg_scheduler(threadref *thread_id, int lock, int mode); + +/* --- EXCEPTION - + The O.S. does not provide this function , it calls this to specify the + location of the dbg_syscall vector + */ +extern void patch_dbg_syscalls(void * vector); + +#endif /* DBG_THREADS_API_INCLUDED */ +#endif // __BSP_DBG_THREADS_API_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/defs.h b/packages/cygmon/v2_0/misc/bsp/defs.h new file mode 100644 index 00000000..cd39ac24 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/defs.h @@ -0,0 +1,112 @@ +#ifndef __BSP_DEFS_H__ +#define __BSP_DEFS_H__ +//========================================================================== +// +// defs.h +// +// Definitions of interest to Red Hat BSP. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Definitions of interest to Red Hat BSP. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#define SZ_1K 0x00000400 +#define SZ_2K 0x00000800 +#define SZ_4K 0x00001000 +#define SZ_8K 0x00002000 +#define SZ_16K 0x00004000 +#define SZ_32K 0x00008000 +#define SZ_64K 0x00010000 +#define SZ_128K 0x00020000 +#define SZ_256K 0x00040000 +#define SZ_512K 0x00080000 +#define SZ_1M 0x00100000 +#define SZ_2M 0x00200000 +#define SZ_4M 0x00400000 +#define SZ_8M 0x00800000 +#define SZ_16M 0x01000000 +#define SZ_32M 0x02000000 +#define SZ_64M 0x04000000 +#define SZ_128M 0x08000000 +#define SZ_256M 0x10000000 +#define SZ_512M 0x20000000 +#define SZ_1G 0x40000000 + +#endif // __BSP_DEFS_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/gdb-data.h b/packages/cygmon/v2_0/misc/bsp/gdb-data.h new file mode 100644 index 00000000..b4dce69e --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/gdb-data.h @@ -0,0 +1,126 @@ +#ifndef __BSP_GDB_DATA_H__ +#define __BSP_GDB_DATA_H__ +//========================================================================== +// +// gdb-data.h +// +// Shared data specific to gdb stub. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Shared data specific to gdb stub. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#ifndef __ASSEMBLER__ +typedef int (*gdb_memproc_t)(void *__addr, /* start addr of memory to read/write */ + int __asid, /* address space id */ + int __size, /* size of individual read/write ops */ + int __n, /* number of read/write operations */ + void *__buf); /* result(read)/src(write) buffer */ + + +typedef void (*gdb_regproc_t)(int __regno, /* Register number */ + void *__regs, /* pointer to saved regs */ + void *__val); /* pointer to register value */ + + +typedef struct { + /* + * An application may override the standard BSP memory + * read and/or write routines with these hooks. + */ + gdb_memproc_t __mem_read_hook; + gdb_memproc_t __mem_write_hook; + + /* + * An application may override the standard BSP register + * access routines with these hooks. + */ + gdb_regproc_t __reg_get_hook; + gdb_regproc_t __reg_set_hook; + + /* + * An application may extend the gdb remote protocol by + * installing hooks to handle unknown general query and + * set packets ("q" pkts and 'Q' pkts) with these two hooks. + */ + void (*__pkt_query_hook)(unsigned char *__pkt); + void (*__pkt_set_hook)(unsigned char *__pkt); + + /* + * An application may also extend the gdb remote protocol + * by installing a hook to handle all unknown packets. + */ + void (*__pkt_hook)(unsigned char *__pkt); + + /* + * The above hooks for receiving packets will probably need + * a mechanism to respond. This vector is provided to allow + * an application to append data to the outgoing packet which + * will be sent after the above hooks are called. + * + * This vector uses a printf-like format string followed by + * some number of arguments. + */ + void (*__pkt_append)(char *fmt, ...); + + /* + * An application can read/write from/to gdb console + * through these vectors. + * + * NB: console read is not supported and will block forever. + */ + int (*__console_read)(char *__buf, int len); + int (*__console_write)(char *__buf, int len); + +} gdb_data_t; + + +extern gdb_data_t *__get_gdb_data(void); + +#endif /* __ASSEMBLER__ */ + +#endif // __BSP_GDB_DATA_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/hex-utils.h b/packages/cygmon/v2_0/misc/bsp/hex-utils.h new file mode 100644 index 00000000..12bf43a5 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/hex-utils.h @@ -0,0 +1,85 @@ +#ifndef __BSP_HEX_UTILS_H__ +#define __BSP_HEX_UTILS_H__ +//========================================================================== +// +// hex-utils.h +// +// Utilities for decoding hexadecimal encoded integers. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Utilities for decoding hexadecimal encoded integers. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#ifndef __ASSEMBLER__ + +/* + * Convert a single hex character to its binary value. + * Returns -1 if given character is not a value hex character. + */ +extern int __hex(char ch); + +/* + * Convert the hex data in 'buf' into 'count' bytes to be placed in 'mem'. + * Returns a pointer to the character in mem AFTER the last byte written. + */ +extern char *__unpack_bytes_to_mem(char *buf, char *mem, int count); + +/* + * While finding valid hex chars, build an unsigned long int. + * Return number of hex chars processed. + */ +extern int __unpack_ulong(char **ptr, unsigned long *val); + +/* + * Unpack 'count' hex characters, forming them into a binary value. + * Return that value as an int. Adjust the source pointer accordingly. + */ +extern int __unpack_nibbles(char **ptr, int count); + +#endif + +#endif // __BSP_HEX_UTILS_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/mips/gdb-cpu.c b/packages/cygmon/v2_0/misc/bsp/mips/gdb-cpu.c new file mode 100644 index 00000000..b539c7ee --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/mips/gdb-cpu.c @@ -0,0 +1,53 @@ +//========================================================================== +// +// gdb-cpu.c +// +// CPU specific support for GDB stub. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-06-07 +// Purpose: CPU specific support for GDB stub. +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Nothing now. diff --git a/packages/cygmon/v2_0/misc/bsp/mips/gdb-cpu.h b/packages/cygmon/v2_0/misc/bsp/mips/gdb-cpu.h new file mode 100644 index 00000000..fc68a42a --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/mips/gdb-cpu.h @@ -0,0 +1,58 @@ +#ifndef __BSP_MIPS_GDB_CPU_H__ +#define __BSP_MIPS_GDB_CPU_H__ +//========================================================================== +// +// gdb-cpu.h +// +// CPU specific definitions for GDB stub. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: dmoseley +// Date: 2000-07-10 +// Purpose: CPU specific definitions for GDB stub. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Nothing now. + +#endif // __BSP_MIPS_GDB_CPU_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/mips/gdb.h b/packages/cygmon/v2_0/misc/bsp/mips/gdb.h new file mode 100644 index 00000000..12180121 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/mips/gdb.h @@ -0,0 +1,58 @@ +#ifndef __BSP_MIPS_GDB_H__ +#define __BSP_MIPS_GDB_H__ +//========================================================================== +// +// gdb.h +// +// +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Nothing now. + +#endif // __BSP_ARM_GDB_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/mips/insn.h b/packages/cygmon/v2_0/misc/bsp/mips/insn.h new file mode 100644 index 00000000..e6cedeaf --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/mips/insn.h @@ -0,0 +1,59 @@ +#ifndef __BSP_MIPS_INSN_H__ +#define __BSP_MIPS_INSN_H__ +//========================================================================== +// +// insn.h +// +// MIPS instruction descriptions. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-07-10 +// Purpose: MIPS instruction descriptions. +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Nothing now. +// We are using the eCos hal for single-stepping. +// FIXME: this file can be removed + +#endif // __BSP_ARM_INSN_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/mips/singlestep.c b/packages/cygmon/v2_0/misc/bsp/mips/singlestep.c new file mode 100644 index 00000000..b57e73c1 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/mips/singlestep.c @@ -0,0 +1,55 @@ +//========================================================================== +// +// singlestep.c +// +// MIPS specific single-step support. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-07-10 +// Purpose: MIPS specific single-step support. +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Nothing now. +// We are using the eCos hal for single-stepping. +// FIXME: this file can be removed diff --git a/packages/cygmon/v2_0/misc/bsp/mn10300/gdb-cpu.c b/packages/cygmon/v2_0/misc/bsp/mn10300/gdb-cpu.c new file mode 100644 index 00000000..ce92d11e --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/mn10300/gdb-cpu.c @@ -0,0 +1,53 @@ +//========================================================================== +// +// gdb-cpu.c +// +// CPU specific support for GDB stub. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-08-11 +// Purpose: CPU specific support for GDB stub. +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Nothing now. diff --git a/packages/cygmon/v2_0/misc/bsp/mn10300/gdb-cpu.h b/packages/cygmon/v2_0/misc/bsp/mn10300/gdb-cpu.h new file mode 100644 index 00000000..87d61798 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/mn10300/gdb-cpu.h @@ -0,0 +1,58 @@ +#ifndef __BSP_MN10300_GDB_CPU_H__ +#define __BSP_MN10300_GDB_CPU_H__ +//========================================================================== +// +// gdb-cpu.h +// +// CPU specific definitions for GDB stub. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-08-11 +// Purpose: CPU specific definitions for GDB stub. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Nothing now. + +#endif // __BSP_MN10300_GDB_CPU_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/mn10300/gdb.h b/packages/cygmon/v2_0/misc/bsp/mn10300/gdb.h new file mode 100644 index 00000000..6b580e97 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/mn10300/gdb.h @@ -0,0 +1,58 @@ +#ifndef __BSP_MN10300_GDB_H__ +#define __BSP_MN10300_GDB_H__ +//========================================================================== +// +// gdb.h +// +// +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-08-11 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Nothing now. + +#endif // __BSP_ARM_GDB_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/mn10300/insn.h b/packages/cygmon/v2_0/misc/bsp/mn10300/insn.h new file mode 100644 index 00000000..3a29fc70 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/mn10300/insn.h @@ -0,0 +1,59 @@ +#ifndef __BSP_MN10300_INSN_H__ +#define __BSP_MN10300_INSN_H__ +//========================================================================== +// +// insn.h +// +// MN10300 instruction descriptions. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-08-11 +// Purpose: MN10300 instruction descriptions. +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Nothing now. +// We are using the eCos hal for single-stepping. +// FIXME: this file can be removed + +#endif // __BSP_ARM_INSN_H__ diff --git a/packages/cygmon/v2_0/misc/bsp/mn10300/singlestep.c b/packages/cygmon/v2_0/misc/bsp/mn10300/singlestep.c new file mode 100644 index 00000000..1273f5a8 --- /dev/null +++ b/packages/cygmon/v2_0/misc/bsp/mn10300/singlestep.c @@ -0,0 +1,55 @@ +//========================================================================== +// +// singlestep.c +// +// MN10300 specific single-step support. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-08-11 +// Purpose: MN10300 specific single-step support. +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Nothing now. +// We are using the eCos hal for single-stepping. +// FIXME: this file can be removed diff --git a/packages/cygmon/v2_0/misc/cpu-mon.c b/packages/cygmon/v2_0/misc/cpu-mon.c new file mode 100644 index 00000000..43cbb4f0 --- /dev/null +++ b/packages/cygmon/v2_0/misc/cpu-mon.c @@ -0,0 +1,61 @@ +//========================================================================== +// +// cpu-mon.c +// +// eCos BSP (for building Cygmon) +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas, dmoseley +// Date: 1999-10-11 +// Description: Architecture support for Cygmon +//####DESCRIPTIONEND#### + +#include // Configuration header + +#ifdef CYGPKG_HAL_ARM +#include "arm/arm-mon.c" +#endif + +#ifdef CYGPKG_HAL_MIPS +#include "mips/mips-mon.c" +#endif + +#ifdef CYGPKG_HAL_MN10300 +#include "mn10300/mn10300-mon.c" +#endif diff --git a/packages/cygmon/v2_0/misc/cpu_info.h b/packages/cygmon/v2_0/misc/cpu_info.h new file mode 100644 index 00000000..1a1700ac --- /dev/null +++ b/packages/cygmon/v2_0/misc/cpu_info.h @@ -0,0 +1,69 @@ +#ifndef __CYGMON_CPU_INFO_H__ +#define __CYGMON_CPU_INFO_H__ +//========================================================================== +// +// cpu_info.h +// +// Architecture specific information +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas, dmoseley +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= +#include +#include + +#ifdef CYGPKG_HAL_ARM +#include "arm/cpu_info.h" +#endif + +#ifdef CYGPKG_HAL_MIPS +#include "mips/cpu_info.h" +#endif + +#ifdef CYGPKG_HAL_MN10300 +#include "mn10300/cpu_info.h" +#endif +#endif // __CYGMON_CPU_INFO_H__ diff --git a/packages/cygmon/v2_0/misc/ecos_bsp.c b/packages/cygmon/v2_0/misc/ecos_bsp.c new file mode 100644 index 00000000..f6ee0fcd --- /dev/null +++ b/packages/cygmon/v2_0/misc/ecos_bsp.c @@ -0,0 +1,470 @@ +//========================================================================== +// +// ecos_bsp.c +// +// eCos BSP (for building Cygmon) +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas, dmoseley +// Date: 1999-10-11 +// Description: Wrapper functions which provide BSP environment for Cygmon +//####DESCRIPTIONEND#### + +#ifdef CYGPKG_KERNEL +#include // Configuration headers +#endif +#include +#include + +#include +#include +#ifdef CYGPKG_KERNEL +#include +#else +#include +#include +#endif +#include +#include "bsp/common/bsp_if.h" +#include +#include +#include CYGHWR_MEMORY_LAYOUT_H + +#include +#ifdef CYGPKG_IO +#include +#include +#endif + +#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM +static char stack[STACK_SIZE]; +#ifdef CYGPKG_KERNEL +static cyg_thread thread_data; +static cyg_handle_t thread_handle; +#endif + +char *build_date = __DATE__; + +extern void monitor_main(int, char *); +extern int stub_is_active; + +void ecos_bsp_set_memsize(unsigned long size); + +void +cygmon_main(void) +{ + _bsp_init(); + monitor_main(0, 0); // Null argument list +} + +extern unsigned long cygmon_memsize; + +externC void +cyg_start( void ) +{ + // Fill in the BSP memory info + if (cygmon_memsize != 0) + ecos_bsp_set_memsize(cygmon_memsize); + +#ifdef CYGPKG_KERNEL + // Create a main thread, so we can run the scheduler and have time 'pass' + cyg_thread_create(10, // Priority - just a number + (cyg_thread_entry_t*)cygmon_main, // entry + 0, // entry parameter + "Cygmon", // Name + &stack[0], // Stack + STACK_SIZE, // Size + &thread_handle, // Handle + &thread_data // Thread data structure + ); + cyg_thread_resume(thread_handle); // Start it + cyg_scheduler_start(); +#else +#ifdef HAL_ARCH_FUNCALL_NEW_STACK + HAL_ARCH_FUNCALL_NEW_STACK(cygmon_main, &stack[0], STACK_SIZE); +#else + #error Need to define HAL_ARCH_FUNCALL_NEW_STACK +#endif +#endif +} // cyg_package_start() + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +extern void *_hal_registers; // Used by eCos GDB stubs +extern void (*__init_vec)(void); +extern void (*__cleanup_vec)(void); +extern void __install_traps(void); +#endif + +extern int machine_syscall(HAL_SavedRegisters *regs); +void +_bsp_handle_exception(cyg_addrword_t data, cyg_code_t num, cyg_addrword_t info) +{ + if (num == CYGNUM_HAL_EXCEPTION_INTERRUPT) { + if (machine_syscall((HAL_SavedRegisters*)info)) { + return; + } + // Fall through to "normal" exception handling if system call failed + } +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + _hal_registers = (void *)info; // Used by eCos GDB stubs + __cleanup_vec(); +#endif + bsp_invoke_dbg_handler(num, (void *)info); +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + __init_vec(); +#endif +} + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +extern void __handle_exception(void); +#else + +int +unhandled_exception(int num, void *args) +{ + diag_printf("Unhandled exception: %d/%x\n", num, args); + while (1) ; +} +#endif + +void +_bsp_cpu_init(void) +{ +#ifdef CYGPKG_KERNEL + int d0; + cyg_exception_set_handler(CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, + _bsp_handle_exception, + (cyg_addrword_t)&d0, + 0, + 0); +#endif +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + bsp_install_dbg_handler((bsp_handler_t)__handle_exception); + __install_traps(); +#else + bsp_install_dbg_handler(unhandled_exception); +#endif +} + +#define FAIL() diag_printf("fail: %s\n", __FUNCTION__); while (1) ; + +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + +struct BSP_IO { + char *name; + cyg_io_handle_t chan; +}; + +static void +uart_putchar(void *base, char c) +{ + char buf; + int len; + struct BSP_IO *io = (struct BSP_IO *)base; + if (io->chan) { + len = 1; + buf = c; + cyg_io_write(io->chan, &buf, &len); + } +} + +extern int __output_gdb_string (const char *str, int string_len); + +// This function is mostly used by the 'write()' system call +static void +uart_write(void *base, const char *buf, int len) +{ + struct BSP_IO *io = (struct BSP_IO *)base; + if (io->chan) { + if (stub_is_active) { + // We are running in 'GDB' mode + __output_gdb_string(buf, len); + } else { + cyg_io_write(io->chan, buf, &len); + } + } +} + +static int +uart_read(void *base, char *buf, int len) +{ + struct BSP_IO *io = (struct BSP_IO *)base; + if (io->chan) { + cyg_io_read(io->chan, buf, &len); + return len; + } + return 0; +} + +static int +uart_getchar(void *base) +{ + char buf = '\0'; + int len; + struct BSP_IO *io = (struct BSP_IO *)base; + if (io->chan) { + len = 1; + cyg_io_read(io->chan, &buf, &len); + } + return buf; +} + +static int +uart_control(void *base, int func, ...) +{ + int rc = 0; + va_list ap; + int arg; + struct BSP_IO *io = (struct BSP_IO *)base; + + va_start(ap, func); + + if (func == COMMCTL_SETBAUD) + { + cyg_serial_info_t buffer = { + CYG_SERIAL_BAUD_DEFAULT, + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT + }; + int len = sizeof(buffer); + arg = va_arg(ap, int); + + switch (arg) + { + case 50: buffer.baud = CYG_SERIAL_BAUD_RATE(50); break; + case 75: buffer.baud = CYG_SERIAL_BAUD_RATE(75); break; + case 110: buffer.baud = CYG_SERIAL_BAUD_RATE(110); break; + case 134: buffer.baud = CYG_SERIAL_BAUD_RATE(134_5); break; + case 135: buffer.baud = CYG_SERIAL_BAUD_RATE(134_5); break; + case 150: buffer.baud = CYG_SERIAL_BAUD_RATE(150); break; + case 200: buffer.baud = CYG_SERIAL_BAUD_RATE(200); break; + case 300: buffer.baud = CYG_SERIAL_BAUD_RATE(300); break; + case 600: buffer.baud = CYG_SERIAL_BAUD_RATE(600); break; + case 1200: buffer.baud = CYG_SERIAL_BAUD_RATE(1200); break; + case 1800: buffer.baud = CYG_SERIAL_BAUD_RATE(1800); break; + case 2400: buffer.baud = CYG_SERIAL_BAUD_RATE(2400); break; + case 3600: buffer.baud = CYG_SERIAL_BAUD_RATE(3600); break; + case 4800: buffer.baud = CYG_SERIAL_BAUD_RATE(4800); break; + case 7200: buffer.baud = CYG_SERIAL_BAUD_RATE(7200); break; + case 9600: buffer.baud = CYG_SERIAL_BAUD_RATE(9600); break; + case 14400: buffer.baud = CYG_SERIAL_BAUD_RATE(14400); break; + case 19200: buffer.baud = CYG_SERIAL_BAUD_RATE(19200); break; + case 38400: buffer.baud = CYG_SERIAL_BAUD_RATE(38400); break; + case 57600: buffer.baud = CYG_SERIAL_BAUD_RATE(57600); break; + case 115200: buffer.baud = CYG_SERIAL_BAUD_RATE(115200); break; + case 230400: buffer.baud = CYG_SERIAL_BAUD_RATE(230400); break; + default: buffer.baud = -1; rc = -1; break; + } + + if ((io->chan) && (buffer.baud != -1)) { + rc = cyg_io_set_config(io->chan, CYG_IO_SET_CONFIG_SERIAL_INFO, &buffer, &len); + } + } + + va_end(ap); + return rc; +} + +/* + * Setup the bsp_comm_channel data structure + */ +struct BSP_IO bsp_comm_io[] = { + {CYGDAT_CYGMON_CONSOLE_DEV, 0}, // Console device +}; + +struct bsp_comm_channel _bsp_comm_list[] = +{ + { + { "UART 0", + BSP_COMM_SERIAL, + BSP_PROTO_NONE }, + { (void*)&bsp_comm_io[0], + uart_write, + uart_read, + uart_putchar, + uart_getchar, + uart_control } + }, +}; +int _bsp_num_comms = sizeof(_bsp_comm_list)/sizeof(_bsp_comm_list[0]); + +void +_bsp_init_board_comm(void) +{ + int i; + for (i = 0; i < _bsp_num_comms; i++) { + Cyg_ErrNo err; + struct BSP_IO *io; + io = (struct BSP_IO *)_bsp_comm_list[i].procs.ch_data; + if ((err = cyg_io_lookup(io->name, &io->chan)) != ENOERR) { + diag_printf("Can't open '%s'\n", io->name); + } + } +} + +#else // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + +struct bsp_comm_channel _bsp_comm_list[1]; +int _bsp_num_comms = 1; + +// Yuck! Two things need doing: + +// FIXME: Make bsp code use pointers in the bsp_comm_channel instead +// of sub-structures. + +// FIXME: Make HAL provide the bsp_comm_info structure - I missed that +// initially because it cannot be accessed via the virtual table API. +void +_bsp_init_board_comm(void) +{ + struct bsp_comm_channel* channel; + hal_virtual_comm_table_t* comm; + + channel = &_bsp_comm_list[0]; + channel->info.name = "fixme"; + channel->info.kind = BSP_COMM_SERIAL; + channel->info.protocol = BSP_PROTO_NONE; + + comm = CYGACC_CALL_IF_DEBUG_PROCS(); + channel->procs = *(struct bsp_comm_procs*)comm; +} +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + +/* + * Array of memory region descriptors. We just list RAM. + */ +#ifdef CYGMEM_REGION_ram +#define RAM_VIRTUAL_BASE CYGMEM_REGION_ram +#define RAM_TOTAL_SIZE CYGMEM_REGION_ram_SIZE +#else +#define RAM_VIRTUAL_BASE 0x00008000 +#define RAM_TOTAL_SIZE 0x00FF8000 +#endif + +struct bsp_mem_info _bsp_memory_list[] = +{ + { (void *)RAM_VIRTUAL_BASE, + (void *)RAM_VIRTUAL_BASE, + 0, + RAM_TOTAL_SIZE, + BSP_MEM_RAM + }, +}; + +/* + * Number of memory region descriptors. + */ +int _bsp_num_mem_regions = sizeof(_bsp_memory_list)/sizeof(_bsp_memory_list[0]); + +void +_bsp_install_cpu_irq_controllers(void) +{ +} + +void +_bsp_install_board_irq_controllers(void) +{ +} + +void +__init_irq_controllers(void) +{ +} + +void +_bsp_board_init(void) +{ + /* + * Define platform info. + */ +#ifdef HAL_PLATFORM_CPU + _bsp_platform_info.cpu = HAL_PLATFORM_CPU; +#else + _bsp_platform_info.cpu = "Unknown CPU"; +#endif +#ifdef HAL_PLATFORM_BOARD + _bsp_platform_info.board = HAL_PLATFORM_BOARD; +#else + _bsp_platform_info.board = "Unknown board"; +#endif +#ifdef HAL_PLATFORM_EXTRA + _bsp_platform_info.extra = HAL_PLATFORM_EXTRA; +#else + _bsp_platform_info.extra = ""; +#endif +} + +extern char *strchr(char *, char); +char * +index(char *string, char key) +{ + return strchr(string, key); +} + +void +flush_i_cache(void) +{ + HAL_ICACHE_SYNC(); +} + +void +ecos_bsp_console_putc(char c) +{ + if (bsp_shared_data) { + bsp_console_putc(c); + } +} + +char +ecos_bsp_console_getc(void) +{ + if (bsp_shared_data) { + return bsp_console_getc(); + } else { + return '?'; + } +} + +void +ecos_bsp_set_memsize(unsigned long size) +{ + _bsp_memory_list[0].nbytes = size; +} diff --git a/packages/cygmon/v2_0/misc/ecos_dummy.c b/packages/cygmon/v2_0/misc/ecos_dummy.c new file mode 100644 index 00000000..876d5270 --- /dev/null +++ b/packages/cygmon/v2_0/misc/ecos_dummy.c @@ -0,0 +1,70 @@ +//========================================================================== +// +// ecos_dummy.c +// +// eCos BSP (for building Cygmon) +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas, dmoseley +// Date: 1999-10-11 +// Description: Wrapper functions which provide BSP environment for Cygmon +//####DESCRIPTIONEND#### + +#ifdef CYGPKG_KERNEL +#include // Configuration header +#include +#endif +#include +#include + +// TEMP + +#define FAIL(n) \ +void n(void) \ +{ \ + diag_printf("Fail: %s\n", #n); \ + while (1) ; \ +} + +#ifndef CYGHWR_HAL_RESET_DEFINED + FAIL(bsp_reset) +#endif + + FAIL(_bsp_gdb_handler) + FAIL(_bsp_gdb_data) diff --git a/packages/cygmon/v2_0/misc/fmt_util.h b/packages/cygmon/v2_0/misc/fmt_util.h new file mode 100644 index 00000000..03a3fca2 --- /dev/null +++ b/packages/cygmon/v2_0/misc/fmt_util.h @@ -0,0 +1,65 @@ +#ifndef __FMT_UTIL_H__ +#define __FMT_UTIL_H__ +//========================================================================== +// +// fmt_util.g +// +// Interface to generic string parsing and formatting utilities. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +/* Interface to generic string parsing and formatting utilities. + + It is posible that these services need to be defined in + a platform dependent way. These will work for the majority of + processors. */ + +extern int str2addr (char *string, mem_addr_t *res); +extern void addr2str (mem_addr_t *addr, char *dest); + +#endif // __FMT_UTIL_H__ diff --git a/packages/cygmon/v2_0/misc/generic-stub.h b/packages/cygmon/v2_0/misc/generic-stub.h new file mode 100644 index 00000000..d6b44ec8 --- /dev/null +++ b/packages/cygmon/v2_0/misc/generic-stub.h @@ -0,0 +1,54 @@ +//========================================================================== +// +// generic-stub.h +// +// +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Placeholder diff --git a/packages/cygmon/v2_0/misc/generic_fmt32.c b/packages/cygmon/v2_0/misc/generic_fmt32.c new file mode 100644 index 00000000..26d21122 --- /dev/null +++ b/packages/cygmon/v2_0/misc/generic_fmt32.c @@ -0,0 +1,98 @@ +//========================================================================== +// +// generic_fmt32.c +// +// Generic address conversion routines +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Generic address conversion routines +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include +#ifdef HAVE_BSP +#include +#include +#endif +#include "monitor.h" +#include "fmt_util.h" + + +int +str2addr (char *string, mem_addr_t *res) +{ +#ifdef HAVE_ASI + if (string[0] == '[') + { + char *ptr = ++string; + while (*ptr && *ptr != ']') + ptr++; + + if (*ptr == 0) + return -1; + + *(ptr++) = 0; + res->asi = str2int (string, 16); + string = ptr; + } + else + res->asi = ASI_DEFAULT; +#endif + res->addr = str2int (string, 16); + return 0; +} + +void +addr2str (mem_addr_t *addr, char *dest) +{ +#ifdef HAVE_ASI + if (addr->asi != ASI_DEFAULT) + xsprintf(dest, "[%x]", addr->asi); + else +#endif + dest[0] = 0; + strcat (dest, int2str (addr->addr, 16, sizeof (void *) * 2)); +} diff --git a/packages/cygmon/v2_0/misc/generic_mem.c b/packages/cygmon/v2_0/misc/generic_mem.c new file mode 100644 index 00000000..76c6c866 --- /dev/null +++ b/packages/cygmon/v2_0/misc/generic_mem.c @@ -0,0 +1,99 @@ +//========================================================================== +// +// generic_mem.c +// +// Routines for reading and writing memory. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas, dmoseley +// Date: 1999-10-20 +// Purpose: +// Description: It may be appropriate to relay directly into the stubs +// implementation of read memory, without board specific +// considerations such as checking the allowed ranges of +// addresses. Perhaps there needs to be some consideration +// of address spaces or, masking addresses. +// +// This file implements a default version of reading and writing +// memory when none of this is an issue +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#ifdef HAVE_BSP +#include +#include "cpu_info.h" +#endif +#include "board.h" +#include "monitor.h" +#include "tservice.h" + +#ifndef HAVE_BSP +#include "generic-stub.h" +#endif + + +int +read_memory (mem_addr_t *src, int size, int amt, char *dst) +{ +#if defined(HAVE_BSP) && !defined(USE_ECOS_HAL_SAFE_MEMORY) + return (bsp_memory_read((unsigned char *)src->addr, MEM_ADDR_ASI(src), + size << 3, amt, dst) != amt); +#else + int totamt = size * amt; + return (totamt != __read_mem_safe (dst, (void*)src->addr, totamt)); +#endif +} + +int +write_memory (mem_addr_t *dst, int size, int amt, char *src) +{ +#if defined(HAVE_BSP) && !defined(USE_ECOS_HAL_SAFE_MEMORY) + return (bsp_memory_write((unsigned char *)dst->addr, MEM_ADDR_ASI(dst), + size << 3, amt, src) != amt); +#else + int totamt = size * amt; + return (totamt != __write_mem_safe (src, (void*)dst->addr, totamt)); +#endif +} + + + diff --git a/packages/cygmon/v2_0/misc/ledit.c b/packages/cygmon/v2_0/misc/ledit.c new file mode 100644 index 00000000..c2609d38 --- /dev/null +++ b/packages/cygmon/v2_0/misc/ledit.c @@ -0,0 +1,604 @@ +//========================================================================== +// +// ledit.c +// +// Utterly simple line editor +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Udderly simple line editor +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + + +#include +#include +#include +#ifdef HAVE_BSP +#include +#endif +#include "ledit.h" + +#ifndef NULL +#define NULL 0 +#endif + +static char *cutBuf = NULL; + +#ifdef NO_MALLOC +static char linebufArray [MAX_HIST_ENTS + 2][MAXLINELEN + 1]; +#endif + +static struct termcap +{ + char *relleft, *relright; + char *oneleft; + char *insertch; + char *deletech; + char *deleteonech; + char *clreol; + char *gobol; + int width; +} terminal; + +static struct linepos +{ + char *prompt; + char *buffer; + char *ebuf; + int cursor; +} linebuf; + +static struct history +{ + char *cmd; + struct history *next, *prev; +} *list = NULL, *topl = NULL, *curl = NULL; + +static int histlen = 0; +static int histLimit = MAX_HIST_ENTS; + +static struct history histEnts[MAX_HIST_ENTS + 1], *histPtr = histEnts; +static struct history currLine = { NULL, NULL, NULL }; + +void +beep (void) +{ + xputchar ('\007'); +} + +void +printHistoryList () +{ + struct history *hist = list; + int hist_num = 1; + + if (hist != NULL) + { + while (hist->prev != NULL) + { + hist = hist->prev; + } + + while (hist != NULL) + { + if (hist->cmd != NULL) + xprintf(" %d %s\n", hist_num++, hist->cmd); + hist = hist->next; + } + } +} + +static void +outputParamStr (char *str, int val) +{ + char *i = strchr (str, '%'); + char *ptr; + int dist = val; + + if (i == NULL) + { + while (dist-- > 0) + xprintf (str); + } + else + { + for (ptr = str; *ptr && ptr < i; ptr++) + xputchar (*ptr); + if (dist > 99) + { + xputchar ('0' + dist / 100); + dist = dist % 100; + } + if (dist > 9) + { + xputchar ('0' + dist / 10); + dist = dist % 10; + } + xputchar ('0' + dist); + if (*ptr) + xprintf (ptr + 1); + } +} + +static void +absMoveCursor (int pos) +{ + int dist, oldpos = linebuf.cursor; + int absdist; + char *bigmove; + + if (pos > (linebuf.ebuf - linebuf.buffer)) + { + beep (); + pos = linebuf.ebuf - linebuf.buffer; + } + else if (pos < 0) + pos = 0; + dist = pos - linebuf.cursor; + absdist = (dist < 0 ? -dist : dist); + linebuf.cursor = pos; + if (dist == 0) + return; + if (dist < 0) + bigmove = terminal.relleft; + else + bigmove = terminal.relright; + + if ((absdist < 4) || (bigmove == NULL)) + { + int x; + int promptLen = strlen (linebuf.prompt); + + if (pos < (absdist - promptLen)) + { + xprintf (terminal.gobol); + xprintf (linebuf.prompt); + for (x = 0; x < pos; x++) + xputchar (linebuf.buffer[x]); + return; + } + + if (dist < 0) + { + for (x = 0; x < -dist ;x++) + xprintf (terminal.oneleft); + } + else + { + for (x = 0; x < dist; x++) + xputchar (linebuf.buffer [oldpos + x]); + } + } + else + { + outputParamStr (bigmove, absdist); + } +} + +static void +clrScrToEol (void) +{ + int len = linebuf.ebuf - linebuf.buffer; + + if (len < linebuf.cursor) + return; + + if(terminal.clreol) + { + xprintf (terminal.clreol); + } + else if (terminal.deletech) + { + outputParamStr (terminal.deletech, len - linebuf.cursor); + } + else + { + int oldcur = linebuf.cursor; + while (linebuf.cursor < len) + { + xputchar (' '); + linebuf.cursor++; + } + + absMoveCursor (oldcur); + } +} + +static void +redrawCmd (void) +{ + xprintf (terminal.gobol); + xprintf (linebuf.prompt); + linebuf.buffer[linebuf.cursor] = 0; + xprintf (linebuf.buffer); + clrScrToEol (); +} + +static void +instCmd (char *ncmd) +{ + linebuf.cursor = strlen (ncmd); + strcpy (linebuf.buffer, ncmd); + redrawCmd (); + linebuf.ebuf = linebuf.buffer + linebuf.cursor; +} + +static void +prevCmd (void) +{ + if (curl == &currLine) + { + if (list != NULL) + { + *linebuf.ebuf = 0; +#ifdef NO_MALLOC + currLine.cmd = linebufArray[MAX_HIST_ENTS]; + strcpy (currLine.cmd, linebuf.buffer); +#else + if (currLine.cmd != NULL) + free (currLine.cmd); + currLine.cmd = strdup (linebuf.buffer); +#endif + curl = list; + } + } + else + { + if (curl->prev != NULL) + curl = curl->prev; + } + if (curl != NULL && curl->cmd != NULL) + instCmd (curl->cmd); + else + beep (); +} + +static void +nextCmd (void) +{ + if (curl->next == NULL) + { + beep (); + } + else + { + curl = curl->next; + instCmd (curl->cmd); + } + +} + +static int initted = 0; + +void +initVt100 (void) +{ + terminal.gobol = "\r"; + terminal.oneleft = "\010"; + terminal.relleft = "\033[%D"; + terminal.relright = "\033[%C"; + terminal.insertch = "\033[%@"; + terminal.deletech = "\033[%P"; + terminal.deleteonech = "\033[P"; + terminal.clreol = "\033[K"; + terminal.width = 80; + initted = 1; +} + +void +initDumb (void) +{ + terminal.gobol = "\r"; + terminal.oneleft = "\010"; + terminal.relleft = NULL; + terminal.relright = NULL; + terminal.insertch = NULL; + terminal.deletech = NULL; + terminal.deleteonech = NULL; + terminal.clreol = NULL; + terminal.width = 80; + initted = 1; +} + +static void +insertChar (char *chars, int num) +{ + int len = linebuf.ebuf - linebuf.buffer + strlen (linebuf.prompt); + int n = 0; + + if ((len + num) >= terminal.width) + { + beep (); + return; + } + if ((linebuf.ebuf - linebuf.buffer) > linebuf.cursor) + { + char *ptr, *eptr = linebuf.buffer + linebuf.cursor; + + for (ptr = linebuf.ebuf; ptr >= eptr; ptr--) + *(ptr+num) = *ptr; + + if (terminal.insertch != NULL) + outputParamStr (terminal.insertch, num); + } + for (n = 0; n < num; n++) + { + xputchar (*chars); + linebuf.buffer[linebuf.cursor++] = *(chars++); + } + + linebuf.ebuf += num; + + if (terminal.insertch == NULL) + { + char *ptr = linebuf.buffer + linebuf.cursor; + int oldcur = linebuf.cursor; + for (; ptr < linebuf.ebuf; ptr++) + xputchar (*ptr); + linebuf.cursor = linebuf.ebuf - linebuf.buffer; + absMoveCursor (oldcur); + } +} + +static void +deleteEol (int putInCutBuffer) +{ + int len = linebuf.ebuf - linebuf.buffer; + if (linebuf.cursor < len) + { + clrScrToEol (); + + if (putInCutBuffer) + { + *linebuf.ebuf = 0; +#ifdef NO_MALLOC + cutBuf = linebufArray[MAX_HIST_ENTS + 1]; + strcpy (cutBuf, linebuf.buffer + linebuf.cursor); +#else + if (cutBuf != NULL) + free (cutBuf); + cutBuf = strdup (linebuf.buffer + linebuf.cursor); +#endif + } + linebuf.ebuf = linebuf.buffer + linebuf.cursor; + } +} + +static void +deleteCurrChar (void) +{ + int len = linebuf.ebuf - linebuf.buffer; + char *ptr; + if (len == linebuf.cursor || len == 0) + return; + for (ptr = linebuf.buffer + linebuf.cursor; ptr < (linebuf.ebuf - 1); ptr++) + { + *ptr = *(ptr + 1); + if (terminal.deleteonech == NULL) + xputchar (*ptr); + } + linebuf.ebuf--; + if (terminal.deleteonech && (len - 1) != linebuf.cursor) + xprintf (terminal.deleteonech); + else + { + int oldcur = linebuf.cursor; + xputchar (' '); + linebuf.cursor = linebuf.ebuf - linebuf.buffer + 1; + absMoveCursor (oldcur); + } +} + +static void +deleteChar (void) +{ + if (linebuf.cursor == 0) + { + beep (); + return; + } + absMoveCursor (linebuf.cursor - 1); + deleteCurrChar (); +} + +int +lineedit (char *prompt, char *buffer, int maxLen) +{ + int c; + + curl = &currLine; + + if (!initted) + { + initted = 1; + /*initVt100 ();*/ + initDumb(); + } + linebuf.prompt = prompt; + linebuf.buffer = buffer; + linebuf.ebuf = buffer; + buffer[0] = 0; + linebuf.cursor = 0; + redrawCmd (); + while ((c=input_char ()) > 0) + { + switch (c) + { + case PREVCMD: + prevCmd (); + break; + case NEXTCMD: + nextCmd (); + break; + case LF: + case CR: + *linebuf.ebuf = 0; +#ifdef NO_MALLOC + cutBuf = NULL; + currLine.cmd = NULL; +#else + if (cutBuf != NULL) + { + free (cutBuf); + cutBuf = NULL; + } + if (currLine.cmd != NULL) + { + free (currLine.cmd); + currLine.cmd = NULL; + } +#endif + return linebuf.ebuf - linebuf.buffer; + break; + case BOLCMD: + absMoveCursor (0); + break; + case EOLCMD: + absMoveCursor (linebuf.ebuf-linebuf.buffer); + break; + case FORWCMD: + absMoveCursor (linebuf.cursor + 1); + break; + case BACKCMD: + absMoveCursor (linebuf.cursor - 1); + break; + case DELBACK: + case '\177': + deleteChar (); + break; + case ERASELINE: + absMoveCursor (0); + deleteEol (0); + break; + case DELEOL: + deleteEol (1); + break; + case DELCURRCH: + deleteCurrChar (); + break; + case YANKCH: + if (cutBuf != NULL) + insertChar (cutBuf,strlen (cutBuf)); + break; + default: + if (c >= 32 && c < 127) + { + char ch = c; + insertChar (&ch, 1); + } + break; + } + } + return -1; +} + +void +addHistoryCmd (char *cmd) +{ + struct history *newent = NULL; + + if (histlen >= histLimit) + { + newent = topl; + topl = topl->next; + topl->prev = NULL; +#ifdef NO_MALLOC + newent->prev = NULL; + newent->next = NULL; +#else + free (newent->cmd); + newent->cmd = NULL; +#endif + histlen = histLimit - 1; + } + + histlen++; + + if (newent == NULL) + { + newent = histPtr++; +#ifdef NO_MALLOC + newent->cmd = linebufArray[histlen - 1]; +#endif + } + + if (list == NULL) + { + list = newent; + list->prev = NULL; + topl = list; + } + else + { + list->next = newent; + list->next->prev = list; + list = list->next; + } + currLine.prev = list; + list->next = &currLine; +#ifdef NO_MALLOC + strcpy (list->cmd, cmd); +#else + list->cmd = strdup (cmd); +#endif + curl = &currLine; +} + +void +set_term_name (char *name) +{ + if (! strcmp (name, "vt100")) + { + initVt100 (); + } + else if (! strcmp (name, "dumb")) + { + initDumb (); + } + else + { + xprintf ("Unknown terminal name %s\n", name); + } +} diff --git a/packages/cygmon/v2_0/misc/ledit.h b/packages/cygmon/v2_0/misc/ledit.h new file mode 100644 index 00000000..083eeff8 --- /dev/null +++ b/packages/cygmon/v2_0/misc/ledit.h @@ -0,0 +1,88 @@ +//========================================================================== +// +// ledit.h +// +// Header for the utterly simple line editor +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Header for the udderly simple line editor +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#ifndef LEDIT_H +#define LEDIT_H + +#define LF '\n' +#define CR '\r' +#define BOLCMD '\001' +#define EOLCMD '\005' +#define FORWCMD '\006' +#define BACKCMD '\002' +#define DELBACK '\010' +#define DELEOL '\013' +#define YANKCH '\031' +#define DELCURRCH '\004' +#define PREVCMD '\020' +#define ERASELINE '\025' +#define NEXTCMD '\016' + +/* Prompt for one line of input using PROMPT. The input from the user + (up to MAXINPLEN characters) will be stored in BUFFER. The number + of characters read will be returned. */ +extern int lineedit(char *prompt, char *buffer, int maxInpLen); + +/* Add CMD to the user's command history. */ +extern void addHistoryCmd (char *cmd); + +/* Configure the editor to use the specified terminal. */ +extern void set_term_name (char *name); + +/* Beep the terminal. */ +extern void beep (void); + +/* Print a history list. */ +extern void printHistoryList(void); + +#endif diff --git a/packages/cygmon/v2_0/misc/mips/board.h b/packages/cygmon/v2_0/misc/mips/board.h new file mode 100644 index 00000000..fff5918d --- /dev/null +++ b/packages/cygmon/v2_0/misc/mips/board.h @@ -0,0 +1,110 @@ +#ifndef __CYGMON_MIPS_BOARD_H__ +#define __CYGMON_MIPS_BOARD_H__ +//========================================================================== +// +// board.h +// +// Cygmon board/platform configuration file +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-07-11 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= +// Hardware/platform/configuration specifics + +// These defines are only necessary for using target_reg union in monitor.h +// It should be possible to remove that once the HAL integration is complete. +#define HAVE_FLOAT_REGS 0 +#define HAVE_DOUBLE_REGS 0 + +#define HAVE_CACHE 0 +#define HAVE_USAGE 0 +#define USE_CYGMON_PROTOTYPES 1 +#define NOMAIN 1 +#define CYGMON_SYSTEM_SERVICES 0 // Not used, fall back to BSP/HAL support + +#ifdef CYGDAT_CYGMON_USE_HELP +#define USE_HELP 1 +#endif + +#define USE_ECOS_HAL_EXCEPTIONS +#define USE_ECOS_HAL_BREAKPOINTS +#define USE_ECOS_HAL_SINGLESTEP + +#include "cpu_info.h" +extern void bp_print (target_register_t bp_val); +extern int __set_breakpoint (target_register_t addr); +extern int __remove_breakpoint (target_register_t addr); +extern void __install_breakpoint_list (void); +extern void __clear_breakpoint_list (void); +extern int __display_breakpoint_list (void (*print_func)(target_register_t)); + +#define bsp_skip_instruction(regs) __skipinst() +#define install_breakpoints() __install_breakpoints() +#define add_mon_breakpoint(bpt) __set_breakpoint((bpt).addr) +#define clear_mon_breakpoint(bpt) __remove_breakpoint((bpt).addr) +#define show_breakpoints() __display_breakpoint_list(bp_print) +#define clear_breakpoints() __clear_breakpoint_list() + +#define bsp_get_signal(exc_nr, regs) __computeSignal(exc_nr) +#define bsp_get_pc(regs) get_register(PC) + +#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS +#include +#include "monitor.h" + +#ifdef __mips64 +#define bsp_set_pc(pc, regs) \ + put_register(PC, pc); \ + if (regs->_sr & SR_ERL) \ + put_register(EPC, pc); \ + else \ + put_register(EEPC, pc); +#else +#define bsp_set_pc(pc, regs) \ + put_register(PC, pc); +#endif + +#endif // __CYGMON_MIPS_BOARD_H__ diff --git a/packages/cygmon/v2_0/misc/mips/cpu.h b/packages/cygmon/v2_0/misc/mips/cpu.h new file mode 100644 index 00000000..e746a2ac --- /dev/null +++ b/packages/cygmon/v2_0/misc/mips/cpu.h @@ -0,0 +1,59 @@ +#ifndef __MIPS_CPU_H__ +#define __MIPS_CPU_H__ +//========================================================================== +// +// cpu.h +// +// MIPS specific processor defines +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-06-07 +// Purpose: MIPS specific processor defines +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include + +#define BSP_MAX_EXCEPTIONS CYGNUM_HAL_VSR_COUNT + +#endif // __MIPS_CPU_H__ diff --git a/packages/cygmon/v2_0/misc/mips/cpu_info.h b/packages/cygmon/v2_0/misc/mips/cpu_info.h new file mode 100644 index 00000000..adf6d705 --- /dev/null +++ b/packages/cygmon/v2_0/misc/mips/cpu_info.h @@ -0,0 +1,90 @@ +#ifndef __MIPS_CPU_INFO_H__ +#define __MIPS_CPU_INFO_H__ +//========================================================================== +// +// cpu_info.h +// +// Architecture information for MIPS processors +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-06-07 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#define IS_MIPS 1 + +/* Temporary as long a multiple protypes are copied in multiple files */ +/* This variation does NOT clone the prototypes */ +#define NO_MALLOC 1 + +#ifndef USE_ECOS_HAL_BREAKPOINTS + +/* big enuf to store a trap in the BP structure */ + +#define BP_INST_T_DEFINED 1 +typedef unsigned int bp_inst_t ; + +#else /* USE_ECOS_HAL_BREAKPOINTS */ + +#define MEM_ADDR_DEFINED 1 +typedef struct mem_addr { + unsigned long addr; +} mem_addr_t ; + +#endif /* USE_ECOS_HAL_BREAKPOINTS */ + +typedef unsigned long target_register_t; + +#include +#include +#if CYG_BYTEORDER == CYG_MSBFIRST +#define PRINT_INSN print_insn_big_mips +#else +#define PRINT_INSN print_insn_little_mips +#endif + +#undef BFD_MACH +#define BFD_MACH 0 + +#endif // __MIPS_CPU_INFO_H__ diff --git a/packages/cygmon/v2_0/misc/mips/mips-mon.c b/packages/cygmon/v2_0/misc/mips/mips-mon.c new file mode 100644 index 00000000..ab6067ca --- /dev/null +++ b/packages/cygmon/v2_0/misc/mips/mips-mon.c @@ -0,0 +1,183 @@ +//========================================================================== +// +// mips-mon.c +// +// Support code to extend the generic monitor code to support +// MIPS processors. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-06-07 +// Purpose: Support code to extend the generic monitor code to support +// MIPS(R) processors. +// Description: Further board specific support is in other files. +// This file contains: +// register names lookup table +// +// Empty Stubs: +// Interval timer - This should really belong to the application +// operating system. +// +// Should not contain: +// low level uart getchar and putchar functions +// delay function to support uart +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include "monitor.h" + +struct regstruct regtab[] = +{ + { "zero", REG_ZERO }, + { "at", REG_AT }, + { "v0", REG_V0 }, + { "v1", REG_V1 }, + { "a0", REG_A0 }, + { "a1", REG_A1 }, + { "a2", REG_A2 }, + { "a3", REG_A3 }, + { "t0", REG_T0 }, + { "t1", REG_T1 }, + { "t2", REG_T2 }, + { "t3", REG_T3 }, + { "t4", REG_T4 }, + { "t5", REG_T5 }, + { "t6", REG_T6 }, + { "t7", REG_T7 }, + { "s0", REG_S0 }, + { "s1", REG_S1 }, + { "s2", REG_S2 }, + { "s3", REG_S3 }, + { "s4", REG_S4 }, + { "s5", REG_S5 }, + { "s6", REG_S6 }, + { "s7", REG_S7 }, + { "t8", REG_T8 }, + { "t9", REG_T9 }, + { "k0", REG_K0 }, + { "k1", REG_K1 }, + { "gp", REG_GP }, + { "sp", REG_SP }, + { "s8", REG_S8 }, + { "ra", REG_RA }, + + { "sr", REG_SR }, + { "lo", REG_LO }, + { "hi", REG_HI }, + { "badvr", REG_BAD }, + { "cause", REG_CAUSE }, + { "pc", REG_PC }, +#ifdef CYGHWR_HAL_MIPS_FPU + { "f0", REG_F0 }, + { "f1", REG_F1 }, + { "f2", REG_F2 }, + { "f3", REG_F3 }, + { "f4", REG_F4 }, + { "f5", REG_F5 }, + { "f6", REG_F6 }, + { "f7", REG_F7 }, + { "f8", REG_F8 }, + { "f9", REG_F9 }, + { "f10", REG_F10 }, + { "f11", REG_F11 }, + { "f12", REG_F12 }, + { "f13", REG_F13 }, + { "f14", REG_F14 }, + { "f15", REG_F15 }, + { "f16", REG_F16 }, + { "f17", REG_F17 }, + { "f18", REG_F18 }, + { "f19", REG_F19 }, + { "f20", REG_F20 }, + { "f21", REG_F21 }, + { "f22", REG_F22 }, + { "f23", REG_F23 }, + { "f24", REG_F24 }, + { "f25", REG_F25 }, + { "f26", REG_F26 }, + { "f27", REG_F27 }, + { "f28", REG_F28 }, + { "f29", REG_F29 }, + { "f30", REG_F30 }, + { "f31", REG_F31 }, + { "fcr31", REG_FCR31 }, +#endif /* CYGHWR_HAL_MIPS_FPU */ + { 0, 0 }, /* Terminating element must be last */ +} ; + +void +initialize_mon(void) +{ +} /* initialize_mon */ + + +#include +#include +int +machine_syscall(HAL_SavedRegisters *regs) +{ + int res, err; + target_register_t a0, a1, a2, a3; + + a0 = get_register(REG_A0); + a1 = get_register(REG_A1); + a2 = get_register(REG_A2); + a3 = get_register(REG_A3); + + err = _bsp_do_syscall(a0, // Function + a1, a2, a3, 0, // arguments, + &res); + if (err) + { + // This was a syscall. It has now been handled, so update the registers appropriately + put_register(REG_V0, res); + bsp_skip_instruction(regs); + } + + return err; +} + + +// Utility function for printing breakpoints +void bp_print(target_register_t bp_val) +{ + bsp_printf("0x%08lx\n", (unsigned long)bp_val); +} diff --git a/packages/cygmon/v2_0/misc/mn10300/board.h b/packages/cygmon/v2_0/misc/mn10300/board.h new file mode 100644 index 00000000..19b6ba12 --- /dev/null +++ b/packages/cygmon/v2_0/misc/mn10300/board.h @@ -0,0 +1,103 @@ +#ifndef __CYGMON_MN10300_BOARD_H__ +#define __CYGMON_MN10300_BOARD_H__ +//========================================================================== +// +// board.h +// +// Cygmon board/platform configuration file +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-08-11 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= +// Hardware/platform/configuration specifics + +// These defines are only necessary for using target_reg union in monitor.h +// It should be possible to remove that once the HAL integration is complete. +#if CYGHWR_HAL_MN10300_AM33_REVISION == 2 +#define HAVE_FLOAT_REGS 1 +#else +#define HAVE_FLOAT_REGS 0 +#endif +#define HAVE_DOUBLE_REGS 0 + +#define HAVE_CACHE 0 +#define HAVE_USAGE 0 +#define USE_CYGMON_PROTOTYPES 1 +#define NOMAIN 1 +#define CYGMON_SYSTEM_SERVICES 0 // Not used, fall back to BSP/HAL support + +#ifdef CYGDAT_CYGMON_USE_HELP +#define USE_HELP 1 +#endif + +#define USE_ECOS_HAL_EXCEPTIONS +#define USE_ECOS_HAL_BREAKPOINTS +#define USE_ECOS_HAL_SINGLESTEP +#define USE_ECOS_HAL_SAFE_MEMORY +extern int __read_mem_safe (void *dst, void *src, int count); +extern int __write_mem_safe (void *src, void *dst, int count); + + +#include "cpu_info.h" +extern void bp_print (target_register_t bp_val); +extern int __set_breakpoint (target_register_t addr); +extern int __remove_breakpoint (target_register_t addr); +extern void __install_breakpoint_list (void); +extern void __clear_breakpoint_list (void); +extern int __display_breakpoint_list (void (*print_func)(target_register_t)); + +#define bsp_skip_instruction(regs) __skipinst() +#define install_breakpoints() __install_breakpoints() +#define add_mon_breakpoint(bpt) __set_breakpoint((bpt).addr) +#define clear_mon_breakpoint(bpt) __remove_breakpoint((bpt).addr) +#define show_breakpoints() __display_breakpoint_list(bp_print) +#define clear_breakpoints() __clear_breakpoint_list() + +#define bsp_get_signal(exc_nr, regs) __computeSignal(exc_nr) +#define bsp_get_pc(regs) get_register(PC) +#define bsp_set_pc(pc, regs) put_register(PC, pc); + +#endif // __CYGMON_MN10300_BOARD_H__ diff --git a/packages/cygmon/v2_0/misc/mn10300/cpu.h b/packages/cygmon/v2_0/misc/mn10300/cpu.h new file mode 100644 index 00000000..ae8a50d8 --- /dev/null +++ b/packages/cygmon/v2_0/misc/mn10300/cpu.h @@ -0,0 +1,61 @@ +#ifndef __MN10300_CPU_H__ +#define __MN10300_CPU_H__ +//========================================================================== +// +// cpu.h +// +// MN10300 specific processor defines +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-08-11 +// Purpose: MN10300 specific processor defines +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include + +#define BSP_MAX_EXCEPTIONS CYGNUM_HAL_VSR_COUNT + +#define REG_PC PC + +#endif // __MN10300_CPU_H__ diff --git a/packages/cygmon/v2_0/misc/mn10300/cpu_info.h b/packages/cygmon/v2_0/misc/mn10300/cpu_info.h new file mode 100644 index 00000000..000c8af3 --- /dev/null +++ b/packages/cygmon/v2_0/misc/mn10300/cpu_info.h @@ -0,0 +1,91 @@ +#ifndef __MN10300_CPU_INFO_H__ +#define __MN10300_CPU_INFO_H__ +//========================================================================== +// +// cpu_info.h +// +// Architecture information for MN10300 processors +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-08-11 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#define IS_MN10300 1 + +/* Temporary as long a multiple protypes are copied in multiple files */ +/* This variation does NOT clone the prototypes */ +#define NO_MALLOC 1 + +#ifndef USE_ECOS_HAL_BREAKPOINTS + +/* big enuf to store a trap in the BP structure */ + +#define BP_INST_T_DEFINED 1 +typedef unsigned char bp_inst_t ; + +#else /* USE_ECOS_HAL_BREAKPOINTS */ + +#define MEM_ADDR_DEFINED 1 +typedef struct mem_addr { + unsigned long addr; +} mem_addr_t ; + +#endif /* USE_ECOS_HAL_BREAKPOINTS */ + +typedef unsigned long target_register_t; + +#include +#include +#define PRINT_INSN print_insn_mn10300 + +#undef BFD_MACH +#define BFD_MACH 0 + +// Ensure that the reg_valid field in regstruct is used. +#define REG_VALID_FIELD_IN_REGSTRUCT +#define INITIALIZE_MON_EACH_TIME() initialize_mon_each_time() +extern void initialize_mon_each_time(void); + +#endif // __MN10300_CPU_INFO_H__ diff --git a/packages/cygmon/v2_0/misc/mn10300/mn10300-mon.c b/packages/cygmon/v2_0/misc/mn10300/mn10300-mon.c new file mode 100644 index 00000000..205c7f65 --- /dev/null +++ b/packages/cygmon/v2_0/misc/mn10300/mn10300-mon.c @@ -0,0 +1,206 @@ +//========================================================================== +// +// mn10300-mon.c +// +// Support code to extend the generic monitor code to support +// MN10300 processors. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dmoseley +// Contributors: dmoseley +// Date: 2000-08-11 +// Purpose: Support code to extend the generic monitor code to support +// MN10300 processors. +// Description: Further board specific support is in other files. +// This file contains: +// register names lookup table +// +// Empty Stubs: +// Interval timer - This should really belong to the application +// operating system. +// +// Should not contain: +// low level uart getchar and putchar functions +// delay function to support uart +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include "monitor.h" + +struct regstruct regtab[] = +{ + {"d0", D0, 1}, + {"d1", D1, 1}, + {"d2", D2, 1}, + {"d3", D3, 1}, + {"a0", A0, 1}, + {"a1", A1, 1}, + {"a2", A2, 1}, + {"a3", A3, 1}, + {"sp", SP, 1}, + {"pc", PC, 1}, + {"mdr", MDR, 1}, + {"psw", PSW, 1}, + {"lir", LIR, 1}, + {"lar", LAR, 1}, +#ifdef CYGPKG_HAL_MN10300_AM33 + {"r0", R0, 1}, + {"r1", R1, 1}, + {"r2", R2, 1}, + {"r3", R3, 1}, + {"r4", R4, 1}, + {"r5", R5, 1}, + {"r6", R6, 1}, + {"r7", R7, 1}, + {"ssp", SSP, 1}, + {"msp", MSP, 1}, + {"usp", USP, 1}, + {"mcrh", MCRH, 1}, + {"mcrl", MCRL, 1}, + {"mcvf", MCVF, 1}, + {"mdrq", MDRQ, 1}, +#if CYGHWR_HAL_MN10300_AM33_REVISION == 2 + {"fpcr", FPCR, 1}, + {"fs0", FS0, 1}, + {"fs1", FS1, 1}, + {"fs2", FS2, 1}, + {"fs3", FS3, 1}, + {"fs4", FS4, 1}, + {"fs5", FS5, 1}, + {"fs6", FS6, 1}, + {"fs7", FS7, 1}, + {"fs8", FS8, 1}, + {"fs9", FS9, 1}, + {"fs10", FS10, 1}, + {"fs11", FS11, 1}, + {"fs12", FS12, 1}, + {"fs13", FS13, 1}, + {"fs14", FS14, 1}, + {"fs15", FS15, 1}, + {"fs16", FS16, 1}, + {"fs17", FS17, 1}, + {"fs18", FS18, 1}, + {"fs19", FS19, 1}, + {"fs20", FS20, 1}, + {"fs21", FS21, 1}, + {"fs22", FS22, 1}, + {"fs23", FS23, 1}, + {"fs24", FS24, 1}, + {"fs25", FS25, 1}, + {"fs26", FS26, 1}, + {"fs27", FS27, 1}, + {"fs28", FS28, 1}, + {"fs29", FS29, 1}, + {"fs30", FS30, 1}, + {"fs31", FS31, 1}, +#endif +#endif + { 0, 0, 1}, /* Terminating element must be last */ +} ; + +void +initialize_mon(void) +{ +} /* initialize_mon */ + +#if CYGHWR_HAL_MN10300_AM33_REVISION == 2 +extern int fpu_regs_read; +#endif + +#ifdef CYGPKG_HAL_MN10300_AM33 +extern int msp_read; +#endif + +void +initialize_mon_each_time(void) +{ + int i; +#if CYGHWR_HAL_MN10300_AM33_REVISION == 2 + // Make sure the regtab[] indicates the valid status of the FPU registers + for (i = 0; regtab[i].registername != NULL; i++) + { + if ((regtab[i].registernumber >= FP_START) && (regtab[i].registernumber <= FP_END)) + regtab[i].registervalid = fpu_regs_read; + } +#endif + +#ifdef CYGPKG_HAL_MN10300_AM33 + // Make sure the regtab[] indicates the valid status of the MSP + for (i = 0; regtab[i].registername != NULL; i++) + { + if (regtab[i].registernumber == MSP) + regtab[i].registervalid = msp_read; + } +#endif +} /* initialize_mon_each_time */ + + +#include +#include +int +machine_syscall(HAL_SavedRegisters *regs) +{ + int res, err; + target_register_t d0, d1, d2, d3; + + d0 = get_register(D0); + d1 = get_register(D1); + d2 = get_register(D2); + d3 = get_register(D3); + + err = _bsp_do_syscall(d0, // Function + d1, d2, d3, 0, // arguments, + &res); + if (err) + { + // This was a syscall. It has now been handled, so update the registers appropriately + put_register(D0, res); + bsp_skip_instruction(regs); + } + + return err; +} + + +// Utility function for printing breakpoints +void bp_print(target_register_t bp_val) +{ + bsp_printf("0x%08lx\n", (unsigned long)bp_val); +} diff --git a/packages/cygmon/v2_0/misc/monitor.c b/packages/cygmon/v2_0/misc/monitor.c new file mode 100644 index 00000000..06c04ae9 --- /dev/null +++ b/packages/cygmon/v2_0/misc/monitor.c @@ -0,0 +1,494 @@ +//========================================================================== +// +// monitor.c +// +// Monitor shell and main routines for CygMON the Wonder Monitor +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas, dmoseley +// Date: 1999-10-20 +// Purpose: Monitor shell and main routines for CygMON the Wonder Monitor +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +/* Platform-independent code for cygmon */ + +#include +#include +#ifdef HAVE_BSP +#include +#include +#include +#endif +#include +#ifdef HAVE_BSP +#include "cpu_info.h" +#endif +#include +#include +#include +#include + +#if USE_CYGMON_PROTOTYPES +/* Use common prototypes */ +/* Some of the composed board.h files compose these + prototypes redundently, but if they dont, + these are the common definitions */ +#include "fmt_util.h" /* Interface to string formatting utilities */ +#include "tservice.h" /* Interface to target specific services */ +#include "generic-stub.h" /* from libstub */ +#endif /* USE_CYGMON_PROTOTYPES */ + +static int cygmon_handle_exception (int sigval); +static void monitor_take_control (void); + +#if CYGMON_SYSTEM_SERVICES +extern int process_syscall (int syscall_num); +#elif defined (USE_ECOS_HAL_EXCEPTIONS) +static int cygmon_process_syscall (int sigval); +#endif + +int stub_is_active = 0; +mem_addr_t last_pc; + +#ifdef HAVE_BSP + +#if !defined(USE_ECOS_HAL_EXCEPTIONS) +static int mon_dbg_handler(int exc_nr, void *regs); +static int mon_kill_handler(int exc_nr, void *regs); +#endif // USE_ECOS_HAL_EXCEPTIONS + +#ifndef USE_ECOS_HAL_BREAKPOINTS +#define __is_breakpoint_function() (get_pc() == (target_register_t)bsp_breakinsn) +#endif + +#ifdef __ECOS__ +/* + * This global flag is used by generic-stub.c to communicate to us that we + * are processing the breakpoint function within Cygmon itself. + */ +extern int processing_breakpoint_function; +#endif + +/* Global pointer to current set of saved registers. */ +void *mon_saved_regs; + +/* Original BSP debug vector replaced by monitor. */ +#if !defined(USE_ECOS_HAL_EXCEPTIONS) +static bsp_handler_t old_dbg_vec; +#endif // !defined(USE_ECOS_HAL_EXCEPTIONS) + +#else +static int handle_signal (int signal_val); + +__PFI user_signal_handler = NULL; +#endif + +#if defined(__ECOS__) +#include +#endif + +#if defined(__ECOS__) && !defined(PROCESS_EXCEPTION_VEC_PROTOTYPE_EXISTS) +#define PROCESS_EXCEPTION_VEC_PROTOTYPE_EXISTS +extern volatile __PFI (*__process_exception_vec)(int); +#endif + + +#ifdef MONITOR_CONTROL_INTERRUPTS +/* This is set if the user wants interrupts enabled in the monitor. */ +static int monitor_interrupts_enabled; +#endif + + +#if NOMAIN +int monitor_main (int argc, char **argv) /* Suppress default main() junk */ +#else +int main (int argc, char **argv) +#endif +{ +#ifdef HAVE_BSP + int cur_port; + struct bsp_comm_info comm_info; +#else + /* Set up exception handling traps */ + initialize_stub (); +#endif + + initialize_mon (); + +#ifdef HAVE_BSP + /* get info on debug channel */ + cur_port = bsp_set_debug_comm(-1); + bsp_sysinfo(BSP_INFO_COMM, cur_port, &comm_info); + + /* + * If we're using a network interface, don't install + * the cygmon vectors. Currently, we only support stub + * mode over a network connection. + */ + if (comm_info.kind != BSP_COMM_ENET) + { + xprintf("\n"); + version (); + + /* replace original BSP debug and kill handler with ours */ +#if !defined(USE_ECOS_HAL_EXCEPTIONS) + old_dbg_vec = bsp_install_dbg_handler(mon_dbg_handler); + (void)bsp_install_kill_handler(mon_kill_handler); +#else + /* replace original BSP debug and kill handler with ours using eCos stuff */ + __process_exception_vec = (__PFI)cygmon_handle_exception; + __process_syscall_vec = cygmon_process_syscall; + __process_exit_vec = monitor_take_control; +#endif // __ECOS__ + } + else + { + /* This forces the console to use the gdb channel. */ + bsp_set_console_comm(cur_port); + } +#else + xprintf("\n"); + version (); + + __process_exception_vec = cygmon_handle_exception; + __process_exit_vec = monitor_take_control; +#if CYGMON_SYSTEM_SERVICES + __process_syscall_vec = process_syscall; +#endif + __process_signal_vec = handle_signal; + __init_vec = install_breakpoints; + __cleanup_vec = clear_breakpoints; +#endif + +#if 0 +#ifdef __ECOS__ + __process_exception_vec = cygmon_handle_exception; +#endif +#endif + + while (1) + { + breakpoint (); + if (switch_to_stub_flag) + { + xprintf("Switching to stub\n"); + switch_to_stub_flag = 0; + } + } + + /* never reached */ + exit (0); +} + + +/* Transfer control to gdb stub */ + +int +transfer_to_stub () +{ + /* Return back to the exception handler, but the exception handler + should invoke the stub's exception handler instead of ours. */ +#if defined(HAVE_BSP) && !defined(USE_ECOS_HAL_EXCEPTIONS) + (void)bsp_install_dbg_handler(old_dbg_vec); +#else + __switch_to_stub (); +#endif + + /* The stub is now active. */ + stub_is_active = 1; + return -1; +} + +void +clear_user_state (void) +{ +#ifdef HAS_TIMER + if (__timer_enabled ()) + __settimer (0, 0); +#endif + + clear_breakpoints (); + +#ifndef HAVE_BSP + user_signal_handler = NULL; +#endif + + __clear_single_step (); +} + +static void +monitor_take_control (void) +{ + stub_is_active = 0; + switch_to_stub_flag = 0; + + // Flush the unget state. This is because the ecos stub and Cygmon track this + // stuff separately. + bsp_debug_ungetc('\0'); + +#ifdef INITIALIZE_MON_EACH_TIME + // Call the per-stop initialization routine if it is defined. + INITIALIZE_MON_EACH_TIME(); +#endif + +#if defined(HAVE_BSP) && !defined(USE_ECOS_HAL_EXCEPTIONS) + /* replace original BSP debug trap handler with ours */ + (void)bsp_install_dbg_handler(mon_dbg_handler); +#else + clear_user_state (); + __process_exception_vec = cygmon_handle_exception; +#endif +} + + +#ifdef MONITOR_CONTROL_INTERRUPTS +void +monitor_enable_interrupts (void) +{ + monitor_interrupts_enabled = 1; + enable_interrupts (); +} + +void +monitor_disable_interrupts (void) +{ + monitor_interrupts_enabled = 0; + disable_interrupts (); +} + +int +monitor_interrupt_state (void) +{ + return monitor_interrupts_enabled; +} +#endif + +#if defined(USE_ECOS_HAL_EXCEPTIONS) +externC HAL_SavedRegisters *_hal_registers; +extern int machine_syscall(HAL_SavedRegisters *regs); +static int +cygmon_process_syscall (int sigval) +{ + return machine_syscall(_hal_registers); +} +#endif + +static int +cygmon_handle_exception (int sigval) +{ + target_register_t pc; + +#ifdef MONITOR_CONTROL_INTERRUPTS + if (monitor_interrupts_enabled) + { + if (! __in_interrupt) + enable_interrupts (); + } +#endif + +#ifdef TARGET_EXCEPTION_CODE + TARGET_EXCEPTION_CODE +#endif + +#ifndef HAVE_BSP + if (sigval != SIGKILL) + if (handle_signal (sigval) == 0) + return 0; +#endif + + clear_user_state (); + + /* We may want to tweak the PC to point at the faulting instruction, + for example. (breakpoints on x86). */ +#ifdef TARGET_ADJUST_PC + TARGET_ADJUST_PC +#endif + + pc = get_pc(); + MAKE_STD_ADDR (pc, &last_pc); + +#ifdef __ECOS__ + if ((sigval == SIGTRAP) && (__is_breakpoint_function() || processing_breakpoint_function)) +#else + if ((sigval == SIGTRAP) && __is_breakpoint_function()) +#endif + { + /* + * This is the initial breakpoint inserted by the BSP + * Don't print anything for this as it is confusing + */ + } + else + { + if (sigval == SIGTRAP) + xprintf ("Hit breakpoint"); + else + xprintf ("Got signal %d", sigval); + + xprintf (" at 0x%s\n", int2str (pc, 16, sizeof (target_register_t) * 2)); + +#ifdef DISASSEMBLER + if (!__is_breakpoint_function ()) + { + do_dis (&last_pc); + flush_dis (); + } +#endif + } + + monitor_take_control (); + + return monitor_loop (); +} + +#ifndef HAVE_BSP +/* Returns 0 if the program should restart at the point at which the + signal was received, -1 otherwise. */ +static int +handle_signal (int signal) +{ + if (signal == SIGKILL) + return -1; + + if (user_signal_handler != NULL) + { + int result = user_signal_handler (signal); + switch (result) + { + /* Don't ignore potential hardware signals. */ + case 3: + if (signal == SIGSEGV || signal == SIGBUS || signal == SIGFPE + || signal == SIGTRAP || signal == SIGILL) + return -1; + + case 0: + return 0; + + default: + case 1: + case 2: + return -1; + } + } + return -1; +} +#endif + + +void +version (void) +{ +#ifdef HAVE_BSP + struct bsp_platform_info platform; + struct bsp_mem_info mem; + int i; + unsigned long u, totmem, topmem; +#endif + extern char *build_date; + + xprintf ("Cygmon, the Cygnus ROM monitor.\n"); + xprintf ("Copyright(c) 1997, 1998, 1999, 2000 Red Hat\n\n"); + xprintf ("Version: %s\nThis image was built on %s\n\n", + VERSION, build_date); + +#ifdef HAVE_BSP + bsp_sysinfo(BSP_INFO_PLATFORM, &platform); + + totmem = topmem = 0; + i = 0; + while (bsp_sysinfo(BSP_INFO_MEMORY, i++, &mem) == 0) + { + if (mem.kind == BSP_MEM_RAM) + { + totmem += mem.nbytes; + u = (unsigned long)mem.virt_start + mem.nbytes; + if (u > topmem) + topmem = u; + } + } + + xprintf("CPU: %s\n", platform.cpu); + xprintf("Board: %s\n", platform.board); + if (*(platform.extra)) + xprintf("%s\n", platform.extra); + xprintf("Total RAM: %d bytes\n", totmem); + xprintf("Top of RAM: 0x%x\n", topmem); +#endif +} + + +#ifdef HAVE_BSP +#if !defined(USE_ECOS_HAL_EXCEPTIONS) +static int +mon_kill_handler(int exc_nr, void *regs) +{ + monitor_take_control(); + return 1; +} +#endif // !defined(USE_ECOS_HAL_EXCEPTIONS) + +#if !defined(USE_ECOS_HAL_EXCEPTIONS) +static int +mon_dbg_handler(int exc_nr, void *regs) +{ + int sig; + unsigned long cur_pc; + + mon_saved_regs = regs; + sig = bsp_get_signal(exc_nr, regs); + + cygmon_handle_exception(sig); + + cur_pc = bsp_get_pc(regs); + if (cur_pc == (unsigned long)bsp_breakinsn) + bsp_skip_instruction(regs); + + if (!stub_is_active) + install_breakpoints(); + + return 1; +} +#endif // !defined(USE_ECOS_HAL_EXCEPTIONS) + +#endif diff --git a/packages/cygmon/v2_0/misc/monitor.h b/packages/cygmon/v2_0/misc/monitor.h new file mode 100644 index 00000000..fe1a6192 --- /dev/null +++ b/packages/cygmon/v2_0/misc/monitor.h @@ -0,0 +1,303 @@ +//========================================================================== +// +// monitor.h +// +// Main definitions for the CygMON ROM monitor +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas, dmoseley +// Date: 1999-10-20 +// Purpose: Main definitions for the CygMON ROM monitor +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#ifndef MONITOR_H +#define MONITOR_H + +#if !defined(__ASSEMBLER__) +#include +#endif + +#include +#ifdef HAVE_BSP +#include "cpu_info.h" +#endif +#include + +#ifdef __ECOS__ +#include +#endif + +#ifndef ASM + +#ifdef HAVE_BSP +#define xprintf bsp_dprintf +#define xsprintf bsp_sprintf +#define xvprintf bsp_dvprintf +#define xputchar bsp_debug_putc +#define xgetchar bsp_debug_getc +#define xungetchar bsp_debug_ungetc +#define __getTty() bsp_set_debug_comm(-1) +#define set_pc(x) bsp_set_pc((x), mon_saved_regs) + +#ifndef USE_ECOS_HAL_SINGLESTEP +#define __single_step() bsp_singlestep_setup(mon_saved_regs) +#define __clear_single_step() bsp_singlestep_cleanup(mon_saved_regs) +#endif /* USE_ECOS_HAL_SINGLESTEP */ + +#ifndef USE_ECOS_HAL_BREAKPOINTS +#define breakpoint() bsp_breakpoint() +#endif /* USE_ECOS_HAL_BREAKPOINTS */ + +#if defined(__ECOS__) && defined(CYGHWR_HAL_RESET_DEFINED) + extern void __reset(void); +#else // defined(__ECOS__) && defined(CYGHWR_HAL_RESET_DEFINED) +# define __reset bsp_reset +#endif // defined(__ECOS__) && defined(CYGHWR_HAL_RESET_DEFINED) + +#else +extern void xprintf(const char *fmt, ...); +extern void xsprintf(char *str, const char *fmt, ...); +extern void xvprintf(const char *fmt, va_list ap); + +#ifdef HAS_USER_IO +#define xputchar putUserChar +#define xgetchar getUserChar +#else +extern void putDebugChar(int ch); +extern int getDebugChar(void); +#define xputchar putDebugChar +#define xgetchar getDebugChar +#endif +#define xungetchar ungetDebugChar +#endif + + +#ifndef USE_ECOS_HAL_BREAKPOINTS +struct bp { + mem_addr_t address; + bp_inst_t old_inst; + char in_memory; + struct bp *next; +}; +#endif // USE_ECOS_HAL_BREAKPOINTS + +struct regstruct +{ + char *registername; + int registernumber; +#ifdef HAVE_BSP +#if defined(CYGPKG_HAL_ARM) || !defined(__ECOS__) + int registertype; +#endif // defined(CYGPKG_HAL_ARM) || !defined(__ECOS__) +#endif +#ifdef REG_VALID_FIELD_IN_REGSTRUCT + int registervalid; +#endif +}; + + + +#ifdef HAVE_BSP +#define REGTYPE_INT 1 +#define REGTYPE_FLOAT 2 +#define REGTYPE_DOUBLE 3 + +union target_reg +{ + unsigned long i; /* integer register (32/64 bit) */ +#if HAVE_FLOAT_REGS + float f; /* float register (32bit) */ +#endif +#if HAVE_DOUBLE_REGS + double d; /* double register (64bit) */ +#endif +}; + +typedef union target_reg target_regval_t; + + +/* This is a template for what should be defined in the board specific + header file composed, board.h */ +#if ! defined(MEM_ADDR_DEFINED) +#define MEM_ADDR_DEFINED 1 +typedef struct mem_addr { + unsigned long addr; +} mem_addr_t; +#endif + +#if !defined(BP_INST_T_DEFINED) +#define BP_INST_T_DEFINED 1 +typedef unsigned char bp_inst_t ; +#endif + +#if ! defined(MAKE_STD_ADDR) +#define MAKE_STD_ADDR(SRC, DST) ((DST)->addr = (SRC)) +#endif + + +#if ! defined(ADD_OFFSET) +#define ADD_OFFSET(SRC,DST,OFFSET) ((DST)->addr = (SRC)->addr + (OFFSET)) +#endif + +#if ! defined(ADD_ALIGN) +#define ADD_ALIGN(SRC,DST,ALIGN) \ + ((DST)->addr = (SRC)->addr - ((SRC)->addr % (ALIGN))) +#endif + +#if ! defined(MEM_ADDR_EQ_P) +#define MEM_ADDR_EQ_P(A, B) ((A).addr == (B).addr) +#endif + +#if ! defined(MEM_ADDR_DIFF) +#define MEM_ADDR_DIFF(A, B) ((A).addr - (B).addr) +#endif + +#if ! defined(MEM_ADDR_ASI) +#define MEM_ADDR_ASI(A) -1 +#endif + +#endif /* HAVE_BSP */ + +#if defined(NO_MALLOC) && ! defined(MAX_NUM_BP) +#define MAX_NUM_BP 64 +#endif + +extern struct regstruct regtab[]; + +extern char **argvect; + +#ifdef HAVE_BSP +#define VERSION "release 2.0" +#else +#define VERSION "release 1.2" +#endif + +#define MAXLINELEN 80 +#define PROMPT "cygmon> " +#if ! defined MAX_HIST_ENTS +#define MAX_HIST_ENTS 10 +#endif + +/* + * From monitor.c + */ +extern mem_addr_t last_pc; +extern int stub_is_active; +#ifdef HAVE_BSP +extern void *mon_saved_regs; +#else +extern int (*user_signal_handler)(int); +#endif + +extern void clear_user_state (void); +extern int transfer_to_stub (void); +extern void version (void); +#ifdef MONITOR_CONTROL_INTERRUPTS +/* Enable interrupts within the monitor. */ +extern void monitor_enable_interrupts (void); + +/* Disable interrupts within the monitor. */ +extern void monitor_disable_interrupts (void); + +/* Returns 1 if interrupts have been enabled within the monitor, 0 + otherwise. */ +extern int monitor_interrupt_state (void); +#endif /* MONITOR_CONTROL_INTERRUPTS */ + + +/* + * From utils.c + */ +extern int switch_to_stub_flag; +extern int input_char (void); +extern target_register_t str2int (char *str, int base); +#if HAVE_DOUBLE_REGS +extern double str2double (char *str, int base); +#endif +extern target_register_t str2intlen (char *str, int base, int len); +extern int hex2bytes(char *string, char *dest, int maxsize); +extern char *int2str (target_register_t number, int base, int numdigs); +#ifndef NO_MALLOC +extern char *strdup(const char *str); +#endif +extern target_register_t get_pc(void); +extern char *get_register_str (regnames_t which, int detail, int valid); +extern void store_register (regnames_t which, char *string); + +#ifndef USE_ECOS_HAL_BREAKPOINTS +/* + * From breakpoints.c + */ +extern int add_mon_breakpoint (mem_addr_t location); +extern void install_breakpoints (void); +extern void clear_breakpoints (void); +extern int show_breakpoints (void); +extern int clear_mon_breakpoint (mem_addr_t location); +#endif /* USE_ECOS_HAL_BREAKPOINTS */ + + +/* + * From do-dis.c + */ +extern mem_addr_t do_dis (mem_addr_t *addr); +extern void flush_dis (void); + + +/* + * From architecture-mon.c + */ +#ifdef HAVE_BSP +extern void initialize_mon(void); +extern target_register_t get_register(regnames_t reg); +extern void put_register (regnames_t which, target_register_t value); +#endif + + +/* Lame. */ +#ifndef ITIMER_REAL +#define ITIMER_REAL 0 +#endif + +#endif /* ASM */ +#endif diff --git a/packages/cygmon/v2_0/misc/monitor_cmd.c b/packages/cygmon/v2_0/misc/monitor_cmd.c new file mode 100644 index 00000000..0a46fb88 --- /dev/null +++ b/packages/cygmon/v2_0/misc/monitor_cmd.c @@ -0,0 +1,2549 @@ +//========================================================================== +// +// monitor_cmd.c +// +// Monitor commands for the CygMON ROM monitor +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas, dmoseley +// Date: 1999-10-20 +// Purpose: Monitor commands for the CygMON ROM monitor +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#ifdef HAVE_BSP +#include "cpu_info.h" +#include +#include +#include +#ifdef __BOARD_HEADER__ +#include __BOARD_HEADER__ +#endif +#endif +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_BSP +#include "fmt_util.h" +#include "tservice.h" +#endif + +#ifdef __ECOS__ +#include +#endif + +#if USE_CYGMON_PROTOTYPES +/* Use common prototypes */ +/* Some of the composed board.h files compose these + prototypes redundently, but if they dont, + these are the common definitions */ +#include "fmt_util.h" /* Interface to string formatting utilities */ +#include "tservice.h" /* Interface to target specific services */ +#include "generic-stub.h" /* from libstub */ +#endif /* USE_CYGMON_PROTOTYPES */ + +static int history_cmd(cmdmode_t mode) ; + +#ifndef MAXLINELEN +#define MAXLINELEN 80 +#endif + +#define MAXLINES 23 + +char inbuf[MAXLINELEN] ; +static char cmd[MAXLINELEN]; + +#if ! defined(PROVIDE_CRASH_CMD) +#define PROVIDE_CRASH_CMD 0 +#endif + +#if PROVIDE_CRASH_CMD +/* + * The crash command is used while debugging cygmon itself + */ +static int crash_cmd(cmdmode_t mode) ; /* Command to trap into cygmon */ +#endif + +struct cmdentry cmdtab[] = { + {NULL, "baud", set_serial_speed_cmd}, + {"b", "break", breakpoint_cmd}, +#if HAVE_CACHE + {NULL, "cache", cache_cmd}, +#endif + {NULL, "copy", copy_cmd}, +#if PROVIDE_CRASH_CMD + {NULL, "crash", crash_cmd}, +#endif + {NULL, "crc", checksumcmd}, + {"d", "disassemble", disassemble_cmd}, + {NULL, "dump", dump_cmd}, +#if defined(NVRAM_ETH_ADDR) + {NULL, "ethaddr", ethaddr_cmd}, +#endif + {NULL, "fill", fill_cmd}, + {NULL, "go", go_cmd}, + {NULL, "help", help_cmd}, + {"his","history", history_cmd}, +#ifdef MONITOR_CONTROL_INTERRUPTS + {NULL, "interrupt", int_cmd}, +#endif +#if defined(NVRAM_IP_ADDR) + {NULL, "ipaddr", ipaddr_cmd}, +#endif + {NULL, "load", load_cmd}, + {"m", "memory", mem_cmd}, +#ifdef OTHERNAMES_CMD + {"o", "othernames", othernames_cmd}, +#endif + {NULL, "port", set_serial_port_cmd}, + {"r", "register", reg_cmd}, + {NULL, "reset", reset_cmd}, +#ifndef HAVE_BSP + {NULL, "setargs", set_program_args_cmd}, +#endif + {"si", "step", step_cmd}, + {NULL, "swapmem", swapmem_cmd}, +#if defined(NVRAM_TCP_PORT) + {NULL, "tcpport", tcpport_cmd}, +#endif + {NULL, "terminal", set_term_cmd}, +#ifdef HAS_TIMER + {NULL, "timer", timer_cmd}, +#endif +#if !defined(__ECOS__) || defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) + {NULL, "transfer", transfer_cmd}, +#endif + {"u", "unbreak", clear_breakpoint_cmd}, +#if HAVE_USAGE + {NULL, "usage", memusage_cmd}, +#endif + {NULL, "version", version_cmd}, + /* Really need to redo the way commands are done--there should be a + dynamic list (perhaps in addition to the static one). */ +#ifdef TARGET_COMMANDS + TARGET_COMMANDS +#endif + + {NULL, NULL, NULL} +}; + +static int +alias_compare (char *cmd) +{ + int m = 0; + int match = -1; + int num_matches = 0; + + while (cmdtab[m].cmd != NULL) + { + if (cmdtab[m].alias != NULL && !strcmp (cmd, cmdtab[m].alias)) + { + match = m; + num_matches++; + /* We're expecting that aliases will be defined + uniquely, but just in case, we let the user know + if there is a conflict */ + if (num_matches > 1) + { + xprintf ("Alias conflict. Executing last matching alias.\n"); + } + } + m++; + } + return match; +} + +static int +command_compare (char *cmd) +{ + int m = 0; + int match = -1; + int num_matches = 0; + int cmdlen = strlen(cmd) ; + while (cmdtab[m].cmd != NULL) + { + if (!(strncmp (cmd,cmdtab[m].cmd, cmdlen))) + { + /* we found a match */ + num_matches++; + if (num_matches == 2) /* we found a second match */ + { + xprintf ("Ambiguous command. Possibilities are:\n%s\n%s\n", + cmdtab[match].cmd, + cmdtab[m].cmd); + } + else if (num_matches > 2) /* we found another match */ + { + /* Show the new possibility we just found */ + xprintf ("%s\n", cmdtab[m].cmd); + } + /* Point the match at the command we just looked at. + We have to wait until now so that the first duplicate + found can output the earlier match as well */ + match = m; + } + m++; + } + return ((num_matches == 1) ? match : -1); +} + +#ifdef USE_HELP +void +usage (char *string) +{ + xprintf ("Usage: %s\n", string); +} + +void +short_help (char *string) +{ + xprintf ("%s\n", string); +} + +void +long_help (char *string) +{ + int linecnt = 0; + int do_leave = 0; + + for (; *string && !do_leave; string++) + { + xprintf ("%c", *string); + if (*string == '\n') + { + linecnt++; + if (linecnt == MAXLINES) + { + int i; + + xprintf ("-More-"); + while ((i = input_char ()) >= 0) + { + if (i == '\r' || i == '\n') + { + linecnt--; + break; + } + else if (i == ' ') + { + linecnt = 0; + break; + } + else if (i == 'q' || i == 'Q') + { + do_leave = 1; + break; + } + else + beep (); + } + } + } + } + xprintf ("\n"); +} + +void +example (char *example) +{ + xprintf ("Example: %s\n", example); +} + +#else +void +no_help (void) +{ + xprintf ("No help available.\n"); +} + +void +no_help_usage (void) +{ + xprintf ("Incorrect usage.\n"); +} +#endif + +int +help_cmd (cmdmode_t mode) +{ + int command_number = -2; + + if (mode == USAGE) + { + usage ("help [command]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("The help command"); + return 0; + } + if (mode == LONG_HELP) + { + help_cmd (USAGE); + long_help ("\ +The help command without arguments shows a list of all available commands\n\ +with a short description of each one. With a command name as an argument\n\ +it shows usage for the command and a paragraph describing the command.\n\ +Usage is shown as command name followed by names of extensions or arguments.\n\ +Arguments in [brackets] are optional, plain text arguments are required.\n\ +Note that all commands can be invoked by typing enough of the command name\n\ +to uniquely specify the command. Some commands have aliases, which are one\n\ +letter abbreviations for commands which do not have unique first letters.\n\ +Aliases for all commands are shown in the help screen, which displays\n\ +commands in the format:\n\ +command name: (alias, if any) description of command \n"); + example("\ +help foo \n\ +Shows the help screen for the command foo."); + return 0; + } + + if (argvect[1] != NULL) + { + if (argvect[2] == NULL) + { + command_number = command_compare (argvect[1]); + if (command_number < 0) + { + xprintf ("No such command as %s\n", argvect[1]); + } + } + + if (command_number < 0) + { + return help_cmd (USAGE); + } + else + { + return cmdtab[command_number].function (LONG_HELP); + } + } + else + { + int i; + + xprintf ("Available commands are:\n"); + for (i = 0; cmdtab[i].cmd != NULL; i++) + { + int x = strlen (cmdtab[i].cmd) + 2; + + xprintf ("%s: ", cmdtab[i].cmd); + if (cmdtab[i].alias != NULL) + { + xprintf("(%s)", cmdtab[i].alias); + x += 2 + strlen(cmdtab[i].alias); + } + for (; x < 20; x++) + { + xprintf (" "); + } + cmdtab[i].function (SHORT_HELP); + if ((i > 0) && (i % MAXLINES) == 0) + { + xprintf ("-More-"); + input_char (); + xprintf ("\n"); + } + } + } + return 0; +} + +#if PROVIDE_CRASH_CMD +static int crash_cmd(cmdmode_t mode) +{ + switch (mode) + { + case USAGE : usage("crash") ; break ; + case SHORT_HELP : short_help("invoke the breakpoint function"); + break ; + case LONG_HELP : + long_help("The crash command calls the breakpoint function() which is useful\n\ +only if you are using an additional debugger to debug this software and,\n\ +the general exception handler is hooked to the other debugger\n") ; + break ; + case INVOCATION : + dbg_breakpoint() ; + break ; + } + return 0 ; +} +#endif /* provide_crash_command */ + + + +static int history_cmd(cmdmode_t mode) +{ + switch (mode) + { + case USAGE : usage("history") ; break ; + case SHORT_HELP : short_help("Print help about line editing features."); + break ; + case INVOCATION : + printHistoryList(); + break; + case LONG_HELP : + long_help("Cygmon line editing allows you to repeat previously entered +commands. The line editing commands are: + CR '\\n' Execute the currently displayed command + ctl-a move to Beginning of line + ctl-e End of line + ctl-f Forward char + ctl-b Backward char + ctl-k Delete to end of line + ctl-y yank Character (undelete) + ctl-d Delete current character + ctl-p edit previous command + ctl-u Erase Line + ctl-n Edit next command") ; + break ; + } + return 0 ; +} /* history_cmd */ + +#ifdef OTHERNAMES_CMD +/* Switch to using the othernames (ie alternate register names) */ +int +othernames_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("othernames"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Switch between alternate register names."); + return 0; + } + if (mode == LONG_HELP) + { + othernames_cmd (USAGE); + long_help ("\ +The othernames command allows you to switch between alternate register +names for a given target."); + example ("\ +othernames\n\ +Switches to the alternate register name set.."); + return 0; + } + OTHERNAMES_CMD(); + + return 0; +} +#endif /* OTHERNAMES_CMD */ + + +#if defined(NVRAM_ETH_ADDR) +int +ethaddr_cmd (cmdmode_t mode) +{ + int i, n; + unsigned char addr[6]; + char *p; + + if (mode == USAGE) + { + usage ("ethaddr [xx:xx:xx:xx:xx:xx]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("get/set NVRAM backed ethernet address"); + return 0; + } + if (mode == LONG_HELP) + { + ethaddr_cmd (USAGE); + long_help ("\ +The ethaddr command is used to view and modify the non-volatile ethernet\n\ +address. The address is specified by 6 colon-seperated 2 digit hexadecimal\n\ +numbers. If no address is specified, the current address is displayed.\n"); + example ("ethaddr 00:00:8B:F1:36:01"); + return 0; + } + + if (argvect[1] != NULL) + { + if (strlen(argvect[1]) != 17 || argvect[2] != NULL) + { + return ethaddr_cmd (USAGE); + } + + for (i = 0, p = argvect[1]; i < 6; i++, p++) + { + n = __hex(*p++); + if (n < 0) + return ethaddr_cmd (USAGE); + addr[i] = (n << 4); + n = __hex(*p++); + if (n < 0) + return ethaddr_cmd (USAGE); + addr[i] |= n; + + if (*p != ':' && !(i == 5 && *p == '\0')) + return ethaddr_cmd (USAGE); + } + for (i = 0; i < 6; i++) + NVRAM_ETH_ADDR(i) = addr[i]; + } + else + { + for (i = 0; i < 5; i++) + xprintf("%02x:", NVRAM_ETH_ADDR(i)); + xprintf("%02x\n", NVRAM_ETH_ADDR(i)); + } + + return 0; +} +#endif /* NVRAM_ETH_ADDR */ + + +#if defined(NVRAM_IP_ADDR) +int +ipaddr_cmd (cmdmode_t mode) +{ + int i, j, n; + unsigned char addr[4]; + char *p; + + if (mode == USAGE) + { + usage ("ipaddr [n.n.n.n]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("get/set NVRAM backed ip address"); + return 0; + } + if (mode == LONG_HELP) + { + ipaddr_cmd (USAGE); + long_help ("\ +The ipaddr command is used to view and modify the non-volatile internet\n\ +address. The address is specified by 4 dot-seperated 1-3 digit decimal\n\ +numbers. If no address is specified, the current address is displayed.\n"); + example ("ipaddr 192.161.0.1"); + return 0; + } + + if (argvect[1] != NULL) + { + if (argvect[2] != NULL) + return ipaddr_cmd (USAGE); + + p = argvect[1]; + + for (i = 0; i < 3; i++, p++) + { + for (j = n = 0; j < 3 && isdigit(*p); j++, p++) + n = n*10 + (*p - '0'); + if (j == 0 || *p != '.' || n > 255) + return ipaddr_cmd (USAGE); + addr[i] = n; + } + for (j = n = 0; j < 3 && isdigit(*p); j++, p++) + n = n*10 + (*p - '0'); + if (j == 0 || *p != '\0' || n > 255) + return ipaddr_cmd (USAGE); + addr[i] = n; + + for (i = 0; i < 4; i++) + NVRAM_IP_ADDR(i) = addr[i]; + } + else + { + for (i = 0; i < 3; i++) + xprintf("%d.", NVRAM_IP_ADDR(i)); + xprintf("%d\n", NVRAM_IP_ADDR(i)); + } + + return 0; +} +#endif /* NVRAM_IP_ADDR */ + +#if defined(NVRAM_TCP_PORT) +int +tcpport_cmd (cmdmode_t mode) +{ + int n; + char *p; + + if (mode == USAGE) + { + usage ("ethaddr [xx:xx:xx:xx:xx:xx]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("get/set NVRAM backed tcp port number"); + return 0; + } + if (mode == LONG_HELP) + { + tcpport_cmd (USAGE); + long_help ("\ +The tcpport command is used to view and modify the non-volatile tcp port\n\ +address used for debugging. The address is specified by decimal numer in\n\ +the range of 1-65535. If no port number is specified, the current port is\n\ +displayed.\n"); + example ("tcpport 1000"); + return 0; + } + + if (argvect[1] != NULL) + { + if (argvect[2] != NULL) + return tcpport_cmd (USAGE); + + p = argvect[1]; + n = 0; + while (isdigit(*p)) + { + n = n*10 + (*p++ - '0'); + if (n > 65535) + return tcpport_cmd (USAGE); + } + if (*p != '\0') + return tcpport_cmd (USAGE); + + NVRAM_TCP_PORT(0) = (n >> 8) & 0xff; + NVRAM_TCP_PORT(1) = n & 0xff; + } + else + xprintf("%d\n", (NVRAM_TCP_PORT(0) << 8) + NVRAM_TCP_PORT(1)); + + return 0; +} +#endif /* NVRAM_TCP_PORT */ + + +#ifdef __ECOS__ +# if (CYG_BYTEORDER == CYG_LSBFIRST) +# define LITTLE_ENDIAN_TARGET +# else +# define BIG_ENDIAN_TARGET +# endif +#endif + +#ifdef LITTLE_ENDIAN_TARGET +static int swap_bytes = 1; +#else +static int swap_bytes = 0; +#endif + +int +get_memory_display_mode (void) +{ + return swap_bytes; +} + +void +set_memory_display_mode (int mode) +{ + swap_bytes = mode; +} + + +/* Just to make DEFAULT_SIZE something usable, this may go elsewhere later.*/ +#ifndef DEFAULT_SIZE +#define DEFAULT_SIZE 1 +#endif + +static int +get_cmd_size (void) +{ + int size = 0; + char *sizestr; + + sizestr = strchr (argvect[0], '.'); + + if (sizestr == NULL || sizestr[0] == '\0' || sizestr[1] == '\0') + { + size = DEFAULT_SIZE; + } + else + { + size = str2int (sizestr + 1, 10) / 8; + } + if (size != 1 && size != 2 && size != 4 && size != 8) + { + xprintf ("Invalid size.\n"); + return -1; + } + return size; +} + + +void +display_memory (char *value, int size, int littleEndian) +{ + int x; + int start = littleEndian ? size - 1 : 0 ; + int end = littleEndian ? -1 : size; + int incr = littleEndian ? -1 : 1; + + if (value) + { + for (x = start; x != end; x += incr) + xprintf ("%02x", value[x] & 0xff); + } + else + { + for (x = start; x != end; x += incr) + xprintf (".."); + } +} + + +static int +peek (void) +{ + mem_addr_t addr; + int size = get_cmd_size (); + + if (size > 0) + { + /* We already checked to see if the command was legal when we called the + function, so there's no need to worry about that here. */ + + if (argvect[1] != 0) + { + char value[8]; + + str2addr (argvect[1], &addr); + if (read_memory (&addr, size, 1, value)) + { + xprintf ("Memory read failed\n"); + } + else + { + display_memory (value, size, get_memory_display_mode ()); + xprintf ("\n"); + } + } + else + { + xprintf ("Not enough arguments\n"); + return mem_cmd (USAGE); + } + } + return 0; +} + +/* Poke a single byte in memory. */ + +static int +poke (void) +{ + int size = 0; + + size = get_cmd_size (); + if (size > 0) + { + /* We already checked to see if the command was legal when we called the + function, so there's no need to worry about that here. */ + + if ((argvect[1] != 0) && (argvect[2] != 0)) + { + char value[8]; + mem_addr_t addr; + + str2addr (argvect[1], &addr); + hex2bytes (argvect[2], value, size); + + if (get_memory_display_mode ()) + { + /* Gotta swap this puppy. */ + int x; + + for (x = 0; x < (size / 2); x++) + { + char tmp = value[x]; + value [x] = value [size - 1 - x]; + value [size - 1 - x] = tmp; + } + } + if (write_memory (&addr, size, 1, value)) + { + xprintf ("Memory write failed\n"); + } +#ifdef HAVE_BSP + bsp_flush_dcache((void *)addr.addr, size); + bsp_flush_icache((void *)addr.addr, size); +#endif + } + else + { + xprintf ("Not enough arguments\n"); + return mem_cmd (USAGE); + } + } + return 0; +} + + +/* I am cheap and easy. */ +int +mem_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("memory[.size] address [value]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("read/write memory"); + return 0; + } + if (mode == LONG_HELP) + { + mem_cmd (USAGE); + long_help ("\ +The memory command is used to view and modify single locations in memory.\n\ +It can take a size extension, which follows the command name or partial\n\ +command name without a space, and is a period followed by the number of\n\ +bits to be viewed or modified. Options are 8, 16, 32, and 64. Without\n\ +a size extension, the memory command defaults to displaying or changing 8\n\ +bits at a time.\n\ +The memory command can take one or two arguments, independent of\n\ +whether a size extension is specified. With one argument, it displays the\n\ +contents of the specified location. With two arguments, it replaces the\n\ +contents of the specified location with the specified value.\n"); + example ("\ +memory.8 45f6b2 57\n\ +Places the 8 bit value 57 at the location 45f6b2."); + return 0; + } + + if (argvect[1] == NULL || (argvect[2] != NULL && argvect[3] != NULL)) + { + return mem_cmd (USAGE); + } + if (argvect[1] != NULL && argvect[2] != NULL) + return poke (); + else + return peek (); +} + +/* Memory dump function. */ + +int +dump_cmd (cmdmode_t mode) +{ + mem_addr_t addr; + char value[8]; + + if (mode == USAGE) + { + usage ("dump[.size] location [count]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Memory dump command"); + return 0; + } + if (mode == LONG_HELP) + { + dump_cmd (USAGE); + long_help ("\ +The dump command displays a region of memory. If no count value is\n\ +supplied, the command displays 16 bytes. It can take a size\n\ +extension, which follows the command name or partial command name\n\ +without a space, and is a period followed by the number of bits to be\n\ +viewed or modified. Options are 8, 16, 32, and 64. Without a size\n\ +extension, the dump command defaults to displaying 8 bits at a time.\n\ +Addresses are aligned to a 16-byte boundary. Thus, dump 65 would show\n\ +all bytes from 60 through 6f.\n"); + example ("\ +dump 44f5\n\ +Displays 16 bytes starting with 44f0 and ending with 44ff."); + return 0; + } + + if (argvect[1] != 0 && (argvect[2] == NULL || argvect[3] == NULL)) + { + mem_addr_t start_addr; + char chardumps[32]; + int offset; + int count; + int line; + int size = get_cmd_size (); + int i; + + if (size == -1) + /* + * Invalid size specified. + */ + return 0; + + str2addr (argvect[1], &addr); + if (argvect[2] != NULL) + { + count = str2int (argvect[2], 10); + count = (count + 15) / 16; + } + else + { + count = 1; + } + ADD_ALIGN(&addr, &start_addr, 16); + for (line = 0; line < count; line ++) + { + for (offset = 0; offset < 16; offset += size) + { + ADD_OFFSET(&start_addr, &addr, offset + line * 16); + + if (offset == 0) + { + char buf[32]; + + addr2str (&addr, buf); + xprintf("%s: ", buf); + } + if (read_memory (&addr, size, 1, value)) + { + display_memory (0, size, get_memory_display_mode ()); + for (i = 0; i < size; i++) + { + value[i] = 0; + } + } else { + display_memory (value, size, get_memory_display_mode ()); + } + xprintf (" "); + for (i = 0; i < size; i++) + { + chardumps[offset + i] = value[i] & 0x7f; + if (chardumps[offset + i] < 32) + chardumps[offset + i] = '.'; + } + } + xprintf (" "); + for(i = 0; i < offset; i++) + { + xprintf ("%c", chardumps[i]); + } + xprintf ("\n"); + } + } + else + { + dump_cmd (USAGE); + } + return 0; +} + +static int scnt; +static int (*srec_input_char) (void); + +static inline int +gethexnibble(void) +{ + int ch; + + inbuf[scnt++] = ch = srec_input_char(); + if (ch >= '0' && ch <= '9') + return (ch - '0'); + if (ch >= 'a' && ch <= 'f') + return (ch - 'a' + 10); + if (ch >= 'A' && ch <= 'F') + return (ch - 'A' + 10); + + inbuf[scnt] = '\0'; + xprintf("Bad hex char: %s\n", inbuf); + return -1; +} + + +static inline int +gethexbyte(void) +{ + int nib; + unsigned char n; + + if ((nib = gethexnibble()) < 0) + return -1; + n = nib << 4; + if ((nib = gethexnibble()) < 0) + return -1; + n |= nib; + return n; +} + +static inline int +chk_cksum(unsigned int cksum, int rval) +{ + int n; + + if ((n = gethexbyte()) < 0) + return -1; + + cksum = ~cksum & 0xff; + + if (cksum != n) + { + inbuf[scnt] = '\0'; + xprintf("Bad cksum[%02x]: %s\n", cksum, inbuf); + return -1; + } + return rval; +} + +int +load_srec(srec_input_func_t inp_func) +{ + int count, dcount, data, n, addr_bytes = 0, is_term, is_comment; + unsigned int address, cksum; + unsigned char data_buf[256]; + mem_addr_t memaddr; + + srec_input_char = inp_func; + + is_comment = is_term = 0; + + while (srec_input_char() != 'S') + ; + + scnt = 0; + inbuf[scnt++] = 'S'; + + if ((n = gethexnibble()) < 0) + return -1; + + switch (n) + { + case 0: + case 5: + is_comment = 1; + break; + + case 1: + case 2: + case 3: + addr_bytes = n + 1; + break; + + case 7: + case 8: + case 9: + is_term = 1; + addr_bytes = 11 - n; + break; + + default: + inbuf[scnt] = '\0'; + xprintf("Bad record type: %s\n", inbuf); + return -1; + } + + if ((count = gethexbyte()) < 0) + return -1; + cksum = count; + + --count; /* don't count chksum */ + + if (is_comment) + { + while (count > 0) + { + if ((n = gethexbyte()) < 0) + return -1; + cksum += n; + --count; + } + return chk_cksum(cksum, 0); + } + + address = 0; + while (count > 0 && addr_bytes) + { + if ((n = gethexbyte()) < 0) + return -1; + cksum += n; + address = (address << 8) | n; + --addr_bytes; + --count; + } + + if (is_term) + { + if (count || addr_bytes) + { + inbuf[scnt] = '\0'; + xprintf("Malformed record cnt[%d] abytes[%d]: %s\n", + count, addr_bytes, inbuf); + return -1; + } + if (chk_cksum(cksum, 1) == 1) + { + set_pc (address); + xprintf("Setting start address: 0x%08x\n", address); + return 1; + } + return -1; + } + + dcount = 0; + + while (count > 0) + { + if ((data = gethexbyte()) < 0) + return -1; + cksum += data; + data_buf[dcount++] = data; + --count; + } + + if (chk_cksum(cksum, 0)) + return -1; + + MAKE_STD_ADDR (address, &memaddr); + write_memory (&memaddr, 1, dcount, data_buf); +#ifdef HAVE_BSP + bsp_flush_dcache((void *)memaddr.addr, dcount); + bsp_flush_icache((void *)memaddr.addr, dcount); +#endif + + return 0; +} + + +int +load_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("load"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Load srecords into memory"); + return 0; + } + if (mode == LONG_HELP) + { + load_cmd (USAGE); + long_help ("\ +The load command switches the monitor into a state where it takes all input +as s-records and stores them in memory. The monitor exits this mode when a +termination record is hit, or certain errors (such as an invalid s-record) +cause the load to fail."); + return 0; + } + + if (argvect[1] != NULL) + { + return load_cmd (USAGE); + } + + while (!load_srec(xgetchar)) + ; + + return 0; +} + +#ifndef REGNAME_EXAMPLE +# define REGNAME_EXAMPLE "a0" +#endif + +#if !defined(__ECOS__) || defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) +int +transfer_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("$"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Transfer to gdb stub"); + return 0; + } + if (mode == LONG_HELP) + { + transfer_cmd (USAGE); + long_help ("\ +The transfer or $ command transfers control to the gdb stub. This function\n\ +does not actually need to be called by the user, as connecting to the board\n\ +with gdb will call it automatically. The transfer command takes no\n\ +arguments. The $ command does not wait for a return, but executes\n\ +immediately. A telnet setup in line mode will require a return when $ is\n\ +executed by the user, as the host computer does not pass any characters to\n\ +the monitor until a return is pressed. Disconnecting from the board in gdb\n\ +automatically returns control to the monitor."); + return 0; + } + if (argvect[1] == NULL) + { + return transfer_to_stub (); + } + else + { + transfer_cmd (USAGE); + } + return 0; +} +#endif + +static void +display_group (int which_group) +{ + int len = 0; + int skipping_group = 0; + char buf[80]; + int start_entry = 0; + int i; + + if (which_group >= 0) + { + start_entry = which_group; + } + + for (i = start_entry; regtab[i].registername != NULL; i++) + { + int buflen; + + if (regtab[i].registernumber < 0) + { + if (which_group >= 0 && i != which_group) + { + break; + } + + if (len > 0) + { + xprintf ("\n"); + len = 0; + } + if (which_group < 0) + { + if (regtab[i].registernumber == -2) + { + skipping_group = 1; + xprintf ("[skipping %s]\n", regtab[i].registername); + } + else + { + skipping_group = 0; + xprintf ("[%s]\n", regtab[i].registername); +#if 0 + len = strlen (regtab[i].registername) + 2; + while (len < MAXLINES) + { + xputchar (' '); + len++; + } +#endif + } + } + } + else + if (!skipping_group) + { +#ifdef REG_VALID_FIELD_IN_REGSTRUCT +#define REGVALID_VAL regtab[i].registervalid +#else +#define REGVALID_VAL 1 +#endif + xsprintf(buf, "%4s: %s", + regtab[i].registername, + get_register_str (regtab[i].registernumber, 0 , REGVALID_VAL)); +#undef REGVALID_VAL + buflen = strlen (buf); + if ((buflen + len + 3) >= 80) + { + xprintf ("\n"); + len = 0; + } + else if(len > 0) + { + xprintf (" "); + len += 3; + } + + xprintf (buf); + len += buflen; + } + } + if (len > 0) + { + xprintf ("\n"); + } +} + +static int +getregister (void) +{ + int i; + + if (argvect[1] == 0) + { + display_group (-1); + } + else + { + for (i = 0; regtab[i].registername != NULL; i++) + { + if (!(strcmp (argvect[1], regtab[i].registername))) + { + break; + } + } + if (regtab[i].registername == NULL) + { + xprintf ("No such register\n"); + } + else + { + if (regtab[i].registernumber < 0) + { + display_group (i); + } + else + { +#ifdef REG_VALID_FIELD_IN_REGSTRUCT +#define REGVALID_VAL regtab[i].registervalid +#else +#define REGVALID_VAL 1 +#endif + xprintf("%s: %s\n", argvect[1], + get_register_str (regtab[i].registernumber, 1, REGVALID_VAL)); +#undef REGVALID_VAL + } + } + } + return 0; +} + +static int +setregister (void) +{ + int number = -1; + int i; + if ((argvect[1] != 0) && (argvect[2] != 0)) + { + i = 0; + while (regtab[i].registername != NULL) + { + if (!(strcmp (argvect[1], regtab[i].registername))) + { + number = regtab[i].registernumber; + break; + } + i++; + } + if (number < 0) + xprintf ("Unknown register name %s\n", argvect[1]); + else + store_register (number, argvect[2]); + } + else + { + xprintf ("Not enough arguments\n"); + } + return 0; +} + + +int +reg_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("register [register name] [value]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("View and manipulate registers"); + return 0; + } + if (mode == LONG_HELP) + { + reg_cmd (USAGE); + long_help ("\ +The register command allows the viewing and manipulation of register\n\ +contents. It can take zero, one, or two arguments. When called with zero\n\ +arguments, the register command displays the values of all registers. When\n\ +called with only the register name argument, it displays the contents of\n\ +the specified register. When called with both a register name and a value,\n\ +it places that value into the specified register.\n"); + example ("\ +register " REGNAME_EXAMPLE " 1f\n\ +Places the value 1f in the register " REGNAME_EXAMPLE); + return 0; + } + + if (argvect[1] != NULL && argvect[2] != NULL) + { + if (argvect[3] != NULL) + { + return reg_cmd (USAGE); + } + return setregister (); + } + else + return getregister (); +} + + +/* execute the program in memory */ +int +go_cmd (cmdmode_t mode) +{ +#ifdef HAS_TIMER + extern tick_type start_tickcount; +#endif + + if (mode == USAGE) + { + usage ("go [location]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Start user program execution"); + return 0; + } + if (mode == LONG_HELP) + { + go_cmd (USAGE); + long_help ("\ +The go command starts user program execution. It can take zero or one\n\ +argument. If no argument is provided, go starts execution at the current\n\ +pc. If an argument is specified, go sets the pc to that location, and then\n\ +starts execution at that location.\n"); + example (" +go 40020000\n\ +Sets the pc to 40020000, and starts program execution."); + return 0; + } + + if (argvect[1] != NULL && argvect[2] != NULL) + { + return go_cmd (USAGE); + } + if (argvect[1] != NULL) + { + set_pc (str2int (argvect[1], 16)); + } + +#ifdef HAS_TIMER + start_tickcount = __read_ticks (); +#endif + /* We want monitor_loop to exit now. */ + return 1; +} + +#ifdef HAS_TIMER +int +timer_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("timer [state]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Enable and disable timer"); + return 0; + } + if (mode == LONG_HELP) + { + timer_cmd (USAGE); + long_help ("\ +The timer command allows control of the on board timer. It takes zero\n\ +or one argument. With zero arguments, it displays the state of the timer,\n\ +with one argument, which can start with e or d, it enables or disables the\n\ +timer, respectively.\n"); + example ("\ +timer e\n\ +Enables the timer."); + return 0; + } + + if (argvect[1] != NULL) + { + if (argvect[2] != NULL) + { + return timer_cmd (USAGE); + } + else if (argvect[1][0] == 'e') + { + __settimer (0, 0); + } + else if (argvect[1][0] == 'd') + { + __disable_timer (); + } + else + { + timer_cmd (USAGE); + } + } + if (__timer_enabled ()) + { + xprintf ("Timer is currently enabled.\n"); + } + else + { + xprintf ("Timer is currently disabled.\n"); + } + return 0; +} +#endif + +int +clear_breakpoint_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("unbreak location"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Clear breakpoint"); + return 0; + } + if (mode == LONG_HELP) + { + clear_breakpoint_cmd (USAGE); + long_help ("\ +The unbreak command removes breakpoints from memory. It takes one\n\ +argument, the location to remove the breakpoint from.\n"); + example ("\ +unbreak 4ff5\n\ +Removes a previously set breakpoint at memory location 4ff5."); + return 0; + } + + if (argvect[1] == NULL || argvect[2] != NULL) + { + clear_breakpoint_cmd (USAGE); + } + else + { + mem_addr_t location; + str2addr (argvect[1], &location); + if (clear_mon_breakpoint (location)) + { + xprintf("Unable to remove breakpoint at 0x%08lx\n", location.addr); + } + } + return 0; +} + + +int +breakpoint_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("break [location]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Set or display breakpoints"); + return 0; + } + if (mode == LONG_HELP) + { + breakpoint_cmd (USAGE); + long_help ("\ +The break command displays and sets breakpoints in memory. It takes zero\n\ +or one argument. With zero arguments, it displays a list of all currently\n\ +set breakpoints. With one argument it sets a new breakpoint at the\n\ +specified location.\n"); + example ("\ +break 4ff5\n\ +Sets a breakpoint at address 4ff5."); + return 0; + } + + if (argvect[1] == NULL) + { + return show_breakpoints (); + } + else if (argvect[2] != NULL) + { + breakpoint_cmd (USAGE); + } + else + { + mem_addr_t location; + + str2addr (argvect[1], &location); + if (add_mon_breakpoint (location)) + { + xprintf("Unable to set breakpoint at 0x%08lx\n", location.addr); + } + } + return 0; +} + + +int +version_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("version"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Display version"); + return 0; + } + if (mode == LONG_HELP) + { + version_cmd (USAGE); + long_help ("\ +The version command displays the version of the monitor."); + return 0; + } + + if (argvect[1] == NULL) + { + version (); + } + else + { + version_cmd (USAGE); + } + return 0; +} + +int +set_serial_port_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("port [port number]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Set the active serial port"); + return 0; + } + if (mode == LONG_HELP) + { + set_serial_port_cmd (USAGE); + long_help ("\ +The port command allows control over the serial port being used by the\n\ +monitor. It takes zero or one argument. Called with zero arguments it\n\ +displays the port currently in use by the monitor. Called with one\n\ +argument it switches the port in use by the monitor to the one specified.\n\ +It then prints out a message on the new port to confirm the switch.\n"); + example ("\ +port 1\n\ +Switches the port in use by the monitor to port 1."); + return 0; + } + if (argvect[1] != NULL && argvect[2] != NULL) + { + set_serial_port_cmd (USAGE); + return 0; + } + if (argvect [1] != NULL) + { +#ifdef HAVE_BSP + if (bsp_set_debug_comm(str2int (argvect[1], 10)) < 0) + xprintf("Invalid port number.\n"); + else + /* Since we are using the new port, we just need to write + something to tell the user that this is the active port */ + xprintf ("Cygmon I/O now on this port.\n"); +#else + __setTty (str2int (argvect[1], 10)); + /* Since we are using the new port, we just need to write + something to tell the user that this is the active port */ + xprintf ("Cygmon I/O now on this port.\n"); +#endif + } + else + { + xprintf ("serial port currently set to %d\n", __getTty()); + return 0; + } + return 0; +} + +int +step_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("step [location]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Single step user program"); + return 0; + } + if (mode == LONG_HELP) + { + step_cmd (USAGE); + long_help ("\ +The step command causes one instruction of the user program to execute, then\n\ +returns control to the monitor. It can take zero or one argument. If no\n\ +argument is provided, step executes one instruction at the current pc. If\n\ +a location is specified, step executes one instruction at the specified\n\ +location.\n"); + example (" +step\n\ +Executes one instruction at the current pc."); + return 0; + } + + if (argvect[1] != NULL && argvect[2] != NULL) + { + step_cmd (USAGE); + return 0; + } + if (argvect[1] != NULL) + set_pc (str2int (argvect[1], 16)); + + __single_step (); + return 1; + +} + +#if HAVE_CACHE +/* This cache function needs to be in processor-specific files. */ + +int +cache_cmd (cmdmode_t mode) +{ + int x; + int cache_op = CACHE_NOOP; + int which_cache = -1; + + if (mode == USAGE) + { + usage ("cache [type] [state]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Manipulate caches"); + return 0; + } + if (mode == LONG_HELP) + { + cache_cmd (USAGE); + long_help ("\ +The cache command displays and changes the states of the caches. It takes\n\ +zero, one, or two arguments. With no arguments, it displays the state of\n\ +both the instruction cache and the data cache. With one argument, it\n\ +displays the state of the specified type of cache. With two arguments, it\n\ +changes the state of the specified cache to the specified state.\n"); + example ("\ +cache i d\n\ +Disables the instruction cache."); + return 0; + } + + if (argvect[1] != NULL && argvect[2] != NULL && argvect[3] != NULL) + { + return cache_cmd (USAGE); + } + if (argvect[1] != NULL) + { + if (argvect[1][0] == 'd') + which_cache = 0; + else if (argvect[1][0] == 'i') + which_cache = 1; + else + { + xprintf ("unknown cache type %s\n", argvect[1]); + return 0; + } + if (argvect[2] != NULL) + { + if (argvect[2][0] == 'e') + cache_op = CACHE_ENABLE; + else if (argvect[2][0] == 'd') + cache_op = CACHE_DISABLE; + else if (argvect[2][0] == 'f') + cache_op = CACHE_FLUSH; + else + { + xprintf ("Unknown cache op %s\n", argvect[2]); + return 0; + } + } + } + if (which_cache == 0 || which_cache == -1) + { + __data_cache (cache_op); + if (cache_op == CACHE_FLUSH) + { + xprintf ("Flushed dcache\n"); + } + x = __data_cache (CACHE_NOOP); + xprintf ("dcache is "); + xprintf (x ? "enabled\n" : "disabled\n"); + } + if (which_cache == 1 || which_cache == -1) + { + __instruction_cache (cache_op); + if (cache_op == CACHE_FLUSH) + { + xprintf ("Flushed icache\n"); + } + x = __instruction_cache (CACHE_NOOP); + xprintf ("icache is "); + xprintf (x ? "enabled\n" : "disabled\n"); + } + return 0; +} +#endif + +int +set_serial_speed_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("baud speed"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Set serial port baud rate"); + return 0; + } + if (mode == LONG_HELP) + { + set_serial_speed_cmd (USAGE); + long_help ("\ +The baud command sets the speed of the active serial port. It takes one\n\ +argument, which specifies the speed to which the port will be set.\n"); + example ("\ +baud 9600\n\ +Sets the speed of the active port to 9600 baud."); + return 0; + } + + if (argvect[1] == NULL || argvect[2] != NULL) + { + return set_serial_speed_cmd (USAGE); + } + else + { +#ifdef HAVE_BSP + int channel_id = bsp_set_debug_comm(-1); + int baud = str2int (argvect[1], 10); + + xprintf("Setting serial baud rate on channel %d to %d baud\n", + channel_id, baud); + + if (bsp_set_serial_baud(bsp_set_debug_comm(-1), + str2int (argvect[1], 10)) < 0) + xprintf("Invalid baud rate\n"); +#else + __set_baud_rate (str2int (argvect[1], 10)); +#endif + } + return 0; +} + + +int +set_term_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("terminal type"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Set the terminal type"); + return 0; + } + if (mode == LONG_HELP) + { + set_term_cmd (USAGE); + long_help ("\ +The terminal command sets the type of the current terminal to that specified\n\ +in the type argument. The only available terminal types are vt100 and dumb.\n\ +This is used by the line editor to determine how to update the terminal\n\ +display.\n"); + example ("\ +terminal dumb\n\ +Sets the type of the current terminal to a dumb terminal.\n"); + return 0; + } + + if (argvect[1] == NULL || argvect[2] != NULL) + set_term_cmd (USAGE); + else + set_term_name (argvect[1]); + return 0; +} + +int +reset_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("reset"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Reset the board (not on all architectures)."); + return 0; + } + if (mode == LONG_HELP) + { + reset_cmd (USAGE); + long_help ("\ +The reset command resets the board. This may not be implemented\n\ +on all architectures"); + return 0; + } + + if (argvect[1] != NULL) + { + reset_cmd (USAGE); + } + else + { + __reset (); + } + return 0; +} + +#if HAVE_USAGE +int +memusage_cmd (cmdmode_t mode) +{ + extern int sdata, _end; + + if (mode == USAGE) + { + usage ("usage"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Show monitor memory usage"); + return 0; + } + if (mode == LONG_HELP) + { + memusage_cmd (USAGE); + long_help ("\ +The usage command shows the amount of memory being used by the monitor,\n\ +broken down by category. Despite its name, it has nothing to do with the\n\ +usage of any other command.\n"); + return 0; + } + + if (argvect[1] != NULL) + { + return memusage_cmd (USAGE); + } + else + { + xprintf ("%d bytes were allocated with sbrk\n", (char *)sbrk (0) - (char *)&_end); + } + return 0; +} +#endif /* HAVE_USAGE */ + +int +disassemble_cmd (cmdmode_t mode) +{ +#ifdef DISASSEMBLER + int x; + + if (mode == USAGE) + { + usage ("disassemble [location]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Disassemble memory"); + return 0; + } + if (mode == LONG_HELP) + { + disassemble_cmd (USAGE); + long_help ("\ +The disassemble command disassembles the contents of memory. Because of the\n\ +way breakpoints are handled, all instructions are shown and breakpoints are\n\ +not visible in the disassembled code. The disassemble command takes zero\n\ +or one argument. When called with zero arguments, it starts disassembling\n\ +from the current (user program) pc. When called with a location, it starts\n\ +disassembling from the specified location. When called after a previous\n\ +call and with no arguments, it disassembles the next area of memory after\n\ +the one previously disassembled.\n"); + example ("\ +disassemble 45667000\n\ +Displays disassembled code starting at location 45667000."); + return 0; + } + if (argvect [1] != NULL && argvect[2] != NULL) + { + return disassemble_cmd (USAGE); + } + + if(argvect [1] != NULL) + str2addr (argvect [1], &last_pc); + for (x = 0; x < 10; x++) + last_pc = do_dis (&last_pc); + flush_dis (); +#else +#warning "DISASSEMBLER not implemented" + xprintf ("disassembler not available\n"); +#endif + + return 0; +} + +int +copy_cmd (cmdmode_t mode) +{ + mem_addr_t src, dst; + target_register_t size; + + if (mode == USAGE) + { + usage ("copy startaddr destaddr amount"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Copies one area of memory to another"); + return 0; + } + if (mode == LONG_HELP) + { + copy_cmd (USAGE); + long_help ("\ +The copy command is used to copy 'amount' bytes of memory\n\ +from 'startaddr' to 'destaddr'\n"); + example ("\ +copy 10000 20000 300\n\ +Copies 0x300 bytes of memory from 0x10000 to 0x20000."); + return 0; + } + if (argvect[1] == NULL || argvect[2] == NULL || argvect[3] == NULL + || argvect[4] != NULL) + { + return copy_cmd (USAGE); + } + str2addr (argvect[1], &src); + str2addr (argvect[2], &dst); + size = str2int (argvect[3], 16); + while (size > 0) + { + char buf[128]; + + int msize = (size > 128) ? 128 : size; + if (read_memory (&src, 1, msize, buf)) + { + xprintf ("Memory read failed\n"); + break; + } + if (write_memory (&dst, 1, msize, buf)) + { + xprintf ("Memory write failed\n"); + break; + } +#ifdef HAVE_BSP + bsp_flush_dcache((void *)dst.addr, msize); + bsp_flush_icache((void *)dst.addr, msize); +#endif + ADD_OFFSET (&src, &src, msize); + ADD_OFFSET (&dst, &dst, msize); + size -= msize; + } + return 0; +} + +#ifndef HAVE_BSP +int +set_program_args_cmd (cmdmode_t mode) +{ + int argc; + + if (mode == USAGE) + { + usage ("setargs [args]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Sets the program arguments passed to main()"); + return 0; + } + if (mode == LONG_HELP) + { + set_program_args_cmd (SHORT_HELP); + return 0; + } + for (argc = 1; argvect[argc] != NULL; argc++) + ; + __set_program_args (argc - 1, argvect + 1); + return 0; +} +#endif + + +int +fill_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("fill[.size] startaddress endaddress [value]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Fills memory with a specified value"); + return 0; + } + if (mode == LONG_HELP) + { + fill_cmd (USAGE); + long_help("\ +The fill command is used to fill a region of memory from 'startaddress'\n\ +to 'endaddress' with the value in 'value'. If no value is specificed,\n\ +it uses zero. It can take a size extension, which follows the command\n\ +name or partial command name without a space, and is a period followed\n\ +by the size of the writes that are used, in bits. Options are 8, 16,\n\ +32, and 64. Without a size extension, the fill command defaults to\n\ +changing 8 bits at a time.\n"); + example ("\ +fill.32 10000 20000 32\n\ +Fills the region between 0x10000 and 0x20000 with the 32 bit value 0x32."); + return 0; + } + if ((argvect[1] == NULL || argvect[2] == NULL) + || (argvect[3] != NULL && argvect[4] != NULL)) + { + fill_cmd (USAGE); + return 0; + } else { + mem_addr_t start,end; + char value[8]; + int size = get_cmd_size(); + int amt; + + if (size == -1) + /* + * Invalid size specified. + */ + return 0; + + if (argvect[3] != NULL) + { + hex2bytes (argvect[3], value, size); + } + else + { + hex2bytes ("0", value, size); + } + str2addr (argvect[1], &start); + str2addr (argvect[2], &end); + amt = MEM_ADDR_DIFF (end, start); + if (amt < 0) + { + xprintf ("Addresses in incorrect order\n"); + } + else + { + int x; + if (get_memory_display_mode ()) + { + /* Gotta swap this puppy. */ + int x; + + for (x = 0; x < (size / 2); x++) + { + char tmp = value[x]; + value [x] = value [size - 1 - x]; + value [size - 1 - x] = tmp; + } + } + + xprintf ("Writing %d units\n", amt / size + 1); + for (x = amt / size; x >= 0; x--) + { + if (write_memory (&start, size, 1, value)) + { + xprintf ("Memory write failed\n"); + break; + } + ADD_OFFSET (&start, &start, size); + } + } + } + return 0; +} + + +int +swapmem_cmd (cmdmode_t mode) +{ + int display_settings = 0; + + if (mode == USAGE) + { + usage ("swapmem [little|big]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Sets whether or not memory values are byte-swapped"); + return 0; + } + if (mode == LONG_HELP) + { + swapmem_cmd (USAGE); + + long_help("\ +The swapmem command is used to determine whether or not memory values are\n\ +displayed and written in little or big-endian byte order. By default, values\n\ +are read and written to match the byte order of the target CPU.\n\ +This command does not alter the CPU state in any way; it only changes the\n\ +way memory values are displayed and written within the monitor.\n"); + example("\ +swapmem \n\ +Displays the byte order that is currently in effect."); + return 0; + display_settings = 1; + } + else + { + if (argvect[1] != NULL && argvect[2] != NULL) + { + swapmem_cmd (USAGE); + return 0; + } + } + if (display_settings || argvect[1] == NULL) + { + if (get_memory_display_mode ()) + { + xprintf ("Memory values are read and written in little-endian byte order.\n"); + } + else + { + xprintf ("Memory values are read and written in big-endian byte order.\n"); + } + return 0; + } + if (strncmp (argvect[1], "little", strlen (argvect[1])) == 0) + { + set_memory_display_mode (1); + xprintf ("Memory values are now read and written in little-endian order.\n"); + } + else if (strncmp (argvect[1], "big", strlen (argvect[1])) == 0) + { + set_memory_display_mode (0); + xprintf ("Memory values are now read and written in big-endian order.\n"); + } + else + { + return swapmem_cmd (USAGE); + } + return 0; +} + +#ifdef MONITOR_CONTROL_INTERRUPTS +int +int_cmd (cmdmode_t mode) +{ + if (mode == USAGE) + { + usage ("interrupt [on|off]"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("Enables or disables interrupts within the monitor"); + return 0; + } + if (mode == LONG_HELP) + { + int_cmd (USAGE); + long_help("\ +The interrupt command is used to enable or disable interrupts while the\n\ +monitor is running."); + return 0; + } + if (argvect[1] != NULL && argvect[2] != NULL) + { + int_cmd (USAGE); + return 0; + } + if (argvect[1] != NULL) + { + if (strcmp (argvect[1], "on") == 0) + { + monitor_enable_interrupts (); + } + else if (strcmp (argvect[1], "off") == 0) + { + monitor_disable_interrupts (); + } + else + { + int_cmd (USAGE); + return 0; + } + } + xprintf ("Interrupts "); + if (monitor_interrupt_state ()) + { + xprintf ("enabled\n"); + } + else + { + xprintf ("disabled\n"); + } + return 0; +} +#endif + + +/* Table used by the crc32 function to calcuate the checksum. */ +static uint32 crc32_table[256]; +static int crc_initted = 0; + +static uint32 +crc32 (unsigned char *buf, int len, uint32 crc) +{ + if (! crc_initted) + { + /* Initialize the CRC table and the decoding table. */ + int i, j; + uint32 c; + + crc_initted = 1; + for (i = 0; i < 256; i++) + { + for (c = i << 24, j = 8; j > 0; --j) + c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1); + crc32_table[i] = c; + } + } + + while (len--) + { + crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255]; + buf++; + } + return crc; +} + + +int +checksumcmd (cmdmode_t mode) +{ + mem_addr_t start, end; + uint32 crc = 0xffffffff; + + if (mode == USAGE) + { + usage ("crc startaddr endaddr"); + return 0; + } + if (mode == SHORT_HELP) + { + short_help ("checksum an area of memory"); + return 0; + } + if (mode == LONG_HELP) + { + checksumcmd (USAGE); + long_help ("\ +The crc command is used to calculate a standard CRC32 checksum of the\n\ +specified memory region. The checksum is printed out as a hexadecimal\n\ +value."); + return 0; + } + if (argvect[1] == NULL || argvect[2] == NULL || argvect[3] != NULL) + { + return checksumcmd (USAGE); + } + + str2addr (argvect[1], &start); + str2addr (argvect[2], &end); + while (start.addr < end.addr) + { + char c[1024]; + int len = end.addr - start.addr; + if (len > sizeof(c)) + len = sizeof(c); + + read_memory (&start, 1, len, c); + crc = crc32 (c, len, crc); + start.addr += len; + } + xprintf("0x%08lx is checksum\n", crc); + return 0; +} + +char **argvect; +static char argvect_cmd[MAXLINELEN]; + +static char ** +buildargv (char *input) +{ + static char *arglist[256]; + int numargs = 0; + + while (1) + { + while (isspace ((unsigned char)*input) && *input != 0) + input++; + if (*input == 0) + break; + arglist [numargs++] = input; + while (!isspace ((unsigned char)*input) && *input != 0) + input++; + if (*input == 0) + break; + *(input++) = 0; + } + arglist [numargs] = NULL; + return arglist; +} + + +int +monitor_loop (void) +{ + int state = 1, return_value = 0; + + while (state == 1) + { + /* Get a line of input, putting it in the input buffer */ + lineedit (PROMPT, inbuf, sizeof (inbuf)); + xprintf ("\n"); + + if (switch_to_stub_flag) + { +#ifndef HAVE_BSP + switch_to_stub_flag = 0; +#endif + return transfer_to_stub (); + } + + /* Separate off the command from any other stuff on the line */ + + strcpy (argvect_cmd, inbuf); + argvect = buildargv (argvect_cmd); + + if (argvect[0] != NULL && argvect[0][0] != '\0') + { + char *ptr; + int command_number; + + strcpy (cmd, argvect[0]); + + /* Function to split off . delimiters. */ + ptr = strchr (cmd, '.'); + + if (ptr != NULL && *ptr == '.') + *ptr = '\0'; + + /* See if it's an alias. */ + command_number = alias_compare (cmd); + + /* Compare input to command list, check for conflicts. */ + if (command_number < 0) + command_number = command_compare (cmd); + + /* If we found a command, just run the function */ + if (command_number >= 0) + { + int status; + /* Execute the function, if the function returns a non-zero + value, break out of the loop and return. */ + status = (*cmdtab[command_number].function) (INVOCATION); + if (status) + { + state = 0; + if (status < 0) + return_value = 1; + } + } + else + { + /* If none of the commands or aliases match, complain. */ + xprintf ("Not a legal command\n"); + } + + if (inbuf[0] != '\0') + addHistoryCmd (inbuf); + } + } + return return_value; +} + + diff --git a/packages/cygmon/v2_0/misc/monitor_cmd.h b/packages/cygmon/v2_0/misc/monitor_cmd.h new file mode 100644 index 00000000..23535b68 --- /dev/null +++ b/packages/cygmon/v2_0/misc/monitor_cmd.h @@ -0,0 +1,126 @@ +//========================================================================== +// +// monitor_cmd.h +// +// Monitor command definitions for the CygMON ROM monitor +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: Monitor command definitions for the CygMON ROM monitor +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#ifndef MONITOR_CMD_H +#define MONITOR_CMD_H + +#ifndef ASM +typedef enum { + INVOCATION, USAGE, SHORT_HELP, LONG_HELP +} cmdmode_t; + +struct cmdentry +{ + char *alias; + char *cmd; + int (*function) (cmdmode_t); +}; + +extern struct cmdentry cmdtab []; + +extern int monitor_loop (void); + +extern char inbuf[]; + +extern char **argvect; + +typedef int (*srec_input_func_t)(void); + +extern int load_srec(srec_input_func_t inp_func); + +#ifdef USE_HELP +extern void usage (char *string); +extern void short_help (char *string); +extern void long_help (char *string); +extern void example (char *string); +#else +#define usage(x) no_help_usage () +#define short_help(x) no_help() +#define long_help(x) no_help() +#define example(x) +extern void no_help (void); +extern void no_help_usage (void); +#endif +extern int help_cmd (cmdmode_t mode); +extern int mem_cmd (cmdmode_t mode); + +extern int dump_cmd (cmdmode_t mode); +extern int ethaddr_cmd (cmdmode_t mode); +extern int ipaddr_cmd (cmdmode_t mode); +extern int tcpport_cmd (cmdmode_t mode); +extern int load_cmd (cmdmode_t mode); +extern int reg_cmd (cmdmode_t mode); +extern int go_cmd (cmdmode_t mode); +extern int othernames_cmd (cmdmode_t mode); +extern int step_cmd (cmdmode_t mode); +extern int transfer_cmd (cmdmode_t mode); +extern int timer_cmd (cmdmode_t mode); +extern int disassemble_cmd (cmdmode_t mode); +extern int breakpoint_cmd (cmdmode_t mode); +extern int clear_breakpoint_cmd (cmdmode_t mode); +extern int memusage_cmd (cmdmode_t mode); +extern int set_serial_port_cmd (cmdmode_t mode); +extern int set_serial_speed_cmd (cmdmode_t mode); +extern int version_cmd (cmdmode_t mode); +extern int cache_cmd (cmdmode_t mode); +extern int set_term_cmd (cmdmode_t mode); +extern int reset_cmd (cmdmode_t mode); +extern int copy_cmd (cmdmode_t mode); +extern int fill_cmd (cmdmode_t mode); +extern int set_program_args_cmd (cmdmode_t mode); +extern int swapmem_cmd (cmdmode_t mode); +extern int checksumcmd (cmdmode_t mode); +extern int int_cmd (cmdmode_t mode); +#endif + +#endif diff --git a/packages/cygmon/v2_0/misc/stub-tservice.h b/packages/cygmon/v2_0/misc/stub-tservice.h new file mode 100644 index 00000000..10aa56cb --- /dev/null +++ b/packages/cygmon/v2_0/misc/stub-tservice.h @@ -0,0 +1,54 @@ +//========================================================================== +// +// stub-tservice.h +// +// +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Placeholder diff --git a/packages/cygmon/v2_0/misc/tservice.h b/packages/cygmon/v2_0/misc/tservice.h new file mode 100644 index 00000000..1338b37e --- /dev/null +++ b/packages/cygmon/v2_0/misc/tservice.h @@ -0,0 +1,84 @@ +#ifndef __TSERVICE_H__ +#define __TSERVICE_H__ +//========================================================================== +// +// tservice.h +// +// These are the core functions are expected to be provided by the +// target dependent services. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +/* These are the core functions are expected to be provided by the + target dependent services. They are used by both cygmon and by + libstub +*/ + + +extern int read_memory (mem_addr_t *src, int size, int amt, char *dst); + +extern int write_memory (mem_addr_t *dst, int size, int amt, char *src); + + +#ifndef USE_ECOS_HAL_BREAKPOINTS +extern void set_breakpoint (struct bp *bp); +extern void clear_breakpoint (struct bp *bp); +#endif // USE_ECOS_HAL_BREAKPOINTS + +#ifndef HAVE_BSP +extern void set_pc (target_register_t pc); +#endif + +extern target_register_t next_step_pc (void); + +extern void enable_interrupts (void); + +#endif // __TSERVICE_H__ + + +extern void initialize_mon(void); diff --git a/packages/cygmon/v2_0/misc/unistd.h b/packages/cygmon/v2_0/misc/unistd.h new file mode 100644 index 00000000..6bbfe6eb --- /dev/null +++ b/packages/cygmon/v2_0/misc/unistd.h @@ -0,0 +1,54 @@ +//========================================================================== +// +// unistd.h +// +// Standard Unix/POSIX environment +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 1999-10-20 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +// Placeholder only diff --git a/packages/cygmon/v2_0/misc/utils.c b/packages/cygmon/v2_0/misc/utils.c new file mode 100644 index 00000000..04b6174a --- /dev/null +++ b/packages/cygmon/v2_0/misc/utils.c @@ -0,0 +1,376 @@ +//========================================================================== +// +// utils.c +// +// Monitor utilities. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: gthomas, dmoseley +// Date: 1999-10-20 +// Purpose: Monitor utilities. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include +#include +#include +#include +#ifdef HAVE_BSP +#include +#include +#include +#endif +#include "monitor.h" +#include "tservice.h" + +#if USE_CYGMON_PROTOTYPES +/* Use common prototypes */ +/* Some of the composed board.h files compose these + prototypes redundently, but if they dont, + these are the common definitions */ +#include "fmt_util.h" /* Interface to string formatting utilities */ +#include "generic-stub.h" /* from libstub */ +#endif /* USE_CYGMON_PROTOTYPES */ + +volatile int switch_to_stub_flag = 0; + +/* Input routine for the line editor. */ +int +input_char (void) +{ + int i; + + /* We have to drop the '+' characters on the floor + because gdb will send a '+' as the first character + when connecting to the target. If we waste time + echoing that, slow hw might get a uart overrun. */ + while ((i = xgetchar ()) == '+'); + + if (i == '$') + { + xungetchar ('$'); + switch_to_stub_flag = 1; + i = '\n'; + } + return i; +} + + +static char tohex_array[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + +#define tohex(X) (tohex_array[(X) & 15]) + +#ifdef HAVE_BSP +#define fromhex __hex +#else +static int +fromhex (a) +{ + int number = -1; + + if (a >= '0' && a <= '9') + number = a - '0'; + else if (a >= 'a' && a <= 'f') + number = a - 'a' + 10; + else if (a >= 'A' && a <= 'F') + number = a - 'A' + 10; + else + xprintf ("Invalid hex digit %c", a); + + return number; +} +#endif + + +static unsigned long long +str2ull (char *str, int base) +{ + unsigned long long l = 0; + + if (str[0] == '0' && str[1] == 'x') + { + str += 2 ; + base = 16 ; + } + + while (*str != '\0') + { + if (*str == '.') + str++; + else + l = (l * base) + fromhex(*str++); + } + + return l; +} + + +/* Converts a string to a long, base is the assumed base of the string */ + +target_register_t +str2int (char *str, int base) +{ + return str2ull(str, base); +} + +/* Converts a string to a double, input is a raw integer string + * of the given assumed base. */ +#if HAVE_DOUBLE_REGS +static double +str2double (char *str, int base) +{ + double d; + + switch (sizeof(double)) + { + case sizeof(unsigned int): + *((unsigned int *)&d) = str2ull(str, base); + break; +#if __LONG_MAX__ != __INT_MAX__ + case sizeof(unsigned long): + *((unsigned long *)&d) = str2ull(str, base); + break; +#endif +#if __LONG_LONG_MAX__ != __LONG_MAX__ + case sizeof(unsigned long long): + *((unsigned long long *)&d) = str2ull(str, base); + break; +#endif + default: + d = 0.0; + break; + } + return d; +} +#endif + +target_register_t +str2intlen (char *str, int base, int len) +{ + target_register_t number = 0; + + while ((len--) > 0 && *str != '\0') + number = number * base + fromhex (*(str++)); + + return number; +} + +int +hex2bytes (char *str, char *dest, int maxsize) +{ + int i; + char *ptr; + + for (i = 0; i < maxsize; i++) + dest[i] = 0; + maxsize--; + + // Don't try and convert 0x prefix + if ((str[0] == '0') && (str[1] == 'x')) + str += 2; + + ptr = str + strlen(str) - 1; + while (maxsize >= 0 && ptr >= str) + { + dest [maxsize] = fromhex(*ptr); + ptr--; + if (ptr >= str) + { + dest [maxsize--] |= fromhex(*ptr) * 16; + ptr--; + } + } + return 0; +} + + +/* Converts an unsigned long long to an ASCII string, adding leading + zeroes to pad space up to numdigs. */ +static int use_dots = 1; + +#define MAX_NUM_DIGS 51 + +static char * +ull2str (unsigned long long number, int base, int numdigs) +{ + static char string[MAX_NUM_DIGS+1]; + int dots, i; + char *ptr = string + MAX_NUM_DIGS; + + dots = (use_dots && base == 16); + + *(ptr--) = '\0'; + *(ptr--) = tohex (number % base); + i = 1; + number = number / base; + + while (number != 0) + { + if (dots && (i % 4) == 0) + *(ptr--) = '.'; + *(ptr--) = tohex (number % base); + i++; + number = number / base; + } + + if (numdigs == 0) + { + numdigs = i; + } + else + { + while(i < numdigs) + { + if (dots && (i % 4) == 0) + *(ptr--) = '.'; + *(ptr--) = '0'; + i++; + } + } + return ptr + 1; +} + + +char * +int2str (target_register_t number, int base, int numdigs) +{ + return ull2str((unsigned long long)number, base, numdigs); +} + +#if HAVE_DOUBLE_REGS +static char * +double2str(double d) +{ + switch(sizeof(double)) + { + case sizeof(unsigned int): + return ull2str(*((unsigned int *)&d), 16, sizeof(double) * 2); + break; +#if __LONG_MAX__ != __INT_MAX__ + case sizeof(unsigned long): + return ull2str(*((unsigned long *)&d), 16, sizeof(double) * 2); + break; +#endif +#if __LONG_LONG_MAX__ != __LONG_MAX__ + case sizeof(unsigned long long): + return ull2str(*((unsigned long long *)&d), 16, sizeof(double) * 2); + break; +#endif + } + return "....fixme..."; +} +#endif + +#ifndef NO_MALLOC +char * +strdup(const char *str) +{ + char *x = malloc (strlen (str) + 1); + if (x != NULL) + strcpy (x, str); + return x; +} +#endif + + +target_register_t +get_pc(void) +{ + return get_register(REG_PC); +} + + +#if defined(HAVE_BSP) && !defined(__ECOS__) +static int +get_register_type(regnames_t which) +{ + int i; + + for (i = 0; regtab[i].registername != NULL; i++) + if (regtab[i].registernumber == which) + return regtab[i].registertype; + return REGTYPE_INT; +} +#endif + +char *get_register_str (regnames_t which, int detail, int valid) +{ +#ifdef SPECIAL_REG_OUTPUT + char *res; + + if ((res = SPECIAL_REG_OUTPUT (which, detail)) != NULL) + { + return res; + } +#endif + if (valid == 0) + { + switch (sizeof (target_register_t)) + { + case 1: return "..."; + case 2: return "....."; + case 4: return "........."; + case 8: return "................."; + default: return "........."; + } + } + else + { + return int2str (get_register (which), 16, sizeof (target_register_t) * 2); + } +} + + +void +store_register (regnames_t which, char *string) +{ +#ifdef SPECIAL_REG_STORE + if (SPECIAL_REG_STORE(which, string)) + return; +#endif + put_register (which, str2int (string, 16)); +} + + +