PR 369/filesystem
	* Makefile.am, configure.ac: sample application to show the use of the
	DOSFS functions
	* fileio/Makefile.am, fileio/fileio.doc, fileio/init.c,
	fileio/system.h: New files.
This commit is contained in:
Jennifer Averett
2003-08-06 19:20:52 +00:00
parent ce275cffd6
commit ac0a2afe73
14 changed files with 1666 additions and 2 deletions

View File

@@ -1,3 +1,11 @@
2003-08-06 Thomas Doerfler<Thomas.Doerfler@imd-systems.de>
PR 369/filesystem
* Makefile.am, configure.ac: sample application to show the use of the
DOSFS functions
* fileio/Makefile.am, fileio/fileio.doc, fileio/init.c,
fileio/system.h: New files.
2003-06-04 Joel Sherrill <joel@OARcorp.com>
* pppd/system.h: Hack from Ralf to compile on all targets.

View File

@@ -15,7 +15,7 @@ FP_TESTS = paranoia
NET_TESTS = loopback
NET_TESTS += pppd
SUBDIRS = hello ticker base_sp unlimited minimum $(MP_TESTS) \
SUBDIRS = hello ticker base_sp unlimited minimum fileio $(MP_TESTS) \
$(CPLUSPLUS_TESTS) $(FP_TESTS) $(NET_TESTS)
AUTOMAKE_FILES = sample.am

View File

@@ -43,6 +43,7 @@ base_sp/Makefile
hello/Makefile
loopback/Makefile
minimum/Makefile
fileio/Makefile
paranoia/Makefile
ticker/Makefile
unlimited/Makefile

View File

@@ -0,0 +1,42 @@
##
## Makefile.am,v 1.9 2002/08/11 05:18:59 ralf Exp
##
SAMPLE = fileio
PGM = ${ARCH}/$(SAMPLE).exe
MANAGERS = io message semaphore
C_FILES = init.c
C_O_FILES = $(C_FILES:%.c=${ARCH}/%.$(OBJEXT))
H_FILES = system.h
noinst_HEADERS = $(H_FILES)
DOCTYPES = doc scn
DOCS = $(DOCTYPES:%=$(SAMPLE).%)
SRCS = $(DOCS) $(C_FILES) $(H_FILES)
OBJS = $(C_O_FILES)
PRINT_SRCS = $(DOCS)
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../../automake/compile.am
include $(top_srcdir)/../../../../automake/leaf.am
include $(top_srcdir)/sample.am
#
# (OPTIONAL) Add local stuff here using +=
#
all-local: ${ARCH} $(TMPINSTALL_FILES)
${PGM}: $(OBJS) $(LINK_FILES)
$(make-exe)
EXTRA_DIST = $(C_FILES) $(DOCS)
include $(top_srcdir)/../../../../automake/local.am

View File

@@ -0,0 +1,45 @@
#
# fileio.doc,v
#
# COPYRIGHT (c) 1989-1999.
# On-Line Applications Research Corporation (OAR).
#
# The license and distribution terms for this file may be
# found in the file LICENSE in this distribution or at
# http://www.OARcorp.com/rtems/license.html.
#
This sample implements some basic tests for the file systems
available. It provides the following functionality:
- perform basic file read/write tests on arbitrary file paths with
selectable I/O buffer size
- perform functions to evaluate FAT disk partition tables
- perform functions to mount FAT disks to the file system tree
A sample session might look like this:
- start this system
- select "p" (part_table_initialize) to read in the partition table of
first harddisk, enter the device name "/dev/hda", when prompted
- select "f" (fsmount) to try to mount the partitions
/dev/hda1../dev/hdc4 to corresponding mount points. Non-existant
partitions will report an error, but will not abort the tests
- select "w" (write file) to create a new file on the mounted disk (or
in the IMFS). Enter the file name (e.g. "/mnt/hda1/test_1M.txt"),
the file size (e.g. 64K or 2M) and the buffer size to use for the
write calls (e.g. 32 or 4K). Then the sample will try to write the
corresponding file and print the time consumed and data rate achived.
- select "r" (read file) to read a file (without displaying the
contents). It has similar parameters as "write file", but does not
query the file size.
- select "s" to call the rtems shell with its various capabilities.

View File

@@ -0,0 +1,600 @@
/* Init
*
* This routine is the initialization task for this test program.
* It is called from init_exec and has the responsibility for creating
* and starting the tasks that make up the test. If the time of day
* clock is required for the test, it should also be set to a known
* value by this function.
*
* Input parameters: NONE
*
* Output parameters: NONE
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* init.c,v 1.11 2000/06/12 15:00:12 joel Exp
*/
#define CONFIGURE_INIT
#include "system.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <rtems.h>
#include <fcntl.h>
#include <rtems/error.h>
#include <dosfs.h>
#include <ctype.h>
#include <rtems/ide_part_table.h>
#include <rtems/libcsupport.h>
#include <rtems/fsmount.h>
/*
* Table of FAT file systems that will be mounted
* with the "fsmount" function.
* See cpukit/libmisc/fsmount for definition of fields
*/
fstab_t fs_table[] = {
{
"/dev/hda1","/mnt/hda1",
&msdos_ops, RTEMS_FILESYSTEM_READ_WRITE,
FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0
},
{
"/dev/hda2","/mnt/hda2",
&msdos_ops, RTEMS_FILESYSTEM_READ_WRITE,
FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0
},
{
"/dev/hda3","/mnt/hda3",
&msdos_ops, RTEMS_FILESYSTEM_READ_WRITE,
FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0
},
{
"/dev/hda4","/mnt/hda4",
&msdos_ops, RTEMS_FILESYSTEM_READ_WRITE,
FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0
},
{
"/dev/hdc1","/mnt/hdc1",
&msdos_ops, RTEMS_FILESYSTEM_READ_WRITE,
FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0
},
{
"/dev/hdc2","/mnt/hdc2",
&msdos_ops, RTEMS_FILESYSTEM_READ_WRITE,
FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0
},
{
"/dev/hdc3","/mnt/hdc3",
&msdos_ops, RTEMS_FILESYSTEM_READ_WRITE,
FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0
},
{
"/dev/hdc4","/mnt/hdc4",
&msdos_ops, RTEMS_FILESYSTEM_READ_WRITE,
FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0
}
};
#ifndef MIN
#define MIN(a,b) (((a) > (b)) ? (b) : (a))
#endif
#define USE_SHELL
#ifdef USE_SHELL
#include <rtems/shell.h>
void fileio_start_shell(void)
{
printf(" =========================\n");
printf(" starting shell\n");
printf(" =========================\n");
shell_init("SHLL",0,100,"/dev/console",
B9600 | CS8,
0);
rtems_task_suspend(RTEMS_SELF);
}
#endif /* USE_SHELL */
void fileio_print_free_heap(void)
{
printf("--- unused dynamic memory: %lu bytes ---\n",
(unsigned long) malloc_free_space());
}
void fileio_part_table_initialize(void)
{
char devname[64];
rtems_status_code rc;
printf(" =========================\n");
printf(" Initialize partition table\n");
printf(" =========================\n");
fileio_print_free_heap();
printf(" Enter device to initialize ==>");
fgets(devname,sizeof(devname)-1,stdin);
while (devname[strlen(devname)-1] == '\n') {
devname[strlen(devname)-1] = '\0';
}
/*
* call function
*/
rc = rtems_ide_part_table_initialize(devname);
printf("result = %d\n",rc);
fileio_print_free_heap();
}
void fileio_fsmount(void)
{
rtems_status_code rc;
printf(" =========================\n");
printf(" Process fsmount table\n");
printf(" =========================\n");
fileio_print_free_heap();
/*
* call function
*/
rc = rtems_fsmount( fs_table,
sizeof(fs_table)/sizeof(fs_table[0]),
NULL);
printf("result = %d\n",rc);
fileio_print_free_heap();
}
void fileio_list_file(void)
{
char fname[1024];
char *buf_ptr = NULL;
unsigned32 flen = 0;
int fd = -1;
ssize_t n;
size_t buf_size = 100;
rtems_interval start_tick,curr_tick,ticks_per_sec;
printf(" =========================\n");
printf(" LIST FILE ... \n");
printf(" =========================\n");
fileio_print_free_heap();
printf(" Enter filename to list ==>");
fgets(fname,sizeof(fname)-1,stdin);
while (fname[strlen(fname)-1] == '\n') {
fname[strlen(fname)-1] = '\0';
}
/*
* allocate buffer of given size
*/
if (buf_size > 0) {
buf_ptr = malloc(buf_size);
}
if (buf_ptr != NULL) {
printf("\n Trying to open file \"%s\" for read\n",fname);
fd = open(fname,O_RDONLY);
if (fd < 0) {
printf("*** file open failed, errno = %d(%s)\n",errno,strerror(errno));
}
}
if (fd >= 0) {
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_tick);
do {
n = read(fd,buf_ptr,buf_size);
if (n > 0) {
write(1,buf_ptr,n);
flen += n;
}
} while (n > 0);
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &curr_tick);
printf("\n ******** End of file reached, flen = %d\n",flen);
close(fd);
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_sec);
printf("time elapsed for read: %g seconds\n",
((double)curr_tick-start_tick)/ticks_per_sec);
}
/*
* free buffer
*/
if (buf_ptr != NULL) {
free(buf_ptr);
}
fileio_print_free_heap();
}
/*
* convert a size string (like 34K or 12M) to actual byte count
*/
boolean fileio_str2size(const char *str,unsigned32 *res_ptr)
{
boolean failed = FALSE;
unsigned long size;
char suffix = ' ';
if (1 > sscanf(str,"%lu%c",&size,&suffix)) {
failed = TRUE;
}
else if (toupper(suffix) == 'K') {
size *= 1024;
}
else if (toupper(suffix) == 'M') {
size *= 1024UL*1024UL;
}
else if (isalpha(suffix)) {
failed = TRUE;
}
if (!failed) {
*res_ptr = size;
}
return failed;
}
void fileio_write_file(void)
{
char fname[1024];
char tmp_str[32];
unsigned32 file_size = 0;
unsigned32 buf_size = 0;
size_t curr_pos,bytes_to_copy;
int fd = -1;
ssize_t n;
rtems_interval start_tick,curr_tick,ticks_per_sec;
char *bufptr = NULL;
boolean failed = FALSE;
static const char write_test_string[] =
"The quick brown fox jumps over the lazy dog\n";
static const char write_block_string[] =
"\n----- end of write buffer ------\n";
printf(" =========================\n");
printf(" WRITE FILE ... \n");
printf(" =========================\n");
fileio_print_free_heap();
/*
* get number of ticks per second
*/
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_sec);
/*
* get path to file to write
*/
if (!failed) {
printf("Enter path/filename ==>");
fgets(fname,sizeof(fname)-1,stdin);
while (fname[strlen(fname)-1] == '\n') {
fname[strlen(fname)-1] = '\0';
}
if (0 == strlen(fname)) {
printf("*** no filename entered, aborted\n");
failed = TRUE;
}
}
/*
* get total file size to write
*/
if (!failed) {
printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
"Enter filesize to write ==>");
fgets(tmp_str,sizeof(tmp_str)-1,stdin);
failed = fileio_str2size(tmp_str,&file_size);
if (failed) {
printf("*** illegal file size, aborted\n");
}
}
/*
* get block size to write
*/
if (!failed) {
printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
"Enter block size to use for write calls ==>");
fgets(tmp_str,sizeof(tmp_str)-1,stdin);
failed = fileio_str2size(tmp_str,&buf_size);
if (failed) {
printf("*** illegal block size, aborted\n");
}
}
/*
* allocate buffer
*/
if (!failed) {
printf("... allocating %lu bytes of buffer for write data\n",
(unsigned long)buf_size);
bufptr = malloc(buf_size+1); /* extra space for terminating NUL char */
if (bufptr == NULL) {
printf("*** malloc failed, aborted\n");
failed = TRUE;
}
}
/*
* fill buffer with test pattern
*/
if (!failed) {
printf("... filling buffer with write data\n");
curr_pos = 0;
/*
* fill buffer with test string
*/
while (curr_pos < buf_size) {
bytes_to_copy = MIN(buf_size-curr_pos,
sizeof(write_test_string)-1);
memcpy(bufptr+curr_pos,write_test_string,bytes_to_copy);
curr_pos += bytes_to_copy;
}
/*
* put "end" mark at end of buffer
*/
bytes_to_copy = sizeof(write_block_string)-1;
if (buf_size >= bytes_to_copy) {
memcpy(bufptr+buf_size-bytes_to_copy,
write_block_string,
bytes_to_copy);
}
}
/*
* create file
*/
if (!failed) {
printf("... creating file \"%s\"\n",fname);
fd = open(fname,O_WRONLY | O_CREAT | O_TRUNC,S_IREAD|S_IWRITE);
if (fd < 0) {
printf("*** file create failed, errno = %d(%s)\n",errno,strerror(errno));
failed = TRUE;
}
}
/*
* write file
*/
if (!failed) {
printf("... writing to file\n");
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_tick);
curr_pos = 0;
do {
bytes_to_copy = buf_size;
do {
n = write(fd,
bufptr + (buf_size-bytes_to_copy),
MIN(bytes_to_copy,file_size-curr_pos));
if (n > 0) {
bytes_to_copy -= n;
curr_pos += n;
}
} while ((bytes_to_copy > 0) && (n > 0));
} while ((file_size > curr_pos) && (n > 0));
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &curr_tick);
if (n < 0) {
failed = TRUE;
printf("*** file write failed, "
"%lu bytes written, "
"errno = %d(%s)\n",
(unsigned long)curr_pos,errno,strerror(errno));
}
else {
printf("time elapsed for write: %g seconds\n",
((double)curr_tick-start_tick)/ticks_per_sec);
printf("write data rate: %g KBytes/second\n",
(((double)file_size) / 1024.0 /
(((double)curr_tick-start_tick)/ticks_per_sec)));
}
}
if (fd >= 0) {
printf("... closing file\n");
close(fd);
}
if (bufptr != NULL) {
printf("... deallocating buffer\n");
free(bufptr);
bufptr = NULL;
}
printf("\n ******** End of file write\n");
fileio_print_free_heap();
}
void fileio_read_file(void)
{
char fname[1024];
char tmp_str[32];
unsigned32 buf_size = 0;
size_t curr_pos;
int fd = -1;
ssize_t n;
rtems_interval start_tick,curr_tick,ticks_per_sec;
char *bufptr = NULL;
boolean failed = FALSE;
printf(" =========================\n");
printf(" READ FILE ... \n");
printf(" =========================\n");
fileio_print_free_heap();
/*
* get number of ticks per second
*/
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_sec);
/*
* get path to file to read
*/
if (!failed) {
printf("Enter path/filename ==>");
fgets(fname,sizeof(fname)-1,stdin);
while (fname[strlen(fname)-1] == '\n') {
fname[strlen(fname)-1] = '\0';
}
if (0 == strlen(fname)) {
printf("*** no filename entered, aborted\n");
failed = TRUE;
}
}
/*
* get block size to read
*/
if (!failed) {
printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
"Enter block size to use for read calls ==>");
fgets(tmp_str,sizeof(tmp_str)-1,stdin);
failed = fileio_str2size(tmp_str,&buf_size);
if (failed) {
printf("*** illegal block size, aborted\n");
}
}
/*
* allocate buffer
*/
if (!failed) {
printf("... allocating %lu bytes of buffer for write data\n",
(unsigned long)buf_size);
bufptr = malloc(buf_size+1); /* extra space for terminating NUL char */
if (bufptr == NULL) {
printf("*** malloc failed, aborted\n");
failed = TRUE;
}
}
/*
* open file
*/
if (!failed) {
printf("... opening file \"%s\"\n",fname);
fd = open(fname,O_RDONLY);
if (fd < 0) {
printf("*** file open failed, errno = %d(%s)\n",errno,strerror(errno));
failed = TRUE;
}
}
/*
* read file
*/
if (!failed) {
printf("... reading from file\n");
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_tick);
curr_pos = 0;
do {
n = read(fd,
bufptr,
buf_size);
if (n > 0) {
curr_pos += n;
}
} while (n > 0);
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &curr_tick);
if (n < 0) {
failed = TRUE;
printf("*** file read failed, "
"%lu bytes read, "
"errno = %d(%s)\n",
(unsigned long)curr_pos,errno,strerror(errno));
}
else {
printf("%lu bytes read\n",
(unsigned long)curr_pos);
printf("time elapsed for read: %g seconds\n",
((double)curr_tick-start_tick)/ticks_per_sec);
printf("read data rate: %g KBytes/second\n",
(((double)curr_pos) / 1024.0 /
(((double)curr_tick-start_tick)/ticks_per_sec)));
}
}
if (fd >= 0) {
printf("... closing file\n");
close(fd);
}
if (bufptr != NULL) {
printf("... deallocating buffer\n");
free(bufptr);
bufptr = NULL;
}
printf("\n ******** End of file read\n");
fileio_print_free_heap();
}
void fileio_menu (void)
{
char inbuf[10];
/*
* Wait for characters from console terminal
*/
for (;;) {
printf(" =========================\n");
printf(" RTEMS FILE I/O Test Menu \n");
printf(" =========================\n");
printf(" p -> part_table_initialize\n");
printf(" f -> mount all disks in fs_table\n");
printf(" l -> list file\n");
printf(" r -> read file\n");
printf(" w -> write file\n");
#ifdef USE_SHELL
printf(" s -> start shell\n");
#endif
printf(" Enter your selection ==>");
inbuf[0] = '\0';
fgets(inbuf,sizeof(inbuf),stdin);
switch (inbuf[0]) {
case 'l':
fileio_list_file ();
break;
case 'r':
fileio_read_file ();
break;
case 'w':
fileio_write_file ();
break;
case 'p':
fileio_part_table_initialize ();
break;
case 'f':
fileio_fsmount ();
break;
#ifdef USE_SHELL
case 's':
fileio_start_shell ();
break;
#endif
default:
printf("Selection `%c` not implemented\n",inbuf[0]);
break;
}
}
exit (0);
}
int menu_tid;
/*
* RTEMS Startup Task
*/
rtems_task
Init (rtems_task_argument ignored)
{
puts( "\n\n*** FILE I/O SAMPLE AND TEST ***" );
fileio_menu();
}

View File

@@ -0,0 +1,136 @@
/* system.h
*
* This include file contains information that is included in every
* function in the test set.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* system.h,v 1.13 2000/06/12 15:00:12 joel Exp
*/
#include <rtems.h>
/* functions */
rtems_task Init(
rtems_task_argument argument
);
/* global variables */
/* configuration information */
#include <bsp.h> /* for device driver prototypes */
#include <libchip/ata.h> /* for ata driver prototype */
#include <libchip/ide_ctrl.h> /* for general ide driver prototype */
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
#define CONFIGURE_HAS_OWN_DEVICE_DRIVER_TABLE
#ifdef CONFIGURE_INIT
rtems_driver_address_table Device_drivers[] =
{
CONSOLE_DRIVER_TABLE_ENTRY
,CLOCK_DRIVER_TABLE_ENTRY
#ifdef RTEMS_BSP_HAS_IDE_DRIVER
,IDE_CONTROLLER_DRIVER_TABLE_ENTRY
/* important: ATA driver must be after ide drivers */
,ATA_DRIVER_TABLE_ENTRY
#endif
};
#include <rtems/bdbuf.h>
rtems_bdbuf_config rtems_bdbuf_configuration[] = {
{512,128,NULL}
};
int rtems_bdbuf_configuration_size =( sizeof(rtems_bdbuf_configuration)
/sizeof(rtems_bdbuf_configuration[0]));
#endif
/*
* XXX: these values are higher than needed...
*/
#define CONFIGURE_MAXIMUM_TASKS 20
#define CONFIGURE_MAXIMUM_SEMAPHORES 20
#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 20
#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 20
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_EXTRA_TASK_STACKS (3 * RTEMS_MINIMUM_STACK_SIZE)
#include <confdefs.h>
/*
* Handy macros and static inline functions
*/
/*
* Macro to hide the ugliness of printing the time.
*/
#define print_time(_s1, _tb, _s2) \
do { \
printf( "%s%02d:%02d:%02d %02d/%02d/%04d%s", \
_s1, (_tb)->hour, (_tb)->minute, (_tb)->second, \
(_tb)->month, (_tb)->day, (_tb)->year, _s2 ); \
fflush(stdout); \
} while ( 0 )
/*
* Macro to print an task name that is composed of ASCII characters.
*
*/
#define put_name( _name, _crlf ) \
do { \
rtems_unsigned32 c0, c1, c2, c3; \
\
c0 = ((_name) >> 24) & 0xff; \
c1 = ((_name) >> 16) & 0xff; \
c2 = ((_name) >> 8) & 0xff; \
c3 = (_name) & 0xff; \
putchar( (char)c0 ); \
if ( c1 ) putchar( (char)c1 ); \
if ( c2 ) putchar( (char)c2 ); \
if ( c3 ) putchar( (char)c3 ); \
if ( (_crlf) ) \
putchar( '\n' ); \
} while (0)
/*
* static inline routine to make obtaining ticks per second easier.
*/
static inline rtems_unsigned32 get_ticks_per_second( void )
{
rtems_interval ticks_per_second;
(void) rtems_clock_get( RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second ); return ticks_per_second;
}
/*
* This allows us to view the "Test_task" instantiations as a set
* of numbered tasks by eliminating the number of application
* tasks created.
*
* In reality, this is too complex for the purposes of this
* example. It would have been easier to pass a task argument. :)
* But it shows how rtems_id's can sometimes be used.
*/
#define task_number( tid ) \
( rtems_get_index( tid ) - \
rtems_configuration_get_rtems_api_configuration()->number_of_initialization_tasks )
/* end of include file */