libcsupport/src/__assert.c

       1  /* __assert - small RTEMS Specific Implementation
           *
           * COPYRIGHT (  c ) 2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: __assert.c,  v 1.7 2009/11/29 13:35:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/bspIo.h>
          #include <rtems.h>
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE___ASSERT_FUNC )
          /*
           * Newlib 1.16.0 added this method. Together these provide an
           * RTEMS safe,   low memory implementation.
           */
      25  void __assert_func(  
           const char *file,  
           int line,  
           const char *func,  
           const char *failedexpr
           )
          {
           printk(  "assertion \"%s\" failed: file \"%s\",   line %d%s%s\n",  
           failedexpr,  
           file,  
           line,  
           (  func ) ? ",   function: " : "",  
           (  func ) ? func : ""
            );
           rtems_fatal_error_occurred(  0 );
          }
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE___ASSERT )
      44  void __assert(  
           const char *file,  
           int line,  
           const char *failedexpr
           )
          {
           __assert_func (  file,   line,   NULL,   failedexpr );
          }
          #endif

libcsupport/src/__getpid.c

       1  /*
           * Some C Libraries reference this routine since they think getpid is
           * a real system call.
           *
           * $Id: __getpid.c,  v 1.3 2004/04/15 13:24:45 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
      14  pid_t __getpid(  void )
          {
           return getpid(   );
          }

libcsupport/src/__gettod.c

       1  /*
           * gettimeofday(   ) - SVR4 and BSD4.3 extension required by Newlib
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: __gettod.c,  v 1.24 2010/06/28 22:14:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          
          #if defined(  RTEMS_NEWLIB )
          #include <sys/time.h>
          #include <errno.h>
          #include <rtems.h>
          #include <rtems/seterr.h>
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE_GETTIMEOFDAY )
          /*
           * NOTE: The solaris gettimeofday does not have a second parameter.
           */
      30  int gettimeofday(  
           struct timeval *tp,  
           void * __tz __attribute__(  (  unused ) )
           )
          {
           /* struct timezone* tzp = (  struct timezone* ) __tz; */
           if (   !tp  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           /*
           * POSIX does not seem to allow for not having a TOD so we just
           * grab the time of day.
           */
           _TOD_Get_timeval(   tp  );
          
           /*
           * Timezone information ignored by the OS proper. Per email
           * with Eric Norum,   this is how GNU/Linux,   Solaris,   and MacOS X
           * do it. This puts us in good company.
           */
          
           return 0;
          }
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__GETTIMEOFDAY_R )
          
          #include <sys/reent.h>
          
          /*
           * "Reentrant" version
           */
      62  int _gettimeofday_r(  
           struct _reent *ignored_reentrancy_stuff __attribute__(  (  unused ) ),  
           struct timeval *tp,  
           struct timezone *tzp
           )
          {
           return gettimeofday(   tp,   tzp  );
          }
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__GETTIMEOFDAY )
          /*
           * "System call" version
           */
          
      77  int _gettimeofday(  
           struct timeval *tp,  
           struct timezone *tzp
           )
          {
           return gettimeofday(   tp,   tzp  );
          }
          #endif
          
          #endif /* defined(  RTEMS_NEWLIB ) */

libcsupport/src/__times.c

       1  /*
           * times(   ) - POSIX 1003.1b 4.5.2 - Get Process Times
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: __times.c,  v 1.27 2010/07/10 13:48:47 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          
          #include <sys/times.h>
          #include <time.h>
          #include <sys/time.h>
          #include <errno.h>
          #include <rtems/seterr.h>
          #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           #include <rtems/score/timestamp.h>
          #endif
          
      29  clock_t _times(  
           struct tms *ptms
           )
          {
           rtems_interval ticks;
          
           if (   !ptms  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           /*
           * This call does not depend on TOD being initialized and can't fail.
           */
          
           ticks = rtems_clock_get_ticks_since_boot(   );
          
           /*
           * RTEMS technically has no notion of system versus user time
           * since there is no separation of OS from application tasks.
           * But we can at least make a distinction between the number
           * of ticks since boot and the number of ticks executed by this
           * this thread.
           */
          
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           {
           Timestamp_Control per_tick;
           uint32_t ticks;
           uint32_t fractional_ticks;
          
           _Timestamp_Set(  
           &per_tick,  
           rtems_configuration_get_microseconds_per_tick(   ) /
           TOD_MICROSECONDS_PER_SECOND,  
           (  rtems_configuration_get_nanoseconds_per_tick(   ) %
           TOD_NANOSECONDS_PER_SECOND )
            );
          
           _Timestamp_Divide(  
           &_Thread_Executing->cpu_time_used,  
           &per_tick,  
           &ticks,  
           &fractional_ticks
            );
           ptms->tms_utime = ticks;
           }
           #else
           ptms->tms_utime = _Thread_Executing->cpu_time_used;
           #endif
           ptms->tms_stime = ticks;
           ptms->tms_cutime = 0;
           ptms->tms_cstime = 0;
          
           return ticks;
          }
          
          /*
           * times(   )
           *
           * times(   ) system call wrapper for _times(   ) above.
           */
          
      90  clock_t times(  
           struct tms *ptms
           )
          {
           return _times(   ptms  );
          }
          
          /*
           * _times_r
           *
           * This is the Newlib dependent reentrant version of times(   ).
           */
          
          #if defined(  RTEMS_NEWLIB )
          
          #include <reent.h>
          
     107  clock_t _times_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           struct tms *ptms
           )
          {
           return _times(   ptms  );
          }
          #endif

libcsupport/src/__usrenv.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: __usrenv.c,  v 1.1 2008/09/17 16:12:01 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          
          /*
           * Global information for POSIX Process Environment Support
           */
          
          rtems_user_env_t rtems_global_user_env;
          rtems_user_env_t * rtems_current_user_env = &rtems_global_user_env;
          
          

libcsupport/src/_calloc_r.c

       1  /*
           * _calloc_r Implementation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: _calloc_r.c,  v 1.3 2009/09/30 06:15:39 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__CALLOC_R )
          #include <sys/reent.h>
          #include <stdlib.h>
          
      22  void *_calloc_r(  
           struct _reent *ignored __attribute__(  (  unused ) ),  
           size_t elements,  
           size_t size
           )
          {
           return calloc(   elements,   size  );
          }
          #endif

libcsupport/src/_free_r.c

       1  /*
           * _free_r Implementation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: _free_r.c,  v 1.3 2009/09/30 05:15:00 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__FREE_R )
          #include <sys/reent.h>
          #include <stdlib.h>
          
      22  void _free_r(  
           struct _reent *ignored __attribute__(  (  unused ) ),  
           void *ptr
           )
          {
           free(   ptr  );
          }
          #endif

libcsupport/src/_malloc_r.c

       1  /*
           * _malloc_r Implementation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: _malloc_r.c,  v 1.3 2009/09/30 05:15:00 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__MALLOC_R )
          #include <sys/reent.h>
          #include <stdlib.h>
          
      22  void *_malloc_r(  
           struct _reent *ignored __attribute__(  (  unused ) ),  
           size_t size
           )
          {
           return malloc(   size  );
          }
          #endif

libcsupport/src/_realloc_r.c

       1  /*
           * _realloc_r Implementation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: _realloc_r.c,  v 1.3 2009/09/30 06:15:39 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__REALLOC_R )
          #include <sys/reent.h>
          #include <stdlib.h>
          
      22  void *_realloc_r(  
           struct _reent *ignored __attribute__(  (  unused ) ),  
           void *ptr,  
           size_t size
           )
          {
           return realloc(   ptr,   size  );
          }
          #endif

libcsupport/src/_rename_r.c

       1  /*
           * _rename_r(   ) - POSIX 1003.1b - 5.3.4 - Rename a file
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: _rename_r.c,  v 1.7 2010/07/01 17:47:45 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__RENAME_R )
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <unistd.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      26  int _rename_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           const char *old,  
           const char *new
           )
          {
           int old_parent_pathlen;
           rtems_filesystem_location_info_t old_loc;
           rtems_filesystem_location_info_t old_parent_loc;
           rtems_filesystem_location_info_t new_parent_loc;
           int i;
           int result;
           const char *name;
           bool free_old_parentloc = false;
          
           /*
           * Get the parent node of the old path to be renamed. Find the parent path.
           */
          
           old_parent_pathlen = rtems_filesystem_dirname (   old  );
          
           if (   old_parent_pathlen == 0  )
           rtems_filesystem_get_start_loc(   old,   &i,   &old_parent_loc  );
           else {
           result = rtems_filesystem_evaluate_path(   old,   old_parent_pathlen,  
           RTEMS_LIBIO_PERMS_WRITE,  
           &old_parent_loc,  
           false  );
           if (   result != 0  )
           return -1;
          
           free_old_parentloc = true;
           }
          
           /*
           * Start from the parent to find the node that should be under it.
           */
          
           old_loc = old_parent_loc;
           name = old + old_parent_pathlen;
           name += rtems_filesystem_prefix_separators(   name,   strlen(   name  )  );
          
           result = rtems_filesystem_evaluate_relative_path(   name ,   strlen(   name  ),  
           0,   &old_loc,   false  );
           if (   result != 0  ) {
           if (   free_old_parentloc  )
           rtems_filesystem_freenode(   &old_parent_loc  );
           return -1;
           }
          
           /*
           * Get the parent of the new node we are renaming to.
           */
          
           rtems_filesystem_get_start_loc(   new,   &i,   &new_parent_loc  );
          
           result = (  *new_parent_loc.ops->evalformake_h )(   &new[i],   &new_parent_loc,   &name  );
           if (   result != 0  ) {
           rtems_filesystem_freenode(   &new_parent_loc  );
           if (   free_old_parentloc  )
           rtems_filesystem_freenode(   &old_parent_loc  );
           rtems_filesystem_freenode(   &old_loc  );
           return -1;
           }
          
           /*
           * Check to see if the caller is trying to rename across file system
           * boundaries.
           */
          
           if (   old_parent_loc.mt_entry != new_parent_loc.mt_entry  ) {
           rtems_filesystem_freenode(   &new_parent_loc  );
           if (   free_old_parentloc  )
           rtems_filesystem_freenode(   &old_parent_loc  );
           rtems_filesystem_freenode(   &old_loc  );
           rtems_set_errno_and_return_minus_one(   EXDEV  );
           }
          
           result = (  *new_parent_loc.ops->rename_h )(   &old_parent_loc,   &old_loc,   &new_parent_loc,   name  );
          
           rtems_filesystem_freenode(   &new_parent_loc  );
           if (   free_old_parentloc  )
           rtems_filesystem_freenode(   &old_parent_loc  );
           rtems_filesystem_freenode(   &old_loc  );
          
           return result;
          }
          #endif

libcsupport/src/access.c

       1  /*
           * access(   ) - POSIX 1003.1b 5.6.3 - File Accessibility
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: access.c,  v 1.5 2004/04/15 13:24:45 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          #include <fcntl.h>
          #include <sys/stat.h>
          
      22  int access(  
           const char *path,  
           int amode
           )
          {
           struct stat statbuf;
          
           if (   stat(  path,   &statbuf )  )
           return -1;
          
           if (   amode & R_OK  ) {
           if (  !(   statbuf.st_mode & S_IREAD  ) )
           return -1;
           }
          
           if (   amode & W_OK  ) {
           if (   !(   statbuf.st_mode & S_IWRITE  )  )
           return -1;
           }
          
           if (   amode & X_OK  ) {
           if (   !(   statbuf.st_mode & S_IEXEC  )  )
           return -1;
           }
          
           return 0;
          }

libcsupport/src/assoclocalbyname.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assoclocalbyname.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
      19  uint32_t rtems_assoc_local_by_name(  
           const rtems_assoc_t *ap,  
           const char *name
           )
          {
           const rtems_assoc_t *nap;
          
           nap = rtems_assoc_ptr_by_name(  ap,   name );
           if (  nap )
           return nap->local_value;
          
           return 0;
          }

libcsupport/src/assoclocalbyremote.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assoclocalbyremote.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
      19  uint32_t rtems_assoc_local_by_remote(  
           const rtems_assoc_t *ap,  
           uint32_t remote_value
           )
          {
           const rtems_assoc_t *nap;
          
           nap = rtems_assoc_ptr_by_remote(  ap,   remote_value );
           if (  nap )
           return nap->local_value;
          
           return 0;
          }

libcsupport/src/assoclocalbyremotebitfield.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assoclocalbyremotebitfield.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
          
      20  uint32_t rtems_assoc_local_by_remote_bitfield(  
           const rtems_assoc_t *ap,  
           uint32_t remote_value
           )
          {
           uint32_t b;
           uint32_t local_value = 0;
          
           for (  b = 1; b; b <<= 1 ) {
           if (  b & remote_value )
           local_value |= rtems_assoc_local_by_remote(  ap,   b );
           }
          
           return local_value;
          }

libcsupport/src/assocnamebad.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assocnamebad.c,  v 1.8 2009/09/15 09:29:55 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <inttypes.h>
          #include <stdio.h> /* sprintf */
          
          /*
           * what to return if a value is not found
           * this is not reentrant,   but it really shouldn't be invoked anyway
           */
          
          const char *
      24  rtems_assoc_name_bad(  
          #ifdef RTEMS_DEBUG
           uint32_t bad_value
          #else
           uint32_t bad_value __attribute(  (  unused ) )
          #endif
           )
          {
          #ifdef RTEMS_DEBUG
           static char bad_buffer[32];
          
           sprintf(  bad_buffer,   "< %" PRId32 "[0x%" PRIx32 " ] >",   bad_value,   bad_value );
          #else
           static char bad_buffer[40] = "<assocnamebad.c: : BAD NAME>";
          #endif
           return bad_buffer;
          }

libcsupport/src/assocnamebylocal.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assocnamebylocal.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
      19  const char *rtems_assoc_name_by_local(  
           const rtems_assoc_t *ap,  
           uint32_t local_value
           )
          {
           const rtems_assoc_t *nap;
          
           nap = rtems_assoc_ptr_by_local(  ap,   local_value );
           if (  nap )
           return nap->name;
          
           return rtems_assoc_name_bad(  local_value );
          }

libcsupport/src/assocnamebylocalbitfield.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assocnamebylocalbitfield.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
      19  char *rtems_assoc_name_by_local_bitfield(  
           const rtems_assoc_t *ap,  
           uint32_t value,  
           char *buffer
           )
          {
           uint32_t b;
          
           *buffer = 0;
          
           for (  b = 1; b; b <<= 1 ) {
           if (  b & value ) {
           if (  *buffer )
           strcat(  buffer,   " " );
           strcat(  buffer,   rtems_assoc_name_by_local(  ap,   b ) );
           }
           }
          
           return buffer;
          }

libcsupport/src/assocnamebyremote.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assocnamebyremote.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
          
      20  const char *rtems_assoc_name_by_remote(  
           const rtems_assoc_t *ap,  
           uint32_t remote_value
           )
          {
           const rtems_assoc_t *nap;
           nap = rtems_assoc_ptr_by_remote(  ap,   remote_value );
          
           if (  nap )
           return nap->name;
          
           return rtems_assoc_name_bad(  remote_value );
          }
          

libcsupport/src/assocnamebyremotebitfield.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assocnamebyremotebitfield.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
          
      20  char *rtems_assoc_name_by_remote_bitfield(  
           const rtems_assoc_t *ap,  
           uint32_t value,  
           char *buffer
           )
          {
           uint32_t b;
          
           *buffer = 0;
          
           for (  b = 1; b; b <<= 1 ) {
           if (  b & value ) {
           if (  *buffer )
           strcat(  buffer,   " " );
           strcat(  buffer,   rtems_assoc_name_by_remote(  ap,   b ) );
           }
           }
          
           return buffer;
          }

libcsupport/src/assocptrbylocal.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assocptrbylocal.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
      19  const rtems_assoc_t *rtems_assoc_ptr_by_local(  
           const rtems_assoc_t *ap,  
           uint32_t local_value
           )
          {
           const rtems_assoc_t *default_ap = 0;
          
           if (  rtems_assoc_is_default(  ap ) )
           default_ap = ap++;
          
           for (   ; ap->name; ap++ )
           if (  ap->local_value == local_value )
           return ap;
          
           return default_ap;
          }

libcsupport/src/assocptrbyname.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assocptrbyname.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
          
      20  const rtems_assoc_t *rtems_assoc_ptr_by_name(  
           const rtems_assoc_t *ap,  
           const char *name
           )
          {
           const rtems_assoc_t *default_ap = 0;
          
           if (  rtems_assoc_is_default(  ap ) )
           default_ap = ap++;
          
           for (   ; ap->name; ap++ )
           if (  strcmp(  ap->name,   name ) == 0 )
           return ap;
          
           return default_ap;
          }

libcsupport/src/assocptrbyremote.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assocptrbyremote.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
      19  const rtems_assoc_t *rtems_assoc_ptr_by_remote(  
           const rtems_assoc_t *ap,  
           uint32_t remote_value
           )
          {
           const rtems_assoc_t *default_ap = 0;
          
           if (  rtems_assoc_is_default(  ap ) )
           default_ap = ap++;
          
           for (   ; ap->name; ap++ )
           if (  ap->remote_value == remote_value )
           return ap;
          
           return default_ap;
          }

libcsupport/src/assocremotebylocal.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assocremotebylocal.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
      19  uint32_t rtems_assoc_remote_by_local(  
           const rtems_assoc_t *ap,  
           uint32_t local_value
           )
          {
           const rtems_assoc_t *nap;
          
           nap = rtems_assoc_ptr_by_local(  ap,   local_value );
           if (  nap )
           return nap->remote_value;
          
           return 0;
          }

libcsupport/src/assocremotebylocalbitfield.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assocremotebylocalbitfield.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
          
      20  uint32_t rtems_assoc_remote_by_local_bitfield(  
           const rtems_assoc_t *ap,  
           uint32_t local_value
           )
          {
           uint32_t b;
           uint32_t remote_value = 0;
          
           for (  b = 1; b; b <<= 1 )
           if (  b & local_value )
           remote_value |= rtems_assoc_remote_by_local(  ap,   b );
          
           return remote_value;
          }

libcsupport/src/assocremotebyname.c

       1  /*
           * assoc.c
           * rtems assoc routines
           *
           * $Id: assocremotebyname.c,  v 1.1 2007/03/26 22:31:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define INSIDE_ASSOC
          
          #include <rtems.h>
          #include <rtems/assoc.h>
          
          #include <string.h> /* strcat,   strcmp */
          
      19  uint32_t rtems_assoc_remote_by_name(  
           const rtems_assoc_t *ap,  
           const char *name
           )
          {
           const rtems_assoc_t *nap;
          
           nap = rtems_assoc_ptr_by_name(  ap,   name );
           if (  nap )
           return nap->remote_value;
          
           return 0;
          }

libcsupport/src/base_fs.c

       1  /*
           * Base file system initialization
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: base_fs.c,  v 1.23 2010/08/02 18:24:15 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          
          /*
           * Default mode for created files.
           */
          
          
          /*
           * rtems_filesystem_initialize
           *
           * Initialize the foundation of the file system. This is specified
           * by the structure rtems_filesystem_mount_table. The usual
           * configuration is a single instantiation of the IMFS or miniIMFS with
           * a single "/dev" directory in it.
           */
          
      36  void rtems_filesystem_initialize(   void  )
          {
           int status;
           const rtems_filesystem_mount_table_t *mt;
           rtems_filesystem_location_info_t loc;
          
           /*
           * Set the default umask to "022".
           */
          
           rtems_filesystem_umask = 022;
          
           /*
           * mount the first filesystem.
           */
           if (   rtems_filesystem_mount_table_size == 0  )
           rtems_fatal_error_occurred(   0xABCD0001  );
          
           mt = &rtems_filesystem_mount_table[0];
          
           status = mount(   mt->device,   mt->mount_point,   mt->type,   mt->fsoptions,   NULL  );
           if (   status == -1  )
           rtems_fatal_error_occurred(   0xABCD0002  );
          
           rtems_filesystem_link_counts = 0;
          
           /* setup the 'current' and 'root' directories
           *
           * NOTE: cloning the pathlocs is not strictly
           * necessary. Since we implicitely let
           * all threads that don't call
           * libio_set_private_env(   ) share the same
           * (  initial ) 'root' and 'current' locs,  
           * we (  also implicitely ) assume that the
           * root filesystem doesn't care about
           * reference counts.
           * I just inserted the code snippet below
           * to remind everybody of the fact by
           * making it more explicit...
           * Ideally,   every thread would have to
           * call either share_private_env(   ) or
           * set_private_env(   ) - but then: that's
           * gonna hit performance.
           *
           * Till Straumann,   10/25/2002
           */
           /* Clone the root pathloc */
           rtems_filesystem_evaluate_path(  "/",   1,   0,   &loc,   0 );
           rtems_filesystem_root = loc;
           /* One more clone for the current node */
           rtems_filesystem_evaluate_path(  "/",   1,   0,   &loc,   0 );
           rtems_filesystem_current = loc;
          
           /* Note: the global_env's refcnt doesn't matter
           * as the global env is never released
           */
          
          
           /*
           * Traditionally RTEMS devices are under "/dev" so install this directory.
           *
           * If the mkdir(   ) fails,   we can't print anything so just fatal error.
           *
           * NOTE: UNIX root is 755 and owned by root/root (  0/0 ). It is actually
           * created that way by the IMFS.
           */
          
           status = mkdir(   "/dev",   0777 );
           if (   status != 0  )
           rtems_fatal_error_occurred(   0xABCD0003  );
          
           /*
           * You can't mount another filesystem properly until the mount point
           * it will be mounted onto is created. Moreover,   if it is going to
           * use a device,   then it is REALLY unfair to attempt this
           * before device drivers are initialized. So we return via a base
           * filesystem image and nothing auto-mounted at this point.
           */
          }

libcsupport/src/calloc.c

       1  /*
           * calloc(   )
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: calloc.c,  v 1.3 2009/09/30 08:20:24 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE_CALLOC )
          #include "malloc_p.h"
          #include <stdlib.h>
          
      22  void *calloc(  
           size_t nelem,  
           size_t elsize
           )
          {
           register char *cptr;
           size_t length;
          
           MSBUMP(  calloc_calls,   1 );
          
           length = nelem * elsize;
           cptr = malloc(   length  );
           if (   cptr  )
           memset(   cptr,   '\0',   length  );
          
           MSBUMP(  malloc_calls,   (  uint32_t ) -1 ); /* subtract off the malloc */
          
           return cptr;
          }
          #endif

libcsupport/src/cfgetispeed.c

       1  /*
           * cfgetispeed(   ) - POSIX 1003.1b 7.1.3 - Baud Rate Functions
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cfgetispeed.c,  v 1.4 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #if defined(  RTEMS_NEWLIB )
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <errno.h>
          #include <termios.h>
          
      26  speed_t cfgetispeed(  
           const struct termios *tp
           )
          {
           return (  tp->c_cflag / (  CIBAUD / CBAUD ) ) & CBAUD;
          }
          #endif

libcsupport/src/cfgetospeed.c

       1  /*
           * cfgetospeed(   ) - POSIX 1003.1b 7.1.3 - Baud Rate Functions
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cfgetospeed.c,  v 1.4 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #if defined(  RTEMS_NEWLIB )
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <errno.h>
          #include <termios.h>
          
      26  speed_t cfgetospeed(  
           const struct termios *tp
           )
          {
           return tp->c_cflag & CBAUD;
          }
          #endif

libcsupport/src/cfsetispeed.c

       1  /*
           * cfsetispeed(   ) - POSIX 1003.1b 7.1.3 - Baud Rate Functions
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cfsetispeed.c,  v 1.6 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #if defined(  RTEMS_NEWLIB )
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <errno.h>
          #include <termios.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      29  int cfsetispeed(  
           struct termios *tp,  
           speed_t speed
           )
          {
           if (   speed & ~CBAUD  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           tp->c_cflag = (  tp->c_cflag & ~CIBAUD ) | (  speed * (  CIBAUD / CBAUD ) );
           return 0;
          }
          #endif

libcsupport/src/cfsetospeed.c

       1  /*
           * cfsetospeed(   ) - POSIX 1003.1b 7.1.3 - Baud Rate Functions
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cfsetospeed.c,  v 1.6 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #if defined(  RTEMS_NEWLIB )
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <errno.h>
          #include <termios.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      29  int cfsetospeed(  
           struct termios *tp,  
           speed_t speed
           )
          {
           if (   speed & ~CBAUD  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           tp->c_cflag = (  tp->c_cflag & ~CBAUD ) | speed;
           return 0;
          }
          #endif

libcsupport/src/chdir.c

       1  /*
           * chdir(   ) - POSIX 1003.1b - 5.2.1 - Change Current Working Directory
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: chdir.c,  v 1.15 2010/07/01 15:12:35 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          
          #include <unistd.h>
          #include <errno.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      26  int chdir(  
           const char *pathname
           )
          {
           rtems_filesystem_location_info_t loc;
           int result;
          
           if (   !pathname  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           /*
           * Get the node where we wish to go.
           */
           result = rtems_filesystem_evaluate_path(  
           pathname,   strlen(   pathname  ),   RTEMS_LIBIO_PERMS_SEARCH,   &loc,   true  );
           if (   result != 0  )
           return -1;
          
           /*
           * Verify you can change directory into this node.
           */
           if (   (  *loc.ops->node_type_h )(   &loc  ) != RTEMS_FILESYSTEM_DIRECTORY  ) {
           rtems_filesystem_freenode(   &loc  );
           rtems_set_errno_and_return_minus_one(   ENOTDIR  );
           }
          
           rtems_filesystem_freenode(   &rtems_filesystem_current  );
          
           rtems_filesystem_current = loc;
          
           return 0;
          }

libcsupport/src/chmod.c

       1  /*
           * chmod(   ) - POSIX 1003.1b 5.6.4 - Change File Modes
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: chmod.c,  v 1.14 2010/07/01 15:12:36 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <errno.h>
          #include <unistd.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      28  int chmod(  
           const char *path,  
           mode_t mode
           )
          {
           int status;
           rtems_filesystem_location_info_t loc;
           int result;
          
           status = rtems_filesystem_evaluate_path(   path,   strlen(   path  ),   0,   &loc,   true  );
           if (   status != 0  )
           return -1;
          
           result = (  *loc.handlers->fchmod_h )(   &loc,   mode  );
          
           rtems_filesystem_freenode(   &loc  );
          
           return result;
          }

libcsupport/src/chown.c

       1  /*
           * chown(   ) - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: chown.c,  v 1.14 2010/07/01 17:22:03 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/stat.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/libio.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      27  int _chown_helper(  
           const char *path,  
           uid_t owner,  
           gid_t group,  
           int follow_link
           )
          {
           rtems_filesystem_location_info_t loc;
           int result;
          
           if (   rtems_filesystem_evaluate_path(   path,   strlen(   path  ),   0x00,   &loc,   follow_link  )  )
           return -1;
          
           result = (  *loc.ops->chown_h )(   &loc,   owner,   group  );
          
           rtems_filesystem_freenode(   &loc  );
          
           return result;
          }
          
      47  int chown(  
           const char *path,  
           uid_t owner,  
           gid_t group
           )
          {
           return _chown_helper(   path,   owner,   group,   true  );
          }

libcsupport/src/chroot.c

       1  /*
           * chroot(   ) - Change Root Directory
           * Author: fernando.ruiz@ctv.es
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: chroot.c,  v 1.9 2009/06/12 01:53:32 ccj Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          
          #include <unistd.h>
          #include <errno.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      27  int chroot(  
           const char *pathname
           )
          {
           int result;
           rtems_filesystem_location_info_t loc;
          
           /* an automatic call to new private env the first time */
           if (  rtems_current_user_env == &rtems_global_user_env ) {
           rtems_libio_set_private_env(   ); /* try to set a new private env*/
           if (  rtems_current_user_env == &rtems_global_user_env ) /* not ok */
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
           }
          
           result = chdir(  pathname );
           if (  result ) {
           rtems_set_errno_and_return_minus_one(   errno  );
           }
          
           /* clone the new root location */
           if (  rtems_filesystem_evaluate_path(  ".",   1,   0,   &loc,   0 ) ) {
           /* our cwd has changed,   though - but there is no easy way of return :-(   */
           rtems_set_errno_and_return_minus_one(   errno  );
           }
           rtems_filesystem_freenode(  &rtems_filesystem_root );
           rtems_filesystem_root = loc;
          
           return 0;
          }

libcsupport/src/close.c

       1  /*
           * close(   ) - POSIX 1003.1b 6.3.1 - Close a File
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: close.c,  v 1.14 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          
      20  int close(  
           int fd
           )
          {
           rtems_libio_t *iop;
           rtems_status_code rc;
          
           rtems_libio_check_fd(  fd );
           iop = rtems_libio_iop(  fd );
           rtems_libio_check_is_open(  iop );
          
           rc = RTEMS_SUCCESSFUL;
           rc = (  *iop->pathinfo.handlers->close_h )(   iop  );
          
           rtems_filesystem_freenode(   &iop->pathinfo  );
           rtems_libio_free(   iop  );
          
           return rc;
          }
          
          /*
           * _close_r
           *
           * This is the Newlib dependent reentrant version of close(   ).
           */
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__CLOSE_R )
          
          #include <reent.h>
          
      50  int _close_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           int fd
           )
          {
           return close(   fd  );
          }
          #endif

libcsupport/src/closedir.c

       1  /*
           * closedir(   ) - POSIX 1003.1b - XXX
           *
           * This was copied from Newlib 1.8.0.
           *
           *
           * Copyright (  c ) 1983 Regents of the University of California.
           * 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.
           * 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.
           */
          
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          static char sccsid[] = "@(  # )closedir.c 5.9 (  Berkeley ) 2/23/91";
          #endif /* LIBC_SCCS and not lint */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_CLOSEDIR
          
          #include <sys/types.h>
          #include <dirent.h>
          #include <stdlib.h>
          #include <unistd.h>
          #include <errno.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          /*
           * close a directory.
           */
          int
      62  closedir(  
           DIR *dirp  )
          {
           int fd;
          
           if (   !dirp  )
           rtems_set_errno_and_return_minus_one(   EBADF  );
          
           fd = dirp->dd_fd;
           dirp->dd_fd = -1;
           dirp->dd_loc = 0;
           (  void )free(  (  void * )dirp->dd_buf );
           (  void )free(  (  void * )dirp );
           return(  close(  fd ) );
          }
          
          #endif

libcsupport/src/creat.c

       1  /*
           * $Id: creat.c,  v 1.4 2009/03/10 07:12:50 ralf Exp $
           */
          
          /* creat(   ) "system call" */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_CREAT
          /* This is needed by f2c and therefore the SPEC benchmarks. */
          
          #include <fcntl.h>
          
          int
      17  creat (  const char *path,   mode_t mode )
          {
           return open (  path,   O_WRONLY | O_CREAT | O_TRUNC,   mode );
          }
          #endif

libcsupport/src/ctermid.c

       1  /*
           * ctermid(   ) - POSIX 1003.1b 4.7.1 - Generate Terminal Pathname
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ctermid.c,  v 1.8 2010/08/27 18:07:03 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #if defined(  RTEMS_NEWLIB )
          
          #include <stdio.h>
          #include <string.h>
          
          static char *ctermid_name = "/dev/console";
          
      26  char *ctermid(  
           char *s
           )
          {
           if (   !s  )
           return ctermid_name;
          
           /*
           * We have no way of knowing the length of the user provided buffer.
           * It may not be large enough but there is no way to know that. :(  
           * So this is a potential buffer owerrun that we can do nothing about.
           */
           strcpy(   s,   ctermid_name  );
           return s;
          }
          
          #endif

libcsupport/src/dup.c

       1  /*
           * dup(   ) - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: dup.c,  v 1.4 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          #include <fcntl.h>
          
      21  int dup(  
           int fildes
           )
          {
           return fcntl(   fildes,   F_DUPFD,   0  );
          }

libcsupport/src/dup2.c

       1  /*
           * dup2(   ) - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: dup2.c,  v 1.6 2004/04/18 06:05:34 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          #include <fcntl.h>
          
          #include <rtems/libio_.h>
          
      23  int dup2(  
           int fildes,  
           int fildes2
           )
          {
           int status;
           struct stat buf;
          
           /*
           * If fildes is not valid,   then fildes2 should not be closed.
           */
          
           status = fstat(   fildes,   &buf  );
           if (   status == -1  )
           return -1;
          
           /*
           * If fildes2 is not valid,   then we should not do anything either.
           */
          
           status = fstat(   fildes2,   &buf  );
           if (   status == -1  )
           return -1;
          
           /*
           * This fcntl handles everything else.
           */
          
           return fcntl(   fildes,   F_DUPFD,   fildes2  );
          }

libcsupport/src/envlock.c

       1  /*
           * Author: Till Straumann <strauman@slac.stanford.edu>,   3/2002
           *
           * $Id: envlock.c,  v 1.5 2010/04/30 08:55:40 sh Exp $
           */
          
          /* provide locking for the global environment 'environ' */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <sys/reent.h>
          
          #include <assert.h>
          
          /*
           * NOTES:
           * - although it looks like a classical multiple-readers / single writer (  MRSW )
           * locking problem,   we still use a single lock for the following reasons:
           * 1 ) newlib has no provision / hook for calling different locking routines
           * from setenv/putenv and getenv,   respectively.
           * 2 ) MRSW involves calling several semaphore-primitives,   even in the most
           * likely case of a first-reader's access. This probably takes more CPU
           * time than just waiting until another reader is done; environment
           * access is fast.
           * - the lock implementation must allow nesting (  same thread may call
           * lock-lock-unlock-unlock ).
           * - NEWLIB-1.8.2 has an ugly BUG: if environ is NULL,   _findenv_r(   ) bails
           * out leaving the lock held :-(  
           *
           * Used by the following functions:
           * findenv_r(   ),   setenv_r(   ),   and unsetenv_r(   ) which are called by
           * getenv(   ),   getenv_r(   ),   setenv(   ),   and unsetenv(   ).
           *
           */
          
          #if defined(  ENVLOCK_DEDIDCATED_MUTEX )
          static rtems_id envLock=0;
          
          static void
      43  __rtems_envlock_init(  void )
          {
           extern char **environ;
           rtems_status_code rc;
          
           if (  envLock ) /* already initialized */
           return;
          
           assert(  environ && "MUST have non-NULL 'environ' due to newlib bug" );
          
           rc = rtems_semaphore_create(  
           rtems_build_name(  'E',  'N',  'V',  'S' ),  
           1,  
           RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,  
           0,  
           &envLock );
           if (  RTEMS_SUCCESSFUL!=rc )
           rtems_fatal_error_occurred(  rc );
          }
          
          void
      64  __env_lock(  struct _reent *r )
          {
           /* Do lazy init */
           if (  !envLock )
           __rtems_envlock_init(   );
           /*
           * Must not use a semaphore before pre-tasking hook is called.
           * - it will corrupt memory :-(  
           */
          
           if (  _Thread_Executing )
           rtems_semaphore_obtain(  envLock,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
          }
          
          void
      79  __env_unlock(  struct _reent *r )
          {
           /*
           * Must not use a semaphore before pre-tasking hook is called.
           * - it will corrupt memory :-(  
           */
           if (  _Thread_Executing )
           rtems_semaphore_release(  envLock );
          }
          #else
          
          /*
           * Reuse the libio mutex -- it is always initialized before we
           * could possibly run.
           */
          
          #include <rtems/libio_.h>
          
          void
      98  __env_lock(  struct _reent *r __attribute__(  (  unused ) ) )
          {
           rtems_libio_lock(   );
          }
          
          void
     104  __env_unlock(  struct _reent *r __attribute__(  (  unused ) ) )
          {
           rtems_libio_unlock(   );
          }
          #endif

libcsupport/src/error.c

       1  /*
           * report errors and panics to RTEMS' stderr.
           * Currently just used by RTEMS monitor.
           *
           * $Id: error.c,  v 1.23 2010/06/28 22:13:55 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * These routines provide general purpose error reporting.
           * rtems_error reports an error to stderr and allows use of
           * printf style formatting. A newline is appended to all messages.
           *
           * error_flag can be specified as any of the following:
           *
           * RTEMS_ERROR_ERRNO -- include errno text in output
           * RTEMS_ERROR_PANIC -- halts local system after output
           * RTEMS_ERROR_ABORT -- abort after output
           *
           * It can also include a rtems_status value which can be OR'd
           * with the above flags. *
           *
           * EXAMPLE
           * #include <rtems.h>
           * #include <rtems/error.h>
           * rtems_error(  0,   "stray interrupt %d",   intr );
           *
           * EXAMPLE
           * if (  (  status = rtems_task_create(  ... ) ) != RTEMS_SUCCCESSFUL )
           * {
           * rtems_error(  status | RTEMS_ERROR_ABORT,  
           * "could not create task" );
           * }
           *
           * EXAMPLE
           * if (  (  fd = open(  pathname,   O_RDNLY ) ) < 0 )
           * {
           * rtems_error(  RTEMS_ERROR_ERRNO,   "open of '%s' failed",   pathname );
           * goto failed;
           * }
           */
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          
          #include <rtems/error.h>
          #include <rtems/assoc.h>
          #include <inttypes.h>
          #include <stdio.h>
          #include <stdarg.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h> /* _exit(   ) */
          
          int rtems_panic_in_progress;
          
          const rtems_assoc_t rtems_status_assoc[] = {
           { "successful completion",   RTEMS_SUCCESSFUL,   0 },  
           { "returned from a thread",   RTEMS_TASK_EXITTED,   0 },  
           { "multiprocessing not configured",   RTEMS_MP_NOT_CONFIGURED,   0 },  
           { "invalid object name",   RTEMS_INVALID_NAME,   0 },  
           { "invalid object id",   RTEMS_INVALID_ID,   0 },  
           { "too many",   RTEMS_TOO_MANY,   0 },  
           { "timed out waiting",   RTEMS_TIMEOUT,   0 },  
           { "object deleted while waiting",   RTEMS_OBJECT_WAS_DELETED,   0 },  
           { "specified size was invalid",   RTEMS_INVALID_SIZE,   0 },  
           { "address specified is invalid",   RTEMS_INVALID_ADDRESS,   0 },  
           { "number was invalid",   RTEMS_INVALID_NUMBER,   0 },  
           { "item has not been initialized",   RTEMS_NOT_DEFINED,   0 },  
           { "resources still outstanding",   RTEMS_RESOURCE_IN_USE,   0 },  
           { "request not satisfied",   RTEMS_UNSATISFIED,   0 },  
           { "thread is in wrong state",   RTEMS_INCORRECT_STATE,   0 },  
           { "thread already in state",   RTEMS_ALREADY_SUSPENDED,   0 },  
           { "illegal on calling thread",   RTEMS_ILLEGAL_ON_SELF,   0 },  
           { "illegal for remote object",   RTEMS_ILLEGAL_ON_REMOTE_OBJECT,   0 },  
           { "called from wrong environment",   RTEMS_CALLED_FROM_ISR,   0 },  
           { "invalid thread priority",   RTEMS_INVALID_PRIORITY,   0 },  
           { "invalid date/time",   RTEMS_INVALID_CLOCK,   0 },  
           { "invalid node id",   RTEMS_INVALID_NODE,   0 },  
           { "directive not configured",   RTEMS_NOT_CONFIGURED,   0 },  
           { "not owner of resource",   RTEMS_NOT_OWNER_OF_RESOURCE ,   0 },  
           { "directive not implemented",   RTEMS_NOT_IMPLEMENTED,   0 },  
           { "RTEMS inconsistency detected",   RTEMS_INTERNAL_ERROR,   0 },  
           { "could not get enough memory",   RTEMS_NO_MEMORY,   0 },  
           { "driver IO error",   RTEMS_IO_ERROR,   0 },  
           { "internal multiprocessing only",   THREAD_STATUS_PROXY_BLOCKING,   0 },  
           { 0,   0,   0 },  
          };
          
          
      95  const char *rtems_status_text(  
           rtems_status_code status
           )
          {
           return rtems_assoc_name_by_local(  rtems_status_assoc,   status );
          }
          
          
     103  static int rtems_verror(  
           rtems_error_code_t error_flag,  
           const char *printf_format,  
           va_list arglist
           )
          {
           int local_errno = 0;
           int chars_written = 0;
           rtems_status_code status;
          
           if (  error_flag & RTEMS_ERROR_PANIC ) {
           if (  rtems_panic_in_progress++ )
           _Thread_Disable_dispatch(   ); /* disable task switches */
          
           /* don't aggravate things */
           if (  rtems_panic_in_progress > 2 )
           return 0;
           }
          
           (  void ) fflush(  stdout ); /* in case stdout/stderr same */
          
           status = error_flag & ~RTEMS_ERROR_MASK;
           if (  error_flag & RTEMS_ERROR_ERRNO ) /* include errno? */
           local_errno = errno;
          
           #if defined(  RTEMS_MULTIPROCESSING )
           if (  _System_state_Is_multiprocessing )
           fprintf(  stderr,   "[%" PRIu32 "] ",   _Configuration_MP_table->node );
           #endif
          
           chars_written += vfprintf(  stderr,   printf_format,   arglist );
          
           if (  status )
           chars_written +=
           fprintf(  stderr,   " (  status: %s )",   rtems_status_text(  status ) );
          
           if (  local_errno ) {
           if (  (  local_errno > 0 ) && *strerror(  local_errno ) )
           chars_written += fprintf(  stderr,   " (  errno: %s )",   strerror(  local_errno ) );
           else
           chars_written += fprintf(  stderr,   " (  unknown errno=%d )",   local_errno );
           }
          
           chars_written += fprintf(  stderr,   "\n" );
          
           (  void ) fflush(  stderr );
          
           return chars_written;
          }
          
          
          /*
           * Report an error.
           * error_flag is as above; printf_format is a normal
           * printf(  3 ) format string,   with its concommitant arguments.
           *
           * Returns the number of characters written.
           */
          
     162  int rtems_error(  
           rtems_error_code_t error_flag,  
           const char *printf_format,  
           ...
           )
          {
           va_list arglist;
           int chars_written;
          
           va_start(  arglist,   printf_format );
           chars_written = rtems_verror(  error_flag,   printf_format,   arglist );
           va_end(  arglist );
          
           if (  error_flag & RTEMS_ERROR_PANIC ) {
           rtems_error(  0,   "fatal error,   exiting" );
           _exit(  errno );
           }
           if (  error_flag & RTEMS_ERROR_ABORT ) {
           rtems_error(  0,   "fatal error,   aborting" );
           abort(   );
           }
          
           return chars_written;
          }
          
          /*
           * rtems_panic is shorthand for rtems_error(  RTEMS_ERROR_PANIC,   ... )
           */
          
     191  void rtems_panic(  
           const char *printf_format,  
           ...
           )
          {
           va_list arglist;
          
           va_start(  arglist,   printf_format );
           (  void ) rtems_verror(  RTEMS_ERROR_PANIC,   printf_format,   arglist );
           va_end(  arglist );
          
           rtems_error(  0,   "fatal error,   exiting" );
           _exit(  errno );
          }

libcsupport/src/eval.c

       1  /*
           * rtems_filesystem_evaluate_path(   )
           *
           * Routine to seed the evaluate path routine.
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: eval.c,  v 1.18 2010/08/26 19:57:19 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      24  int rtems_filesystem_evaluate_relative_path(  
           const char *pathname,  
           size_t pathnamelen,  
           int flags,  
           rtems_filesystem_location_info_t *pathloc,  
           int follow_link
           )
          {
           int result;
           rtems_filesystem_node_types_t type;
          
           #if defined(  RTEMS_DEBUG )
           /*
           * Verify Input parameters that should never be bad unless someone
           * is implementing a new filesystem and has bugs.
           */
           if (   !pathname  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           if (   !pathloc  )
           rtems_set_errno_and_return_minus_one(   EIO  );
           #endif
          
           result = (  *pathloc->ops->evalpath_h )(   pathname,   pathnamelen,   flags,   pathloc  );
          
           /*
           * Get the Node type and determine if you need to follow the link or
           * not.
           */
          
           if (   (  result == 0 ) && follow_link  ) {
          
           type = (  *pathloc->ops->node_type_h )(   pathloc  );
          
           if (   (   type == RTEMS_FILESYSTEM_HARD_LINK  ) ||
           (   type == RTEMS_FILESYSTEM_SYM_LINK  )  ) {
          
           /* what to do with the valid node pathloc points to
           * if eval_link_h fails?
           * Let the FS implementation deal with this case. It
           * should probably free pathloc in either case:
           * - if the link evaluation fails,   it must free the
           * original (  valid ) pathloc because we are going
           * to return -1 and hence the FS generics won't
           * cleanup pathloc.
           * - if the link evaluation is successful,   the updated
           * pathloc will be passed up (  and eventually released ).
           * Hence,   the (  valid ) originial node that we submit to
           * eval_link_h(   ) should be released by the handler.
           */
          
           result = (  *pathloc->ops->eval_link_h )(   pathloc,   flags  );
           }
           }
          
           return result;
          }
          
      82  int rtems_filesystem_evaluate_path(  
           const char *pathname,  
           size_t pathnamelen,  
           int flags,  
           rtems_filesystem_location_info_t *pathloc,  
           int follow_link
           )
          {
           int i = 0;
          
           #if defined(  RTEMS_DEBUG )
           /*
           * Verify Input parameters that should never be bad unless someone
           * is implementing a new filesystem and has bugs.
           */
           if (   !pathname  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           if (   !pathloc  )
           rtems_set_errno_and_return_minus_one(   EIO  );
           #endif
          
           /*
           * Evaluate the path using the optable evalpath.
           */
          
           rtems_filesystem_get_start_loc(   pathname,   &i,   pathloc  );
          
           /*
           * We evaluation the path relative to the start location we get got.
           */
           return rtems_filesystem_evaluate_relative_path(   &pathname[i],  
           pathnamelen - i,  
           flags,  
           pathloc,  
           follow_link  );
          }
          
     120  int rtems_filesystem_dirname(  
           const char *pathname
           )
          {
           int len = strlen(   pathname  );
          
           while (   len  ) {
           len--;
           if (   rtems_filesystem_is_separator(   pathname[len]  )  )
           break;
           }
          
           return len;
          }
          
     135  int rtems_filesystem_prefix_separators(  
           const char *pathname,  
           int pathnamelen
           )
          {
           /*
           * Eat any separators at start of the path.
           */
           int stripped = 0;
           while (   *pathname && pathnamelen && rtems_filesystem_is_separator(   *pathname  )  )
           {
           pathname++;
           pathnamelen--;
           stripped++;
           }
           return stripped;
          }

libcsupport/src/fchdir.c

       1  /*
           * fchdir(   ) - compatible with SVr4,   4.4BSD and X/OPEN - Change Directory
           *
           * COPYRIGHT (  c ) 1989-2000.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: fchdir.c,  v 1.11 2010/07/01 15:12:36 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          #include <sys/stat.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      27  int fchdir(  
           int fd
           )
          {
           rtems_libio_t *iop;
           rtems_filesystem_location_info_t loc,   saved;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(  iop );
          
           /*
           * Now process the fchmod(   ).
           */
          
           rtems_libio_check_permissions(   iop,   LIBIO_FLAGS_READ  );
          
           /*
           * Verify you can change directory into this node.
           */
          
           if (   (  *iop->pathinfo.ops->node_type_h )(   &iop->pathinfo  ) !=
           RTEMS_FILESYSTEM_DIRECTORY  ) {
           rtems_set_errno_and_return_minus_one(   ENOTDIR  );
           }
          
          
           /*
           * FIXME : I feel there should be another call to
           * actually take into account the extra reference to
           * this node which we are making here. I can
           * see the freenode interface but do not see
           * allocnode node interface. It maybe node_type.
           *
           * FIXED: T.Straumann: it is evaluate_path(   )
           * but note the race condition. Threads who
           * share their rtems_filesystem_current better
           * be synchronized!
           */
          
           saved = rtems_filesystem_current;
           rtems_filesystem_current = iop->pathinfo;
          
           /* clone the current node */
           if (  rtems_filesystem_evaluate_path(  ".",   1,   0,   &loc,   0 ) ) {
           /* cloning failed; restore original and bail out */
           rtems_filesystem_current = saved;
           return -1;
           }
           /* release the old one */
           rtems_filesystem_freenode(   &saved  );
          
           rtems_filesystem_current = loc;
          
           return 0;
          }

libcsupport/src/fchmod.c

       1  /*
           * fchmod(   ) - POSIX 1003.1b 5.6.4 - Change File Modes
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: fchmod.c,  v 1.13 2010/07/01 15:12:36 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          #include <sys/stat.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      27  int fchmod(  
           int fd,  
           mode_t mode
           )
          {
           rtems_libio_t *iop;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(  iop );
          
           /*
           * Now process the fchmod(   ).
           */
          
           rtems_libio_check_permissions(   iop,   LIBIO_FLAGS_WRITE  );
          
           return (  *iop->pathinfo.handlers->fchmod_h )(   &iop->pathinfo,   mode  );
          }

libcsupport/src/fchown.c

       1  /*
           * fchown(   ) - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: fchown.c,  v 1.2 2010/07/01 15:12:36 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/stat.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/libio.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      27  int fchown(  
           int fd,  
           uid_t owner,  
           gid_t group
           )
          {
           rtems_libio_t *iop;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(  iop );
          
           rtems_libio_check_permissions(   iop,   LIBIO_FLAGS_WRITE  );
          
           return (  *iop->pathinfo.ops->chown_h )(   &iop->pathinfo,   owner,   group  );
          }

libcsupport/src/fcntl.c

       1  /*
           * fcntl(   ) - POSIX 1003.1b 6.5.2 - File Control
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: fcntl.c,  v 1.27 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          #include <unistd.h>
          #include <fcntl.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          
      26  static int vfcntl(  
           int fd,  
           int cmd,  
           va_list ap
           )
          {
           rtems_libio_t *iop;
           rtems_libio_t *diop;
           int fd2;
           int flags;
           int mask;
           int ret = 0;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(  iop );
          
           /*
           * Now process the fcntl(   ).
           */
          
           /*
           * This switch should contain all the cases from POSIX.
           */
          
           switch (   cmd  ) {
           case F_DUPFD: /* dup */
           fd2 = va_arg(   ap,   int  );
           if (   fd2  )
           diop = rtems_libio_iop(   fd2  );
           else {
           /* allocate a file control block */
           diop = rtems_libio_allocate(   );
           if (   diop == 0  ) {
           ret = -1;
           break;
           }
           }
          
           diop->flags = iop->flags;
           diop->pathinfo = iop->pathinfo;
           ret = (  int ) (  diop - rtems_libio_iops );
           break;
          
           case F_GETFD: /* get f_flags */
           ret = (  (  iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC ) != 0 );
           break;
          
           case F_SETFD: /* set f_flags */
           /*
           * Interpret the third argument as the "close on exec(   )" flag.
           * If this argument is 1,   then the file descriptor is to be closed
           * if a new process is exec(   )'ed. Since RTEMS does not support
           * processes,   then we can ignore this one except to make
           * F_GETFD work.
           */
          
           if (   va_arg(   ap,   int  )  )
           iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC;
           else
           iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC;
           break;
          
           case F_GETFL: /* more flags (  cloexec ) */
           ret = rtems_libio_to_fcntl_flags(   iop->flags  );
           break;
          
           case F_SETFL:
           flags = rtems_libio_fcntl_flags(   va_arg(   ap,   int  )  );
           mask = LIBIO_FLAGS_NO_DELAY | LIBIO_FLAGS_APPEND;
          
           /*
           * XXX If we are turning on append,   should we seek to the end?
           */
          
           iop->flags = (  iop->flags & ~mask ) | (  flags & mask );
           break;
          
           case F_GETLK:
           errno = ENOTSUP;
           ret = -1;
           break;
          
           case F_SETLK:
           errno = ENOTSUP;
           ret = -1;
           break;
          
           case F_SETLKW:
           errno = ENOTSUP;
           ret = -1;
           break;
          
           case F_SETOWN: /* for sockets. */
           errno = ENOTSUP;
           ret = -1;
           break;
          
           case F_GETOWN: /* for sockets. */
           errno = ENOTSUP;
           ret = -1;
           break;
          
           default:
           errno = EINVAL;
           ret = -1;
           break;
           }
          
           /*
           * If we got this far successfully,   then we give the optional
           * filesystem specific handler a chance to process this.
           */
          
           if (  ret >= 0 ) {
           int err = (  *iop->pathinfo.handlers->fcntl_h )(   cmd,   iop  );
           if (  err ) {
           errno = err;
           ret = -1;
           }
           }
           return ret;
          }
          
     150  int fcntl(  
           int fd,  
           int cmd,  
           ...
           )
          {
           int ret;
           va_list ap;
           va_start(   ap,   cmd  );
           ret = vfcntl(  fd,  cmd,  ap );
           va_end(  ap );
           return ret;
          }
          
          
          /*
           * _fcntl_r
           *
           * This is the Newlib dependent reentrant version of fcntl(   ).
           */
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE_FCNTL_R )
          
          #include <reent.h>
          
     175  int _fcntl_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           int fd,  
           int cmd,  
           int arg
           )
          {
           return fcntl(   fd,   cmd,   arg  );
          }
          #endif

libcsupport/src/fdatasync.c

       1  /*
           * fdatasync(   ) - POSIX 1003.1b 6.6.2 - Synchronize the Data of a File
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: fdatasync.c,  v 1.12 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      23  int fdatasync(  
           int fd
           )
          {
           rtems_libio_t *iop;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(  iop );
           rtems_libio_check_permissions(   iop,   LIBIO_FLAGS_WRITE  );
          
           /*
           * Now process the fdatasync(   ).
           */
          
           return (  *iop->pathinfo.handlers->fdatasync_h )(   iop  );
          }

libcsupport/src/flockfile.c

       1  /*
           * Copyright (  c ) 2009 by
           * Ralf Corsépius,   Ulm,   Germany. All rights reserved.
           *
           * Permission to use,   copy,   modify,   and distribute this software
           * is freely granted,   provided that this notice is preserved.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE_FLOCKFILE ) && defined(  HAVE_DECL_FLOCKFILE )
          
          #include <stdio.h>
          
          /* This is a non-functional stub */
      18  void flockfile(  FILE* file )
          {
          }
          
          #endif

libcsupport/src/fpathconf.c

       1  /*
           * fpathconf(   ) - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: fpathconf.c,  v 1.9 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          #include <unistd.h>
          #include <errno.h>
          
      24  long fpathconf(  
           int fd,  
           int name
           )
          {
           long return_value;
           rtems_libio_t *iop;
           rtems_filesystem_limits_and_options_t *the_limits;
          
           rtems_libio_check_fd(  fd );
           iop = rtems_libio_iop(  fd );
           rtems_libio_check_is_open(  iop );
           rtems_libio_check_permissions(  iop,   LIBIO_FLAGS_READ );
          
           /*
           * Now process the information request.
           */
          
           the_limits = &iop->pathinfo.mt_entry->pathconf_limits_and_options;
          
           switch (   name  ) {
           case _PC_LINK_MAX:
           return_value = the_limits->link_max;
           break;
           case _PC_MAX_CANON:
           return_value = the_limits->max_canon;
           break;
           case _PC_MAX_INPUT:
           return_value = the_limits->max_input;
           break;
           case _PC_NAME_MAX:
           return_value = the_limits->name_max;
           break;
           case _PC_PATH_MAX:
           return_value = the_limits->path_max;
           break;
           case _PC_PIPE_BUF:
           return_value = the_limits->pipe_buf;
           break;
           case _PC_CHOWN_RESTRICTED:
           return_value = the_limits->posix_chown_restrictions;
           break;
           case _PC_NO_TRUNC:
           return_value = the_limits->posix_no_trunc;
           break;
           case _PC_VDISABLE:
           return_value = the_limits->posix_vdisable;
           break;
           case _PC_ASYNC_IO:
           return_value = the_limits->posix_async_io;
           break;
           case _PC_PRIO_IO:
           return_value = the_limits->posix_prio_io;
           break;
           case _PC_SYNC_IO:
           return_value = the_limits->posix_sync_io;
           break;
           default:
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           break;
           }
          
           return return_value;
          }

libcsupport/src/free.c

       1  /*
           * calloc(   )
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: free.c,  v 1.10 2010/08/25 14:30:01 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include "malloc_p.h"
          #include <stdlib.h>
          
      22  void free(  
           void *ptr
           )
          {
           MSBUMP(  free_calls,   1 );
          
           if (   !ptr  )
           return;
          
           /*
           * Do not attempt to free memory if in a critical section or ISR.
           */
           if (   _System_state_Is_up(  _System_state_Get(   ) ) &&
           !malloc_is_system_state_OK(   )  ) {
           malloc_deferred_free(  ptr );
           return;
           }
          
           /*
           * If configured,   update the statistics
           */
           if (   rtems_malloc_statistics_helpers  )
           (  *rtems_malloc_statistics_helpers->at_free )(  ptr );
          
           if (   !_Protected_heap_Free(   RTEMS_Malloc_Heap,   ptr  )  ) {
           printk(   "Program heap: free of bad pointer %p -- range %p - %p \n",  
           ptr,  
           RTEMS_Malloc_Heap->area_begin,  
           RTEMS_Malloc_Heap->area_end
            );
           }
          
          }
          #endif

libcsupport/src/freenode.c

       1  /*
           * freenode(   )
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: freenode.c,  v 1.2 2010/07/01 15:12:37 jennifer Exp $
           */
          
          #include <stdlib.h>
          #include <rtems/libio_.h>
          
      17  void rtems_filesystem_freenode(   rtems_filesystem_location_info_t *_node  )
          {
           _node->ops->freenod_h(  _node  );
          }

libcsupport/src/fstat.c

       1  /*
           * fstat(   ) - POSIX 1003.1b 5.6.2 - Get File Status
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: fstat.c,  v 1.14 2010/07/30 22:36:32 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/stat.h>
          #include <unistd.h>
          #include <string.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      25  int fstat(  
           int fd,  
           struct stat *sbuf
           )
          {
           rtems_libio_t *iop;
          
           /*
           * Check to see if we were passed a valid pointer.
           */
           if (   !sbuf  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           /*
           * Now process the stat(   ) request.
           */
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_fd(   fd  );
           rtems_libio_check_is_open(  iop );
          
           /*
           * Zero out the stat structure so the various support
           * versions of stat don't have to.
           */
           memset(   sbuf,   0,   sizeof(  struct stat )  );
          
           return (  *iop->pathinfo.handlers->fstat_h )(   &iop->pathinfo,   sbuf  );
          }
          
          /*
           * _fstat_r
           *
           * This is the Newlib dependent reentrant version of fstat(   ).
           */
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE_FSTAT_R )
          
          #include <reent.h>
          
      64  int _fstat_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           int fd,  
           struct stat *buf
           )
          {
           return fstat(   fd,   buf  );
          }
          #endif

libcsupport/src/fsync.c

       1  /*
           * fsync(   ) - POSIX 1003.1b 6.6.1 - Synchronize the State of a File
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: fsync.c,  v 1.13 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      23  int fsync(  
           int fd
           )
          {
           rtems_libio_t *iop;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(  iop );
           rtems_libio_check_permissions(   iop,   LIBIO_FLAGS_WRITE  );
          
           /*
           * Now process the fsync(   ).
           */
          
           return (  *iop->pathinfo.handlers->fsync_h )(   iop  );
          }

libcsupport/src/ftruncate.c

       1  /*
           * ftruncate(   ) - Truncate a File to the Specified Length
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ftruncate.c,  v 1.14 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          #include <errno.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      24  int ftruncate(  
           int fd,  
           off_t length
           )
          {
           rtems_libio_t *iop;
           rtems_filesystem_location_info_t loc;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(  iop );
          
           /*
           * Now process the ftruncate(   ) request.
           */
          
           /*
           * Make sure we are not working on a directory
           */
          
           loc = iop->pathinfo;
           if (   (  *loc.ops->node_type_h )(   &loc  ) == RTEMS_FILESYSTEM_DIRECTORY  )
           rtems_set_errno_and_return_minus_one(   EISDIR  );
          
           rtems_libio_check_permissions(   iop,   LIBIO_FLAGS_WRITE  );
          
           return (  *iop->pathinfo.handlers->ftruncate_h )(   iop,   length  );
          }

libcsupport/src/ftrylockfile.c

       1  /*
           * Copyright (  c ) 2009 by
           * Ralf Corsépius,   Ulm,   Germany. All rights reserved.
           *
           * Permission to use,   copy,   modify,   and distribute this software
           * is freely granted,   provided that this notice is preserved.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE_FTRYLOCKFILE ) && defined(  HAVE_DECL_FTRYLOCKFILE )
          
          #include <stdio.h>
          #include <rtems/seterr.h>
          #include <errno.h>
          
          /* This is a non-functional stub */
      20  int ftrylockfile(  FILE* file )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }
          
          #endif

libcsupport/src/funlockfile.c

       1  /*
           * Copyright (  c ) 2009 by
           * Ralf Corsépius,   Ulm,   Germany. All rights reserved.
           *
           * Permission to use,   copy,   modify,   and distribute this software
           * is freely granted,   provided that this notice is preserved.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE_FUNLOCKFILE ) && defined(  HAVE_DECL_FUNLOCKFILE )
          
          #include <stdio.h>
          
          /* This is a non-functional stub */
      18  void funlockfile(  FILE* file )
          {
          }
          
          #endif

libcsupport/src/getchark.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: getchark.c,  v 1.1 2008/09/22 21:47:04 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/bspIo.h>
          
      19  int getchark(  void )
          {
           if (   BSP_poll_char  )
           return (  *BSP_poll_char )(   );
          
           return -1;
          }

libcsupport/src/getcwd.c

       1  /*
           * Copyright (  c ) 1989,   1991 The Regents of the University of California.
           * 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.
           * 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.
           *
           * Copied from newlib 1.8.1. RTEMS can not build all of the contents
           * of the UNIX directory but we need this routine.
           *
           * $Id: getcwd.c,  v 1.6 2008/12/05 06:42:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_GETCWD
          
          /*
           * Added these when moved to RTEMS
           */
          
          #define _stat stat
          #define _opendir opendir
          #define _fstat fstat
          #define _readdir readdir
          #define _closedir closedir
          
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          static char sccsid[] = "@(  # )getcwd.c 5.11 (  Berkeley ) 2/24/91";
          #endif /* LIBC_SCCS and not lint */
          
          #include <sys/stat.h>
          #include <errno.h>
          #include <dirent.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          #include <reent.h>
          #include <_syslist.h>
          
          #define bcopy(  a,  b,  c ) memmove (  b,  a,  c )
          
          #define ISDOT(  dp ) \
           (  dp->d_name[0] == '.' && (  dp->d_name[1] == '\0' || \
           (  dp->d_name[1] == '.' && dp->d_name[2] == '\0' ) ) )
          
          #ifndef _REENT_ONLY
      76  
          char *
          getcwd (  
           char *pt,  
           size_t size )
          {
           register struct dirent *dp;
           register DIR *dir = 0;
           register dev_t dev;
           register ino_t ino;
           register int first;
           register char *bpt,   *bup;
           struct stat s;
           dev_t root_dev;
           ino_t root_ino;
           size_t ptsize,   upsize;
           int save_errno;
           char *ept,   *eup,   *up;
          
           /*
           * If no buffer specified by the user,   allocate one as necessary.
           * If a buffer is specified,   the size has to be non-zero. The path
           * is built from the end of the buffer backwards.
           */
          
           if (  pt )
           {
           ptsize = 0;
           if (  !size )
           {
           errno = EINVAL;
           return (  char * ) NULL;
           }
           ept = pt + size;
           }
           else
           {
           if (  !(  pt = (  char * ) malloc (  ptsize = 1024 - 4 ) ) )
           {
           return (  char * ) NULL;
           }
           ept = pt + ptsize;
           }
           bpt = ept - 1;
           *bpt = '\0';
          
           /*
           * Allocate bytes (  1024 - malloc space ) for the string of "../"'s.
           * Should always be enough (  it's 340 levels ). If it's not,   allocate
           * as necessary. Special * case the first stat,   it's ".",   not "..".
           */
          
           if (  !(  up = (  char * ) malloc (  upsize = 1024 - 4 ) ) )
           {
           goto err;
           }
           eup = up + MAXPATHLEN;
           bup = up;
           up[0] = '.';
           up[1] = '\0';
          
           /* Save root values,   so know when to stop. */
           if (  stat (  "/",   &s ) )
           goto err;
           root_dev = s.st_dev;
           root_ino = s.st_ino;
          
           errno = 0; /* XXX readdir has no error return. */
          
           for (  first = 1;; first = 0 )
           {
           /* Stat the current level. */
           if (  _stat (  up,   &s ) )
           goto err;
          
           /* Save current node values. */
           ino = s.st_ino;
           dev = s.st_dev;
          
           /* Check for reaching root. */
           if (  root_dev == dev && root_ino == ino )
           {
           *--bpt = '/';
           /*
           * It's unclear that it's a requirement to copy the
           * path to the beginning of the buffer,   but it's always
           * been that way and stuff would probably break.
           */
           (  void ) bcopy (  bpt,   pt,   ept - bpt );
           free (  up );
           return pt;
           }
          
           /*
           * Build pointer to the parent directory,   allocating memory
           * as necessary. Max length is 3 for "../",   the largest
           * possible component name,   plus a trailing NULL.
           */
          
           if (  bup + 3 + MAXNAMLEN + 1 >= eup )
           {
           if (  !(  up = (  char * ) realloc (  up,   upsize *= 2 ) ) )
           {
           goto err;
           }
           bup = up;
           eup = up + upsize;
           }
           *bup++ = '.';
           *bup++ = '.';
           *bup = '\0';
          
           /* Open and stat parent directory. */
           if (  !(  dir = _opendir (  up ) ) || _fstat (  __dirfd (  dir ),   &s ) )
           goto err;
          
           /* Add trailing slash for next directory. */
           *bup++ = '/';
          
           /*
           * If it's a mount point,   have to stat each element because
           * the inode number in the directory is for the entry in the
           * parent directory,   not the inode number of the mounted file.
           */
          
           save_errno = 0;
           if (  s.st_dev == dev )
           {
           for (  ;; )
           {
           if (  !(  dp = _readdir (  dir ) ) )
           goto notfound;
           if (  dp->d_ino == ino )
           break;
           }
           }
           else
           for (  ;; )
           {
           if (  !(  dp = _readdir (  dir ) ) )
           goto notfound;
           if (  ISDOT (  dp ) )
           continue;
           bcopy (  dp->d_name,   bup,   strlen (  dp->d_name ) + 1 );
          
           /* Save the first error for later. */
           if (  stat (  up,   &s ) )
           {
           if (  !save_errno )
           save_errno = errno;
           errno = 0;
           continue;
           }
           if (  s.st_dev == dev && s.st_ino == ino )
           break;
           }
          
           /*
           * Check for length of the current name,   preceding slash,  
           * leading slash.
           */
          
           if (  bpt - pt <= strlen (  dp->d_name ) + (  first ? 1 : 2 ) )
           {
           size_t len,   off;
          
           if (  !ptsize )
           {
           errno = ERANGE;
           goto err;
           }
           off = bpt - pt;
           len = ept - bpt;
           if (  !(  pt = (  char * ) realloc (  pt,   ptsize *= 2 ) ) )
           {
           goto err;
           }
           bpt = pt + off;
           ept = pt + ptsize;
           (  void ) bcopy (  bpt,   ept - len,   len );
           bpt = ept - len;
           }
           if (  !first )
           *--bpt = '/';
           bpt -= strlen (  dp->d_name );
           bcopy (  dp->d_name,   bpt,   strlen (  dp->d_name ) );
           (  void ) _closedir (  dir );
           dir = 0;
          
           /* Truncate any file name. */
           *bup = '\0';
           }
          
          notfound:
           /*
           * If readdir set errno,   use it,   not any saved error; otherwise,  
           * didn't find the current directory in its parent directory,   set
           * errno to ENOENT.
           */
          
           if (  !errno )
           errno = save_errno ? save_errno : ENOENT;
           /* FALLTHROUGH */
          
          err:
           if(  dir )
           (  void ) _closedir (  dir );
           if (  ptsize )
           free (  pt );
           free (  up );
           return (  char * ) NULL;
          }
          
          #endif /* _REENT_ONLY */
          
          #endif

libcsupport/src/getdents.c

       1  /*
           * getdents(   ) - Get Directory Entries
           *
           * SVR4 and SVID extension required by Newlib readdir(   ) family.
           *
           * This routine will dd_len / (  sizeof dirent ) directory entries relative to
           * the current directory position index. These entries will be placed in
           * character array pointed to by -dd_buf-
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: getdents.c,  v 1.11 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      29  int getdents(  
           int dd_fd,  
           char *dd_buf,  
           int dd_len
           )
          {
           rtems_libio_t *iop;
           rtems_filesystem_location_info_t loc;
          
           /*
           * Get the file control block structure associated with the file descriptor
           */
           iop = rtems_libio_iop(   dd_fd  );
          
           /*
           * Make sure we are working on a directory
           */
           loc = iop->pathinfo;
           if (   (  *loc.ops->node_type_h )(   &loc  ) != RTEMS_FILESYSTEM_DIRECTORY  )
           rtems_set_errno_and_return_minus_one(   ENOTDIR  );
          
           /*
           * Return the number of bytes that were actually transfered as a result
           * of the read attempt.
           */
           return (  *iop->pathinfo.handlers->read_h )(   iop,   dd_buf,   dd_len  );
          }

libcsupport/src/getegid.c

       1  /*
           * $Id: getegid.c,  v 1.5 2010/08/03 15:56:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/seterr.h>
          #include <rtems/userenv.h>
          
          /*
           * 4.2.1 Get Real User,   Effective User,   Ral Group,   and Effective Group IDs,  
           * P1003.1b-1993,   p. 84
           */
          
      21  gid_t getegid(   void  )
          {
           return _POSIX_types_Egid;
          }

libcsupport/src/geteuid.c

       1  /*
           * $Id: geteuid.c,  v 1.3 2010/08/03 15:56:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/seterr.h>
          
          #include <rtems/userenv.h>
          
          /*
           * MACRO in userenv.h
          uid_t _POSIX_types_Euid = 0;
          */
          
          /*PAGE
           *
           * 4.2.1 Get Real User,   Effective User,   Ral Group,   and Effective Group IDs,  
           * P1003.1b-1993,   p. 84
           */
          
      28  uid_t geteuid(   void  )
          {
           return _POSIX_types_Euid;
          }

libcsupport/src/getgid.c

       1  /*
           * $Id: getgid.c,  v 1.3 2010/08/03 15:46:52 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/userenv.h>
          
          /*
           * 4.2.1 Get Real User,   Effective User,   Ral Group,   and Effective Group IDs,  
           * P1003.1b-1993,   p. 84
           */
      15  gid_t getgid(   void  )
          {
           return _POSIX_types_Gid;
          }

libcsupport/src/getgroups.c

       1  /*
           * $Id: getgroups.c,  v 1.4 2009/09/30 04:46:31 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <unistd.h>
          
          /*PAGE
           *
           * 4.2.3 Get Supplementary IDs,   P1003.1b-1993,   p. 86
           */
          
      17  int getgroups(  
           int gidsetsize __attribute__(  (  unused ) ),  
           gid_t grouplist[] __attribute__(  (  unused ) )
           )
          {
           return 0; /* no supplemental group ids */
          }

libcsupport/src/getlogin.c

       1  /*
           * $Id: getlogin.c,  v 1.4 2010/08/29 19:48:52 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <limits.h>
          #include <string.h>
          #include <sys/types.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/seterr.h>
          #include <rtems/userenv.h>
          
          #include <unistd.h>
          #include <pwd.h>
          
          /*
           * 4.2.4 Get User Name,   P1003.1b-1993,   p. 87
           *
           * NOTE: P1003.1c/D10,   p. 49 adds getlogin_r(   ).
           */
      27  char *getlogin(   void  )
          {
           (  void ) getlogin_r(   _POSIX_types_Getlogin_buffer,   LOGIN_NAME_MAX  );
           return _POSIX_types_Getlogin_buffer;
          }
          
          /*
           * 4.2.4 Get User Name,   P1003.1b-1993,   p. 87
           *
           * NOTE: P1003.1c/D10,   p. 49 adds getlogin_r(   ).
           */
      38  int getlogin_r(  
           char *name,  
           size_t namesize
           )
          {
           struct passwd *pw;
           char *pname;
          
           if (   !name  )
           return EFAULT;
          
           if (   namesize < LOGIN_NAME_MAX  )
           return ERANGE;
          
           /* Set the pointer to a default name */
           pname = "";
          
           pw = getpwuid(  getuid(   ) );
           if (   pw  )
           pname = pw->pw_name;
          
           strncpy(   name,   pname,   LOGIN_NAME_MAX  );
           return 0;
          }

libcsupport/src/getpagesize.c

       1  /*
           * $Id: getpagesize.c,  v 1.2 2009/09/24 11:14:12 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          #include <sys/param.h>
          
          /*
           * Get System Page Size (  from SVR4 and 4.2+ BSD )
           *
           * This is not a functional version but the SPARC backend for at least
           * gcc 2.8.1 plus gnat 3.13p and gcc 3.0.1 require it to be there and
           * return a reasonable value.
           */
      19  int getpagesize(  void )
          {
           return PAGE_SIZE;
          }

libcsupport/src/getpgrp.c

       1  /*
           * $Id: getpgrp.c,  v 1.1 2003/08/18 07:31:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <limits.h>
          #include <errno.h>
          #include <string.h>
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 4.3.1 Get Process Group IDs,   P1003.1b-1993,   p. 89
           */
          
      23  pid_t getpgrp(   void  )
          {
           /*
           * This always succeeds and returns the process group id. For rtems,  
           * this will always be the local node;
           */
          
           return _Objects_Local_node;
          }

libcsupport/src/getpid.c

       1  /*
           * $Id: getpid.c,  v 1.5 2010/08/03 15:56:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 4.1.1 Get Process and Parent Process IDs,   P1003.1b-1993,   p. 83
           */
          
      20  pid_t getpid(   void  )
          {
           return _Objects_Local_node;
          }
          
          /*
           * _getpid_r
           *
           * This is the Newlib dependent reentrant version of getpid(   ).
           */
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__GETPID_R )
          
          #include <reent.h>
          
      35  pid_t _getpid_r(  
           struct _reent *ptr __attribute__(  (  unused ) )
           )
          {
           return getpid(   );
          }
          #endif

libcsupport/src/getppid.c

       1  /*
           * $Id: getppid.c,  v 1.3 2010/08/03 15:56:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/seterr.h>
          
          pid_t _POSIX_types_Ppid = 0;
          
          /*PAGE
           *
           * 4.1.1 Get Process and Parent Process IDs,   P1003.1b-1993,   p. 83
           */
          
      22  pid_t getppid(   void  )
          {
           return _POSIX_types_Ppid;
          }

libcsupport/src/getpwent.c

       1  /*
           * POSIX 1003.1b - 9.2.2 - User Database Access Routines
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: getpwent.c,  v 1.14 2010/06/28 22:14:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <sys/types.h>
          #include <pwd.h>
          #include <grp.h>
          #include <errno.h>
          #include <unistd.h>
          #include <stdlib.h>
          #include <string.h>
          #include <limits.h>
          #include <ctype.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          /*
           * Static,   thread-unsafe,   buffers
           */
          static FILE *passwd_fp;
          static char pwbuf[200];
          static struct passwd pwent;
          static FILE *group_fp;
          static char grbuf[200];
          static struct group grent;
          
          /*
           * Initialize useable but dummy databases
           */
      42  void init_etc_passwd_group(  void )
          {
           FILE *fp;
           static char etc_passwd_initted = 0;
          
           if (  etc_passwd_initted )
           return;
           etc_passwd_initted = 1;
           mkdir(  "/etc",   0777 );
          
           /*
           * Initialize /etc/passwd
           */
           if (  (  fp = fopen(  "/etc/passwd",   "r" ) ) != NULL ) {
           fclose(  fp );
           }
           else if (  (  fp = fopen(  "/etc/passwd",   "w" ) ) != NULL ) {
           fprintf(  fp,   "root:*:0:0:root::/:/bin/sh\n"
           "rtems:*:1:1:RTEMS Application::/:/bin/sh\n"
           "tty:!:2:2:tty owner::/:/bin/false\n"  );
           fclose(  fp );
           }
          
           /*
           * Initialize /etc/group
           */
           if (  (  fp = fopen(  "/etc/group",   "r" ) ) != NULL ) {
           fclose(  fp );
           }
           else if (  (  fp = fopen(  "/etc/group",   "w" ) ) != NULL ) {
           fprintf(   fp,   "root:x:0:root\n"
           "rtems:x:1:rtems\n"
           "tty:x:2:tty\n"  );
           fclose(  fp );
           }
          }
          
          /*
           * Extract a string value from the database
           */
          static int
      83  scanString(  FILE *fp,   char **name,   char **bufp,   size_t *nleft,   int nlFlag )
          {
           int c;
          
           *name = *bufp;
           for (  ;; ) {
           c = getc(  fp );
           if (  c == ':' ) {
           if (  nlFlag )
           return 0;
           break;
           }
           if (  c == '\n' ) {
           if (  !nlFlag )
           return 0;
           break;
           }
           if (  c == EOF )
           return 0;
           if (  *nleft < 2 )
           return 0;
           **bufp = c;
           ++(  *bufp );
           --(  *nleft );
           }
           **bufp = '\0';
           ++(  *bufp );
           --(  *nleft );
           return 1;
          }
          
          /*
           * Extract an integer value from the database
           */
          static int
     118  scanInt(  FILE *fp,   int *val )
          {
           int c;
           unsigned int i = 0;
           unsigned int limit = INT_MAX;
           int sign = 0;
           int d;
          
           for (  ;; ) {
           c = getc(  fp );
           if (  c == ':' )
           break;
           if (  sign == 0 ) {
           if (  c == '-' ) {
           sign = -1;
           limit++;
           continue;
           }
           sign = 1;
           }
           if (  !isdigit(  c ) )
           return 0;
           d = c - '0';
           if (  (  i > (  limit / 10 ) )
           || (  (  i == (  limit / 10 ) ) && (  d > (  limit % 10 ) ) ) )
           return 0;
           i = i * 10 + d;
           }
           if (  sign == 0 )
           return 0;
           *val = i * sign;
           return 1;
          }
          
          /*
           * Extract a single password record from the database
           */
     155  static int scanpw(  
           FILE *fp,  
           struct passwd *pwd,  
           char *buffer,  
           size_t bufsize
           )
          {
           int pwuid,   pwgid;
          
           if (  !scanString(  fp,   &pwd->pw_name,   &buffer,   &bufsize,   0 )
           || !scanString(  fp,   &pwd->pw_passwd,   &buffer,   &bufsize,   0 )
           || !scanInt(  fp,   &pwuid )
           || !scanInt(  fp,   &pwgid )
           || !scanString(  fp,   &pwd->pw_comment,   &buffer,   &bufsize,   0 )
           || !scanString(  fp,   &pwd->pw_gecos,   &buffer,   &bufsize,   0 )
           || !scanString(  fp,   &pwd->pw_dir,   &buffer,   &bufsize,   0 )
           || !scanString(  fp,   &pwd->pw_shell,   &buffer,   &bufsize,   1 ) )
           return 0;
           pwd->pw_uid = pwuid;
           pwd->pw_gid = pwgid;
           return 1;
          }
          
     178  static int getpw_r(  
           const char *name,  
           int uid,  
           struct passwd *pwd,  
           char *buffer,  
           size_t bufsize,  
           struct passwd **result
           )
          {
           FILE *fp;
           int match;
          
           init_etc_passwd_group(   );
          
           if (  (  fp = fopen(  "/etc/passwd",   "r" ) ) == NULL )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           for(  ;; ) {
           if (  !scanpw(  fp,   pwd,   buffer,   bufsize ) )
           goto error_einval;
          
           if (  name ) {
           match = (  strcmp(  pwd->pw_name,   name ) == 0 );
           } else {
           match = (  pwd->pw_uid == uid );
           }
          
           if (  match ) {
           fclose(  fp );
           *result = pwd;
           return 0;
           }
           }
          error_einval:
           fclose(  fp );
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }
          
     216  int getpwnam_r(  
           const char *name,  
           struct passwd *pwd,  
           char *buffer,  
           size_t bufsize,  
           struct passwd **result
           )
          {
           return getpw_r(  name,   0,   pwd,   buffer,   bufsize,   result );
          }
          
     227  struct passwd *getpwnam(  
           const char *name
           )
          {
           struct passwd *p;
          
           if(  getpwnam_r(  name,   &pwent,   pwbuf,   sizeof pwbuf,   &p ) )
           return NULL;
           return p;
          }
          
     238  int getpwuid_r(  
           uid_t uid,  
           struct passwd *pwd,  
           char *buffer,  
           size_t bufsize,  
           struct passwd **result
           )
          {
           return getpw_r(  NULL,   uid,   pwd,   buffer,   bufsize,   result );
          }
          
     249  struct passwd *getpwuid(  
           uid_t uid
           )
          {
           struct passwd *p;
          
           if(  getpwuid_r(  uid,   &pwent,   pwbuf,   sizeof pwbuf,   &p ) )
           return NULL;
           return p;
          }
          
     260  struct passwd *getpwent(  void )
          {
           if (  passwd_fp == NULL )
           return NULL;
           if (  !scanpw(  passwd_fp,   &pwent,   pwbuf,   sizeof pwbuf ) )
           return NULL;
           return &pwent;
          }
          
     269  void setpwent(  void )
          {
           init_etc_passwd_group(   );
          
           if (  passwd_fp != NULL )
           fclose(  passwd_fp );
           passwd_fp = fopen(  "/etc/passwd",   "r" );
          }
          
     278  void endpwent(  void )
          {
           if (  passwd_fp != NULL )
           fclose(  passwd_fp );
          }
          
          /*
           * Extract a single group record from the database
           */
     287  static int scangr(  
           FILE *fp,  
           struct group *grp,  
           char *buffer,  
           size_t bufsize
           )
          {
           int grgid;
           char *grmem,   *cp;
           int memcount;
          
           if (  !scanString(  fp,   &grp->gr_name,   &buffer,   &bufsize,   0 )
           || !scanString(  fp,   &grp->gr_passwd,   &buffer,   &bufsize,   0 )
           || !scanInt(  fp,   &grgid )
           || !scanString(  fp,   &grmem,   &buffer,   &bufsize,   1 ) )
           return 0;
           grp->gr_gid = grgid;
          
           /*
           * Determine number of members
           */
           for (  cp = grmem,   memcount = 1 ; *cp != 0 ; cp++ ) {
           if(  *cp == ',  ' )
           memcount++;
           }
          
           /*
           * Hack to produce (  hopefully ) a suitably-aligned array of pointers
           */
           if (  bufsize < (  (  (  memcount+1 )*sizeof(  char * ) ) + 15 ) )
           return 0;
           grp->gr_mem = (  char ** )(  (  (  uintptr_t )buffer + 15 ) & ~15 );
          
           /*
           * Fill in pointer array
           */
           grp->gr_mem[0] = grmem;
           for (  cp = grmem,   memcount = 1 ; *cp != 0 ; cp++ ) {
           if(  *cp == ',  ' ) {
           *cp = '\0';
           grp->gr_mem[memcount++] = cp + 1;
           }
           }
           grp->gr_mem[memcount] = NULL;
           return 1;
          }
          
     334  static int getgr_r(  
           const char *name,  
           int gid,  
           struct group *grp,  
           char *buffer,  
           size_t bufsize,  
           struct group **result
           )
          {
           FILE *fp;
           int match;
          
           init_etc_passwd_group(   );
          
           if (  (  fp = fopen(  "/etc/group",   "r" ) ) == NULL )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           for(  ;; ) {
           if (  !scangr(  fp,   grp,   buffer,   bufsize ) )
           goto error_einval;
          
           if (  name ) {
           match = (  strcmp(  grp->gr_name,   name ) == 0 );
           } else {
           match = (  grp->gr_gid == gid );
           }
          
           if (  match ) {
           fclose(  fp );
           *result = grp;
           return 0;
           }
           }
          error_einval:
           fclose(  fp );
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }
          
     372  int getgrnam_r(  
           const char *name,  
           struct group *grp,  
           char *buffer,  
           size_t bufsize,  
           struct group **result
           )
          {
           return getgr_r(  name,   0,   grp,   buffer,   bufsize,   result );
          }
          
     383  struct group *getgrnam(  
           const char *name
           )
          {
           struct group *p;
          
           if(  getgrnam_r(  name,   &grent,   grbuf,   sizeof grbuf,   &p ) )
           return NULL;
           return p;
          }
          
     394  int getgrgid_r(  
           gid_t gid,  
           struct group *grp,  
           char *buffer,  
           size_t bufsize,  
           struct group **result
           )
          {
           return getgr_r(  NULL,   gid,   grp,   buffer,   bufsize,   result );
          }
          
     405  struct group *getgrgid(  
           gid_t gid
           )
          {
           struct group *p;
          
           if(  getgrgid_r(  gid,   &grent,   grbuf,   sizeof grbuf,   &p ) )
           return NULL;
           return p;
          }
          
     416  struct group *getgrent(  void )
          {
           if (  group_fp == NULL )
           return NULL;
           if (  !scangr(  group_fp,   &grent,   grbuf,   sizeof grbuf ) )
           return NULL;
           return &grent;
          }
          
     425  void setgrent(  void )
          {
           init_etc_passwd_group(   );
          
           if (  group_fp != NULL )
           fclose(  group_fp );
           group_fp = fopen(  "/etc/group",   "r" );
          }
          
     434  void endgrent(  void )
          {
           if (  group_fp != NULL )
           fclose(  group_fp );
          }

libcsupport/src/getrusage.c

       1  /*
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: getrusage.c,  v 1.2 2010/07/06 01:15:44 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/resource.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/seterr.h>
          
      22  int getrusage(  int who,   struct rusage *usage )
          {
           struct timespec uptime;
           struct timeval rtime;
          
           if (   !usage  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           /*
           * RTEMS only has a single process so there are no children.
           * The single process has been running since the system
           * was booted and since there is no distinction between system
           * and user time,   we will just report the uptime.
           */
           if (  who == RUSAGE_SELF ) {
           rtems_clock_get_uptime(   &uptime  );
          
           rtime.tv_sec = uptime.tv_sec;
           rtime.tv_usec = uptime.tv_nsec / 1000;
          
           usage->ru_utime = rtime;
           usage->ru_stime = rtime;
          
           return 0;
           }
          
           if (  who == RUSAGE_CHILDREN ) {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
           }
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }
          

libcsupport/src/getuid.c

       1  /*
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: getuid.c,  v 1.4 2010/08/03 15:56:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          #include <rtems/userenv.h>
          
          /*
           * 4.2.1 Get Real User,   Effective User,   Ral Group,   and Effective Group IDs,  
           * P1003.1b-1993,   p. 84
           */
      24  uid_t getuid(   void  )
          {
           return _POSIX_types_Uid;
          }
          

libcsupport/src/gxx_wrappers.c

       1  /*
           * RTEMS threads compatibility routines for libgcc2.
           *
           * by: Rosimildo da Silva (  rdasilva@connecttel.com )
           *
           * Used ideas from:
           * W. Eric Norum
           * Canadian Light Source
           * University of Saskatchewan
           * Saskatoon,   Saskatchewan,   CANADA
           * eric@cls.usask.ca
           *
           * Eric sent some e-mail in the rtems-list as a start point for this
           * module implementation.
           *
           * $Id: gxx_wrappers.c,  v 1.22 2010/08/23 07:59:38 sh Exp $
           */
          
          /*
           * This file is only used if using gcc
           */
          #if defined(  __GNUC__ )
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/gxx_wrappers.h>
          
          #include <stdlib.h>
          
          #include <rtems.h>
          
          /* uncomment this if you need to debug this interface */
          /*#define DEBUG_GXX_WRAPPERS 1*/
          
      37  int rtems_gxx_once(  __gthread_once_t *once,   void (  *func ) (  void ) )
          {
           #ifdef DEBUG_GXX_WRAPPERS
           printk(   "gxx_wrappers: once=%x,   func=%x\n",   *once,   func  );
           #endif
          
           if (   *(  volatile __gthread_once_t * )once == 0  ) {
           rtems_mode saveMode;
           __gthread_once_t o;
          
           rtems_task_mode(  RTEMS_NO_PREEMPT,   RTEMS_PREEMPT_MASK,   &saveMode );
           if (   (  o = *(  volatile __gthread_once_t * )once ) == 0  ) {
           *(  volatile __gthread_once_t * )once = 1;
           }
           rtems_task_mode(  saveMode,   RTEMS_PREEMPT_MASK,   &saveMode );
           if (   o == 0  )
           (  *func )(   );
           }
           return 0;
          }
          
      58  int rtems_gxx_key_create (  __gthread_key_t *key,   void (  *dtor ) (  void * ) )
          {
           rtems_status_code status;
          
           /* Ok,   this can be a bit tricky. We are going to return a "key" as a
           * pointer to the buffer that will hold the value of the key itself.
           * We have to to this,   because the others functions on this interface
           * deal with the value of the key,   as used with the POSIX API.
           */
           /* Do not pull your hair,   trust me this works. :- ) */
           __gthread_key_t new_key = (  __gthread_key_t ) malloc(   sizeof(   *new_key  )  );
           *key = new_key;
           new_key->val = NULL;
           new_key->dtor = dtor;
          
           #ifdef DEBUG_GXX_WRAPPERS
           printk(  
           "gxx_wrappers: create key=%x,   dtor=%x,   new_key=%x\n",   key,   dtor,   new_key
            );
           #endif
          
           /* register with RTEMS the buffer that will hold the key values */
           status = rtems_task_variable_add(   RTEMS_SELF,   (  void ** )new_key,   dtor  );
           if (   status == RTEMS_SUCCESSFUL  )
           return 0;
           return -1;
          }
          
      86  int rtems_gxx_key_dtor (  __gthread_key_t key,   void *ptr )
          {
           #ifdef DEBUG_GXX_WRAPPERS
           printk(   "gxx_wrappers: dtor key=%x,   ptr=%x\n",   key,   ptr  );
           #endif
          
           key->val = 0;
           return 0;
          }
          
      96  int rtems_gxx_key_delete (  __gthread_key_t key )
          {
           rtems_status_code status;
          
           #ifdef DEBUG_GXX_WRAPPERS
           printk(   "gxx_wrappers: delete key=%x\n",   key  );
           #endif
          
           /* register with RTEMS the buffer that will hold the key values */
           status = rtems_task_variable_delete(   RTEMS_SELF,   (  void ** )key  );
           if (   status == RTEMS_SUCCESSFUL  ) {
           /* Hmm - hopefully all tasks using this key have gone away... */
           if (   key  ) free(   *(  void ** )key  );
           return 0;
           }
           key = NULL;
           return 0;
          }
          
     115  void *rtems_gxx_getspecific(  __gthread_key_t key )
          {
           rtems_status_code status;
           void *p= 0;
          
           /* register with RTEMS the buffer that will hold the key values */
           status = rtems_task_variable_get(   RTEMS_SELF,   (  void ** )key,   &p  );
           if (   status == RTEMS_SUCCESSFUL  ) {
           /* We do not have to do this,   but what the heck ! */
           p= key->val;
           } else {
           /* fisrt time,   always set to zero,   it is unknown the value that the others
           * threads are using at the moment of this call
           */
           status = rtems_task_variable_add(   RTEMS_SELF,   (  void ** )key,   key->dtor  );
           if (   status != RTEMS_SUCCESSFUL  ) {
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_GXX_KEY_ADD_FAILED
            );
           }
           key->val = (  void * )0;
           }
          
           #ifdef DEBUG_GXX_WRAPPERS
           printk(  
           "gxx_wrappers: getspecific key=%x,   ptr=%x,   id=%x\n",  
           key,  
           p,  
           rtems_task_self(   )
            );
           #endif
           return p;
          }
          
     151  int rtems_gxx_setspecific(  __gthread_key_t key,   const void *ptr )
          {
           rtems_status_code status;
          
           #ifdef DEBUG_GXX_WRAPPERS
           printk(  
           "gxx_wrappers: setspecific key=%x,   ptr=%x,   id=%x\n",  
           key,  
           ptr,  
           rtems_task_self(   )
            );
           #endif
          
           /* register with RTEMS the buffer that will hold the key values */
           status = rtems_task_variable_add(   RTEMS_SELF,   (  void ** )key,   key->dtor  );
           if (   status == RTEMS_SUCCESSFUL  ) {
           /* now let's set the proper value */
           key->val = (  void * )ptr;
           return 0;
           }
           return -1;
          }
          
          
          /*
           * MUTEX support
           */
     178  void rtems_gxx_mutex_init (  __gthread_mutex_t *mutex )
          {
           rtems_status_code status;
          
           #ifdef DEBUG_GXX_WRAPPERS
           printk(   "gxx_wrappers: mutex init =%X\n",   *mutex  );
           #endif
          
           status = rtems_semaphore_create(  
           rtems_build_name (  'G',   'C',   'C',   '2' ),  
           1,  
           RTEMS_PRIORITY|RTEMS_BINARY_SEMAPHORE|
           RTEMS_INHERIT_PRIORITY|RTEMS_NO_PRIORITY_CEILING|RTEMS_LOCAL,  
           0,  
           (  rtems_id * )mutex
            );
           if (   status != RTEMS_SUCCESSFUL  ) {
           #ifdef DEBUG_GXX_WRAPPERS
           printk(  
           "gxx_wrappers: mutex init failed %s (  %d )\n",  
           rtems_status_text(  status ),  
           status
            );
           #endif
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_GXX_MUTEX_INIT_FAILED
            );
           }
           #ifdef DEBUG_GXX_WRAPPERS
           printk(   "gxx_wrappers: mutex init complete =%X\n",   *mutex  );
           #endif
          }
          
     213  int rtems_gxx_mutex_lock (  __gthread_mutex_t *mutex )
          {
           rtems_status_code status;
          
           #ifdef DEBUG_GXX_WRAPPERS
           printk(   "gxx_wrappers: lock mutex=%X\n",   *mutex  );
           #endif
          
           status = rtems_semaphore_obtain(  
           *(  rtems_id * )mutex,  
           RTEMS_WAIT,  
           RTEMS_NO_TIMEOUT
            );
           if (   status == RTEMS_SUCCESSFUL  )
           return 0;
           return -1;
          }
          
     231  int rtems_gxx_mutex_destroy (  __gthread_mutex_t *mutex )
          {
           rtems_status_code status;
          
           #ifdef DEBUG_GXX_WRAPPERS
           printk(   "gxx_wrappers: destroy mutex=%X\n",   *mutex  );
           #endif
          
           status = rtems_semaphore_delete(  *(  rtems_id * )mutex );
           if (   status == RTEMS_SUCCESSFUL  )
           return 0;
           return -1;
          }
          
     245  int rtems_gxx_mutex_trylock (  __gthread_mutex_t *mutex )
          {
           rtems_status_code status;
          
           #ifdef DEBUG_GXX_WRAPPERS
           printk(   "gxx_wrappers: trylock mutex=%X\n",   *mutex  );
           #endif
          
           status = rtems_semaphore_obtain (  *(  rtems_id * )mutex,   RTEMS_NO_WAIT,   0 );
           if (   status == RTEMS_SUCCESSFUL  )
           return 0;
           return -1;
          }
          
     259  int rtems_gxx_mutex_unlock (  __gthread_mutex_t *mutex )
          {
           rtems_status_code status;
          
           #ifdef DEBUG_GXX_WRAPPERS
           printk(   "gxx_wrappers: unlock mutex=%X\n",   *mutex  );
           #endif
          
           status = rtems_semaphore_release(   *(  rtems_id * )mutex  );
           if (   status == RTEMS_SUCCESSFUL  )
           return 0;
           return -1;
          }
          
     273  void rtems_gxx_recursive_mutex_init(  __gthread_recursive_mutex_t *mutex )
          {
           rtems_gxx_mutex_init(  mutex );
          }
          
     278  int rtems_gxx_recursive_mutex_lock(  __gthread_recursive_mutex_t *mutex )
          {
           return rtems_gxx_mutex_lock(  mutex );
          }
          
     283  int rtems_gxx_recursive_mutex_trylock(  __gthread_recursive_mutex_t *mutex )
          {
           return rtems_gxx_mutex_trylock(  mutex );
          }
          
     288  int rtems_gxx_recursive_mutex_unlock(  __gthread_recursive_mutex_t *mutex )
          {
           return rtems_gxx_mutex_unlock(  mutex );
          }
          
          #endif /* __GNUC__ */

libcsupport/src/ioctl.c

       1  /*
           * ioctl(   ) system call
           *
           * This routine is not defined in the POSIX 1003.1b standard but is
           * commonly supported on most UNIX and POSIX systems.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ioctl.c,  v 1.18 2010/08/23 23:17:42 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          #include <unistd.h>
          
      28  int ioctl(  
           int fd,  
           ioctl_command_t command,  
           ...
           )
          {
           va_list ap;
           rtems_status_code rc;
           rtems_libio_t *iop;
           void *buffer;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(  iop );
          
           va_start(  ap,   command );
          
           buffer = va_arg(  ap,   void * );
          
           /*
           * Now process the ioctl(   ).
           */
           rc = (  *iop->pathinfo.handlers->ioctl_h )(   iop,   command,   buffer  );
          
           va_end(   ap  );
           return rc;
          }

libcsupport/src/isatty.c

       1  /*
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: isatty.c,  v 1.6 2008/12/05 06:42:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_ISATTY
          
          #include <sys/stat.h>
          
      20  int isatty(  
           int fd
           )
          {
           struct stat buf;
          
           if (  fstat (  fd,   &buf ) < 0 )
           return 0;
          
           if (  S_ISCHR (  buf.st_mode ) )
           return 1;
          
           return 0;
          }
          
          #endif

libcsupport/src/isatty_r.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: isatty_r.c,  v 1.4 2010/04/02 07:05:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * _isatty_r
           *
           * This is the Newlib dependent reentrant version of isatty(   ).
           */
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__ISATTY_R )
          
          #include <unistd.h>
          #include <reent.h>
          #include <sys/stat.h>
          
      28  int _isatty_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           int fd
           )
          {
           return isatty(   fd  );
          }
          #endif

libcsupport/src/issetugid.c

       1  /*
           * Dummy version of BSD routine
           *
           * $Id: issetugid.c,  v 1.3 2010/07/01 15:37:48 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE_ISSETUGID )
      12  int issetugid (  void )
          {
           return 0;
          }
          #endif

libcsupport/src/kill_noposix.c

       1  /*
           * Marginal implementations of some POSIX API routines
           * to be used when POSIX is disabled.
           *
           * + kill
           * + _kill_r
           * + __kill
           * + sleep
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: kill_noposix.c,  v 1.1 2009/12/01 14:22:58 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          
          #include <unistd.h>
          
          /*
           * These are directly supported (  and completely correct ) in the posix api.
           */
          
          #if !defined(  RTEMS_POSIX_API )
      30  int kill(   pid_t pid,   int sig  )
          {
           return 0;
          }
          
          #if defined(  RTEMS_NEWLIB )
          #include <reent.h>
          
      38  int _kill_r(   struct _reent *ptr,   pid_t pid,   int sig  )
          {
           return 0;
          }
          #endif
          
      44  int __kill(   pid_t pid,   int sig  )
          {
           return 0;
          }
          #endif

libcsupport/src/lchown.c

       1  /*
           * lchown(   ) - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
           * But Do Not Follow a Symlink
           *
           * Written by: Vinu Rajashekhar <vinutheraj@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: lchown.c,  v 1.1 2010/07/01 17:22:03 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/stat.h>
          
          #include <rtems.h>
          
      22  int _chown_helper(   const char *path,   uid_t owner,   gid_t group,   int follow_link );
          
      24  int lchown(  
           const char *path,  
           uid_t owner,  
           gid_t group
           )
          {
           return _chown_helper(   path,   owner,   group,   false  );
          }

libcsupport/src/libio.c

       1  /*
           * This file contains the support infrastructure used to manage the
           * table of integer style file descriptors used by the low level
           * POSIX system calls like open(   ),   read,   fstat(   ),   etc.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: libio.c,  v 1.49 2010/04/30 08:55:41 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <fcntl.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          #include <rtems/assoc.h>
          
          /* define this to alias O_NDELAY to O_NONBLOCK,   i.e.,  
           * O_NDELAY is accepted on input but fcntl(  F_GETFL ) returns
           * O_NONBLOCK. This is because rtems has no distinction
           * between the two (  but some systems have ).
           * Note that accepting this alias creates a problem:
           * an application trying to clear the non-blocking flag
           * using a
           *
           * fcntl(  fd,   F_SETFL,   fcntl(  fd,   F_GETFL ) & ~O_NDELAY );
           *
           * does (  silently ) ignore the operation.
           */
          #undef ACCEPT_O_NDELAY_ALIAS
          
          /*
           * rtems_libio_fcntl_flags
           *
           * Convert UNIX fnctl(  2 ) flags to ones that RTEMS drivers understand
           */
          
          const rtems_assoc_t access_modes_assoc[] = {
           { "READ",   LIBIO_FLAGS_READ,   O_RDONLY },  
           { "WRITE",   LIBIO_FLAGS_WRITE,   O_WRONLY },  
           { "READ/WRITE",   LIBIO_FLAGS_READ_WRITE,   O_RDWR },  
           { 0,   0,   0 },  
          };
          
          const rtems_assoc_t status_flags_assoc[] = {
          #ifdef ACCEPT_O_NDELAY_ALIAS
           { "NO DELAY",   LIBIO_FLAGS_NO_DELAY,   O_NDELAY },  
          #endif
           { "NONBLOCK",   LIBIO_FLAGS_NO_DELAY,   O_NONBLOCK },  
           { "APPEND",   LIBIO_FLAGS_APPEND,   O_APPEND },  
           { "CREATE",   LIBIO_FLAGS_CREATE,   O_CREAT },  
           { 0,   0,   0 },  
          };
          
      67  uint32_t rtems_libio_fcntl_flags(  
           uint32_t fcntl_flags
           )
          {
           uint32_t flags = 0;
           uint32_t access_modes;
          
           /*
           * Access mode is a small integer
           */
          
           access_modes = fcntl_flags & O_ACCMODE;
           fcntl_flags &= ~O_ACCMODE;
           flags = rtems_assoc_local_by_remote(   access_modes_assoc,   access_modes  );
          
           /*
           * Everything else is single bits
           */
          
           flags |=
           rtems_assoc_local_by_remote_bitfield(  status_flags_assoc,   fcntl_flags );
           return flags;
          }
          
          /*
           * rtems_libio_to_fcntl_flags
           *
           * Convert RTEMS internal flags to UNIX fnctl(  2 ) flags
           */
          
      97  uint32_t rtems_libio_to_fcntl_flags(  
           uint32_t flags
           )
          {
           uint32_t fcntl_flags = 0;
          
           if (   (  flags & LIBIO_FLAGS_READ_WRITE ) == LIBIO_FLAGS_READ_WRITE  ) {
           fcntl_flags |= O_RDWR;
           } else if (   (  flags & LIBIO_FLAGS_READ ) == LIBIO_FLAGS_READ ) {
           fcntl_flags |= O_RDONLY;
           } else if (   (  flags & LIBIO_FLAGS_WRITE ) == LIBIO_FLAGS_WRITE ) {
           fcntl_flags |= O_WRONLY;
           }
          
           if (   (  flags & LIBIO_FLAGS_NO_DELAY ) == LIBIO_FLAGS_NO_DELAY  ) {
           fcntl_flags |= O_NONBLOCK;
           }
          
           if (   (  flags & LIBIO_FLAGS_APPEND ) == LIBIO_FLAGS_APPEND  ) {
           fcntl_flags |= O_APPEND;
           }
          
           if (   (  flags & LIBIO_FLAGS_CREATE ) == LIBIO_FLAGS_CREATE  ) {
           fcntl_flags |= O_CREAT;
           }
          
           return fcntl_flags;
          }
          
          /*
           * rtems_libio_allocate
           *
           * This routine searches the IOP Table for an unused entry. If it
           * finds one,   it returns it. Otherwise,   it returns NULL.
           */
          
     133  rtems_libio_t *rtems_libio_allocate(   void  )
          {
           rtems_libio_t *iop,   *next;
           rtems_status_code rc;
           rtems_id sema;
          
           rtems_libio_lock(   );
          
           if (  rtems_libio_iop_freelist ) {
           rc = rtems_semaphore_create(  
           RTEMS_LIBIO_IOP_SEM(  rtems_libio_iop_freelist - rtems_libio_iops ),  
           1,  
           RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,  
           0,  
           &sema
            );
           if (  rc != RTEMS_SUCCESSFUL )
           goto failed;
           iop = rtems_libio_iop_freelist;
           next = iop->data1;
           (  void ) memset(   iop,   0,   sizeof(  rtems_libio_t )  );
           iop->flags = LIBIO_FLAGS_OPEN;
           iop->sem = sema;
           rtems_libio_iop_freelist = next;
           goto done;
           }
          
          failed:
           iop = 0;
          
          done:
           rtems_libio_unlock(   );
           return iop;
          }
          
          /*
           * rtems_libio_free
           *
           * This routine frees the resources associated with an IOP (  file descriptor )
           * and clears the slot in the IOP Table.
           */
          
     175  void rtems_libio_free(  
           rtems_libio_t *iop
           )
          {
           rtems_libio_lock(   );
          
           if (  iop->sem )
           rtems_semaphore_delete(  iop->sem );
          
           iop->flags &= ~LIBIO_FLAGS_OPEN;
           iop->data1 = rtems_libio_iop_freelist;
           rtems_libio_iop_freelist = iop;
          
           rtems_libio_unlock(   );
          }
          
          /*
           * rtems_libio_is_open_files_in_fs
           *
           * This routine scans the entire file descriptor table to determine if the
           * are any active file descriptors that refer to the at least one node in the
           * file system that we are trying to dismount.
           *
           * If there is at least one node in the file system referenced by the mount
           * table entry a 1 is returned,   otherwise a 0 is returned.
           */
          
     202  int rtems_libio_is_open_files_in_fs(  
           rtems_filesystem_mount_table_entry_t * fs_mt_entry
           )
          {
           rtems_libio_t *iop;
           int result = 0;
           uint32_t i;
          
           rtems_libio_lock(   );
          
           /*
           * Look for any active file descriptor entry.
           */
          
           for (  iop=rtems_libio_iops,  i=0; i < rtems_libio_number_iops; iop++,   i++ ){
          
           if (  (  iop->flags & LIBIO_FLAGS_OPEN ) != 0 ) {
          
           /*
           * Check if this node is under the file system that we
           * are trying to dismount.
           */
          
           if (   iop->pathinfo.mt_entry == fs_mt_entry  ) {
           result = 1;
           break;
           }
           }
           }
          
           rtems_libio_unlock(   );
          
           return result;
          }
          
          /*
           * rtems_libio_is_file_open
           *
           * This routine scans the entire file descriptor table to determine if the
           * given file refers to an active file descriptor.
           *
           * If the given file is open a 1 is returned,   otherwise a 0 is returned.
           */
          
     246  int rtems_libio_is_file_open(  
           void *node_access
           )
          {
           rtems_libio_t *iop;
           int result=0;
           uint32_t i;
          
           rtems_libio_lock(   );
          
           /*
           * Look for any active file descriptor entry.
           */
          
           for (  iop=rtems_libio_iops,  i=0; i < rtems_libio_number_iops; iop++,   i++ ){
           if (  (  iop->flags & LIBIO_FLAGS_OPEN ) != 0 ) {
          
           /*
           * Check if this node is under the file system that we
           * are trying to dismount.
           */
          
           if (   iop->pathinfo.node_access == node_access  ) {
           result = 1;
           break;
           }
           }
           }
          
           rtems_libio_unlock(   );
          
           return result;
          }

libcsupport/src/libio_init.c

       1  /*
           * This file contains the support infrastructure used to manage the
           * table of integer style file descriptors used by the low level
           * POSIX system calls like open(   ),   read,   fstat(   ),   etc.
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: libio_init.c,  v 1.6 2010/07/04 14:53:44 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h> /* libio_.h pulls in rtems */
          #include <rtems.h>
          #include <rtems/assoc.h> /* assoc.h not included by rtems.h */
          
          #include <stdio.h> /* O_RDONLY,   et.al. */
          #include <fcntl.h> /* O_RDONLY,   et.al. */
          #include <errno.h>
          
          #include <errno.h>
          #include <string.h> /* strcmp */
          #include <unistd.h>
          #include <stdlib.h> /* calloc(   ) */
          
          #include <rtems/libio.h> /* libio.h not pulled in by rtems */
          
          /*
           * File descriptor Table Information
           */
          
          rtems_id rtems_libio_semaphore;
          rtems_libio_t *rtems_libio_iops;
          rtems_libio_t *rtems_libio_iop_freelist;
          
          /*
           * rtems_libio_init
           *
           * Called by BSP startup code to initialize the libio subsystem.
           */
          
      49  void rtems_libio_init(   void  )
          {
           rtems_status_code rc;
           uint32_t i;
           rtems_libio_t *iop;
          
           if (  rtems_libio_number_iops > 0 )
           {
           rtems_libio_iops = (  rtems_libio_t * ) calloc(  rtems_libio_number_iops,  
           sizeof(  rtems_libio_t ) );
           if (  rtems_libio_iops == NULL )
           rtems_fatal_error_occurred(  RTEMS_NO_MEMORY );
          
           iop = rtems_libio_iop_freelist = rtems_libio_iops;
           for (  i = 0 ; (  i + 1 ) < rtems_libio_number_iops ; i++,   iop++ )
           iop->data1 = iop + 1;
           iop->data1 = NULL;
           }
          
           /*
           * Create the binary semaphore used to provide mutual exclusion
           * on the IOP Table.
           */
          
           rc = rtems_semaphore_create(  
           RTEMS_LIBIO_SEM,  
           1,  
           RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,  
           RTEMS_NO_PRIORITY,  
           &rtems_libio_semaphore
            );
           if (   rc != RTEMS_SUCCESSFUL  )
           rtems_fatal_error_occurred(   rc  );
          
           /*
           * Initialize the base file system infrastructure.
           */
          
           if (  rtems_fs_init_helper )
           (  * rtems_fs_init_helper )(   );
          }

libcsupport/src/libio_sockets.c

       1  /*
           * This file contains the support infrastructure used to manage the
           * table of integer style file descriptors used by the socket calls.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: libio_sockets.c,  v 1.16 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          /*
           * Convert an RTEMS file descriptor to a BSD socket pointer.
           */
          
      26  struct socket *rtems_bsdnet_fdToSocket(  
           int fd
           )
          {
           rtems_libio_t *iop;
          
           /* same as rtems_libio_check_fd(  _fd ) but different return */
           if (  (  uint32_t )fd >= rtems_libio_number_iops ) {
           errno = EBADF;
           return NULL;
           }
           iop = &rtems_libio_iops[fd];
          
           /* same as rtems_libio_check_is_open(  iop ) but different return */
           if (  (  iop->flags & LIBIO_FLAGS_OPEN ) == 0 ) {
           errno = EBADF;
           return NULL;
           }
          
           if (  iop->data1 == NULL )
           errno = EBADF;
           return iop->data1;
          }
          
          /*
           * Create an RTEMS file descriptor for a socket
           */
          
      54  int rtems_bsdnet_makeFdForSocket(  
           void *so,  
           const rtems_filesystem_file_handlers_r *h
           )
          {
           rtems_libio_t *iop;
           int fd;
          
           iop = rtems_libio_allocate(   );
           if (  iop == 0 )
           rtems_set_errno_and_return_minus_one(   ENFILE  );
          
           fd = iop - rtems_libio_iops;
           iop->flags |= LIBIO_FLAGS_WRITE | LIBIO_FLAGS_READ;
           iop->data0 = fd;
           iop->data1 = so;
           iop->pathinfo.handlers = h;
           iop->pathinfo.ops = &rtems_filesystem_operations_default;
           return fd;
          }

libcsupport/src/link.c

       1  /*
           * link(   ) - POSIX 1003.1b - 5.3.4 - Create a new link
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: link.c,  v 1.19 2010/07/16 09:24:51 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <errno.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      25  int link(  
           const char *existing,  
           const char *new
           )
          {
           rtems_filesystem_location_info_t existing_loc;
           rtems_filesystem_location_info_t parent_loc;
           int i;
           int result;
           const char *name_start;
          
           /*
           * Get the node we are linking to.
           */
          
           result = rtems_filesystem_evaluate_path(   existing,   strlen(   existing  ),  
           0,   &existing_loc,   true  );
           if (   result != 0  )
           return -1;
          
           /*
           * Get the parent of the node we are creating.
           */
          
           rtems_filesystem_get_start_loc(   new,   &i,   &parent_loc  );
          
           result = (  *parent_loc.ops->evalformake_h )(   &new[i],   &parent_loc,   &name_start  );
           if (   result != 0  ) {
           rtems_filesystem_freenode(   &existing_loc  );
           return -1;
           }
          
           /*
           * Check to see if the caller is trying to link across file system
           * boundaries.
           */
          
           if (   parent_loc.mt_entry != existing_loc.mt_entry  ) {
           rtems_filesystem_freenode(   &existing_loc  );
           rtems_filesystem_freenode(   &parent_loc  );
           rtems_set_errno_and_return_minus_one(   EXDEV  );
           }
          
           result = (  *parent_loc.ops->link_h )(   &existing_loc,   &parent_loc,   name_start  );
          
           rtems_filesystem_freenode(   &existing_loc  );
           rtems_filesystem_freenode(   &parent_loc  );
          
           return result;
          }
          
          /*
           * _link_r
           *
           * This is the Newlib dependent reentrant version of link(   ).
           */
          
          #if defined(  RTEMS_NEWLIB )
          
          #include <reent.h>
          
      86  int _link_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           const char *existing,  
           const char *new
           )
          {
           return link(   existing,   new  );
          }
          #endif

libcsupport/src/lseek.c

       1  /*
           * lseek(   ) - POSIX 1003.1b 6.5.3 - Reposition Read/Write File Offset
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: lseek.c,  v 1.18 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      23  off_t lseek(  
           int fd,  
           off_t offset,  
           int whence
           )
          {
           rtems_libio_t *iop;
           off_t old_offset;
           off_t status;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(  iop );
          
           /*
           * Now process the lseek(   ).
           */
          
           old_offset = iop->offset;
           switch (   whence  ) {
           case SEEK_SET:
           iop->offset = offset;
           break;
          
           case SEEK_CUR:
           iop->offset += offset;
           break;
          
           case SEEK_END:
           iop->offset = iop->size + offset;
           break;
          
           default:
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           /*
           * At this time,   handlers assume iop->offset has the desired
           * new offset.
           */
          
           status = (  *iop->pathinfo.handlers->lseek_h )(   iop,   offset,   whence  );
           if (   status == (  off_t ) -1  )
           iop->offset = old_offset;
          
           /*
           * So if the operation failed,   we have to restore iop->offset.
           */
          
           return status;
          }
          
          /*
           * _lseek_r
           *
           * This is the Newlib dependent reentrant version of lseek(   ).
           */
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__LSEEK_R )
          
          #include <reent.h>
          
      85  off_t _lseek_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           int fd,  
           off_t offset,  
           int whence
           )
          {
           return lseek(   fd,   offset,   whence  );
          }
          #endif

libcsupport/src/lstat.c

       1  /*
           * lstat(   ) - BSD 4.3 and SVR4 - Get File Status
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: lstat.c,  v 1.5 2008/09/01 11:42:19 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define _STAT_NAME lstat
          #define _STAT_R_NAME _lstat_r
          #define _STAT_FOLLOW_LINKS false
          
          #include "stat.c"

libcsupport/src/malloc.c

       1  /*
           * RTEMS Malloc Family Implementation
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: malloc.c,  v 1.60 2010/08/25 14:30:01 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include <stdlib.h>
          #include <errno.h>
          
          #include "malloc_p.h"
          
      25  void *malloc(  
           size_t size
           )
          {
           void *return_this;
          
           MSBUMP(  malloc_calls,   1 );
          
           /*
           * If some free's have been deferred,   then do them now.
           */
           malloc_deferred_frees_process(   );
          
           /*
           * Validate the parameters
           */
           if (   !size  )
           return (  void * ) 0;
          
           /*
           * Do not attempt to allocate memory if not in correct system state.
           */
           if (   _System_state_Is_up(  _System_state_Get(   ) ) &&
           !malloc_is_system_state_OK(   )  )
           return NULL;
          
           /*
           * Try to give a segment in the current heap if there is not
           * enough space then try to grow the heap.
           * If this fails then return a NULL pointer.
           */
          
           return_this = _Protected_heap_Allocate(   RTEMS_Malloc_Heap,   size  );
          
           if (   !return_this  ) {
           if (  rtems_malloc_sbrk_helpers )
           return_this = (  *rtems_malloc_sbrk_helpers->extend )(   size  );
           if (   !return_this  ) {
           errno = ENOMEM;
           return (  void * ) 0;
           }
           }
          
           /*
           * If the user wants us to dirty the allocated memory,   then do it.
           */
           if (   rtems_malloc_dirty_helper  )
           (  *rtems_malloc_dirty_helper )(   return_this,   size  );
          
           /*
           * If configured,   update the statistics
           */
           if (   rtems_malloc_statistics_helpers  )
           (  *rtems_malloc_statistics_helpers->at_malloc )(  return_this );
          
           return return_this;
          }
          
          #endif

libcsupport/src/malloc_deferred.c

       1  /*
           * Process free requests deferred because they were from ISR
           * or other critical section.
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: malloc_deferred.c,  v 1.4 2008/09/01 11:42:19 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include <stdlib.h>
          #include <errno.h>
          
          #include "malloc_p.h"
          
          rtems_chain_control RTEMS_Malloc_GC_list;
          
      27  bool malloc_is_system_state_OK(  void )
          {
           if (   _Thread_Dispatch_disable_level > 0  )
           return false;
          
           if (   _ISR_Nest_level > 0  )
           return false;
          
           return true;
          }
          
      38  void malloc_deferred_frees_initialize(  void )
          {
           rtems_chain_initialize_empty(  &RTEMS_Malloc_GC_list );
          }
          
      43  void malloc_deferred_frees_process(  void )
          {
           rtems_chain_node *to_be_freed;
          
           /*
           * If some free's have been deferred,   then do them now.
           */
           while (  (  to_be_freed = rtems_chain_get(  &RTEMS_Malloc_GC_list ) ) != NULL )
           free(  to_be_freed );
          }
          
      54  void malloc_deferred_free(  
           void *pointer
           )
          {
           rtems_chain_append(  &RTEMS_Malloc_GC_list,   (  rtems_chain_node * )pointer );
          }
          #endif

libcsupport/src/malloc_dirtier.c

       1  /*
           * RTEMS Malloc Family -- Dirty Memory from Malloc
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: malloc_dirtier.c,  v 1.1 2008/01/09 21:08:36 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/malloc.h>
          #include "malloc_p.h"
          
          #include <errno.h>
          
      24  void rtems_malloc_dirty_memory(  
           void *start,  
           size_t size
           )
          {
           (  void ) memset(  start,   0xCF,   size );
          }

libcsupport/src/malloc_get_statistics.c

       1  /*
           * malloc_get_statistics Implementation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: malloc_get_statistics.c,  v 1.3 2009/11/29 13:35:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include "malloc_p.h"
          
      21  int malloc_get_statistics(  
           rtems_malloc_statistics_t *stats
           )
          {
           if (   !stats  )
           return -1;
           _RTEMS_Lock_allocator(   );
           *stats = rtems_malloc_statistics;
           _RTEMS_Unlock_allocator(   );
           return 0;
          }
          
          #endif

libcsupport/src/malloc_initialize.c

       1  /**
           * @file
           *
           * @brief Malloc initialization implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: malloc_initialize.c,  v 1.14 2010/08/25 14:30:01 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/malloc.h>
          #include <rtems/score/wkspace.h>
          #include "malloc_p.h"
          
          /* FIXME: Dummy function */
          #ifndef RTEMS_NEWLIB
      29  void RTEMS_Malloc_Initialize(  
           void *heap_begin,  
           uintptr_t heap_size,  
           size_t sbrk_amount
           )
          {
          }
          #else
          rtems_malloc_statistics_t rtems_malloc_statistics;
          extern bool rtems_unified_work_area;
          
      40  void RTEMS_Malloc_Initialize(  
           void *heap_begin,  
           uintptr_t heap_size,  
           size_t sbrk_amount
           )
          {
           /*
           * If configured,   initialize the statistics support
           */
           if (   rtems_malloc_statistics_helpers != NULL  ) {
           (  *rtems_malloc_statistics_helpers->initialize )(   );
           }
          
           /*
           * Initialize the garbage collection list to start with nothing on it.
           */
           malloc_deferred_frees_initialize(   );
          
           /*
           * Initialize the optional sbrk support for extending the heap
           */
           if (   rtems_malloc_sbrk_helpers != NULL  ) {
           heap_begin = (  *rtems_malloc_sbrk_helpers->initialize )(  
           heap_begin,  
           sbrk_amount
            );
           heap_size = (  uintptr_t ) sbrk_amount;
           }
          
           /*
           * If this system is configured to use the same heap for
           * the RTEMS Workspace and C Program Heap,   then we need to
           * be very very careful about destroying the initialization
           * that has already been done.
           */
          
           /*
           * If the BSP is not clearing out the workspace,   then it is most likely
           * not clearing out the initial memory for the heap. There is no
           * standard supporting zeroing out the heap memory. But much code
           * with UNIX history seems to assume that memory malloc'ed during
           * initialization (  before any free's ) is zero'ed. This is true most
           * of the time under UNIX because zero'ing memory when it is first
           * given to a process eliminates the chance of a process seeing data
           * left over from another process. This would be a security violation.
           */
          
           if (  
           !rtems_unified_work_area
           && rtems_configuration_get_do_zero_of_workspace(   )
            ) {
           memset(   heap_begin,   0,   heap_size  );
           }
          
           /*
           * Unfortunately we cannot use assert if this fails because if this
           * has failed we do not have a heap and if we do not have a heap
           * STDIO cannot work because there will be no buffers.
           */
          
           if (   !rtems_unified_work_area  ) {
           uintptr_t status = _Protected_heap_Initialize(  
           RTEMS_Malloc_Heap,  
           heap_begin,  
           heap_size,  
           CPU_HEAP_ALIGNMENT
            );
           if (   status == 0  ) {
           rtems_fatal_error_occurred(   RTEMS_NO_MEMORY  );
           }
           }
          
           MSBUMP(   space_available,   _Protected_heap_Get_size(  RTEMS_Malloc_Heap )  );
          }
          #endif

libcsupport/src/malloc_report_statistics.c

       1  /*
           * malloc_report_statistics Implementation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: malloc_report_statistics.c,  v 1.1 2007/12/18 20:36:40 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include "malloc_p.h"
          
      21  void malloc_report_statistics(  void )
          {
           malloc_report_statistics_with_plugin(   NULL,   printk_plugin  );
          }
          
          #endif

libcsupport/src/malloc_report_statistics_plugin.c

       1  /*
           * malloc_report_statistics with plugin Implementation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: malloc_report_statistics_plugin.c,  v 1.3 2009/09/14 14:48:38 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include "malloc_p.h"
          #include "inttypes.h"
          
      22  void malloc_report_statistics_with_plugin(  
           void *context,  
           rtems_printk_plugin_t print
           )
          {
           rtems_malloc_statistics_t *s;
           uintmax_t allocated;
          
           s = &rtems_malloc_statistics;
          
           allocated = s->lifetime_allocated - s->lifetime_freed;
          
           (  *print )(  
           context,  
           "Malloc statistics\n"
           " avail:%"PRIu32"k allocated:%"PRIu32"k (  %"PRId32"%% ) "
           "max:%"PRIu32"k (  %"PRIu32"%% )"
           " lifetime:%"PRIu32"k freed:%"PRIu32"k\n",  
           s->space_available / 1024,  
           allocated / 1024,  
           /* avoid float! */
           (  allocated * 100 ) / s->space_available,  
           s->max_depth / 1024,  
           (  s->max_depth * 100 ) / s->space_available,  
           (  uint32_t ) (  s->lifetime_allocated / 1024 ),  
           (  uint32_t ) (  s->lifetime_freed / 1024 )
            );
           (  *print )(  
           context,  
           " Call counts: malloc:%"PRIu32" memalign:%"PRIu32" free:%"PRIu32
           " realloc:%"PRIu32" calloc:%"PRIu32"\n",  
           s->malloc_calls,  
           s->memalign_calls,  
           s->free_calls,  
           s->realloc_calls,  
           s->calloc_calls
            );
          }
          
          #endif

libcsupport/src/malloc_sbrk_helpers.c

       1  /*
           * RTEMS Malloc -- SBRK Support Plugin
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: malloc_sbrk_helpers.c,  v 1.4 2010/04/02 07:05:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h> /* sbrk */
          
          #include <rtems.h>
          #include <rtems/malloc.h>
          #include "malloc_p.h"
          
          #include <errno.h>
          
          size_t RTEMS_Malloc_Sbrk_amount;
          
      28  void *malloc_sbrk_initialize(  
           void *starting_address,  
           size_t length
           )
          {
           uintptr_t old_address;
           uintptr_t uaddress;
          
           RTEMS_Malloc_Sbrk_amount = length;
          
           /*
           * If the starting address is 0 then we are to attempt to
           * get length worth of memory using sbrk. Make sure we
           * align the address that we get back.
           */
          
           if (  !starting_address ) {
           uaddress = (  uintptr_t )sbrk(  length );
          
           if (  uaddress == (  uintptr_t ) -1 ) {
           rtems_fatal_error_occurred(   RTEMS_NO_MEMORY  );
           /* DOES NOT RETURN!!! */
           }
          
           if (  uaddress & (  CPU_HEAP_ALIGNMENT-1 ) ) {
           old_address = uaddress;
           uaddress = (  uaddress + CPU_HEAP_ALIGNMENT ) & ~(  CPU_HEAP_ALIGNMENT-1 );
          
           /*
           * adjust the length by whatever we aligned by
           */
           length -= uaddress - old_address;
           }
          
           starting_address = (  void * )uaddress;
           }
           return starting_address;
          }
          
      67  void *malloc_sbrk_extend_and_allocate(  
           size_t size
           )
          {
           uint32_t sbrk_amount;
           void *starting_address;
           uint32_t the_size;
           void *return_this;
          
           /*
           * Round to the "requested sbrk amount" so hopefully we won't have
           * to grow again for a while. This effectively does sbrk(   ) calls
           * in "page" amounts.
           */
          
           sbrk_amount = RTEMS_Malloc_Sbrk_amount;
          
           if (   sbrk_amount == 0  )
           return (  void * ) 0;
          
           the_size = (  (  size + sbrk_amount ) / sbrk_amount * sbrk_amount );
          
           starting_address = (  void * ) sbrk(  the_size );
           if (   starting_address == (  void* ) -1  )
           return (  void * ) 0;
          
           if (   !_Protected_heap_Extend(  
           RTEMS_Malloc_Heap,   starting_address,   the_size )  ) {
           sbrk(  -the_size );
           errno = ENOMEM;
           return (  void * ) 0;
           }
          
           MSBUMP(  space_available,   the_size );
          
           return_this = _Protected_heap_Allocate(   RTEMS_Malloc_Heap,   size  );
           return return_this;
          }
          
          
          rtems_malloc_sbrk_functions_t rtems_malloc_sbrk_helpers_table = {
           malloc_sbrk_initialize,  
           malloc_sbrk_extend_and_allocate
          };
          
          

libcsupport/src/malloc_statistics_helpers.c

       1  
          /*
           * _calloc_r Implementation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: malloc_statistics_helpers.c,  v 1.7 2009/09/14 14:48:38 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include "malloc_p.h"
          
          #include <sys/reent.h>
          #include <stdlib.h>
          
          
      26  static void rtems_malloc_statistics_initialize(   void  )
          {
           /*
           * Zero all the statistics
           */
           (  void ) memset(  &rtems_malloc_statistics,   0,   sizeof(  rtems_malloc_statistics ) );
          }
          
      34  static void rtems_malloc_statistics_at_malloc(  
           void *pointer
           )
          {
           uintptr_t actual_size = 0;
           uint32_t current_depth;
           rtems_malloc_statistics_t *s = &rtems_malloc_statistics;
          
           if (   !pointer  )
           return;
          
           _Protected_heap_Get_block_size(  RTEMS_Malloc_Heap,   pointer,   &actual_size );
          
           MSBUMP(  lifetime_allocated,   actual_size );
          
           current_depth = (  uint32_t ) (  s->lifetime_allocated - s->lifetime_freed );
           if (  current_depth > s->max_depth )
           s->max_depth = current_depth;
          }
          
          /*
           * If the pointer is not in the heap,   then we won't be able to get its
           * size and thus we skip updating the statistics.
           */
      58  static void rtems_malloc_statistics_at_free(  
           void *pointer
           )
          {
           uintptr_t size;
          
           if (  _Protected_heap_Get_block_size(  RTEMS_Malloc_Heap,   pointer,   &size )  ) {
           MSBUMP(  lifetime_freed,   size );
           }
          }
          
          rtems_malloc_statistics_functions_t rtems_malloc_statistics_helpers_table = {
           rtems_malloc_statistics_initialize,  
           rtems_malloc_statistics_at_malloc,  
           rtems_malloc_statistics_at_free,  
          };
          
          #endif

libcsupport/src/malloc_walk.c

       1  /*
           * malloc_walk Implementation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: malloc_walk.c,  v 1.4 2009/09/14 14:48:38 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include "malloc_p.h"
          
          #include <stdlib.h>
          
      23  void malloc_walk(  size_t source,   size_t printf_enabled )
          {
           _Protected_heap_Walk(   RTEMS_Malloc_Heap,   (  int ) source,   printf_enabled  );
          }
          
          #endif

libcsupport/src/mallocfreespace.c

       1  /*
           * RTEMS Malloc Get Free Information
           *
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mallocfreespace.c,  v 1.11 2010/07/04 14:53:44 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          #include <rtems/libcsupport.h>
          #include <rtems/score/protectedheap.h>
          
          #include <stdio.h>
          #include <stdlib.h>
          #include <sys/types.h>
          #include <errno.h>
          #include <string.h>
          
          #include "malloc_p.h"
          
          /*
           * Find amount of free heap remaining
           */
          
      36  size_t malloc_free_space(   void  )
          {
           Heap_Information info;
          
           _Protected_heap_Get_free_information(   RTEMS_Malloc_Heap,   &info  );
           return (  size_t ) info.largest;
          }

libcsupport/src/mallocgetheapptr.c

       1  /*
           * RTEMS Malloc Get Heap Pointer -- Primarily for Debug
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mallocgetheapptr.c,  v 1.1 2010/08/10 13:15:30 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          #include <rtems/libcsupport.h>
          #include "malloc_p.h"
          
      23  Heap_Control *malloc_get_heap_pointer(   void  )
          {
           return RTEMS_Malloc_Heap;
          }

libcsupport/src/mallocinfo.c

       1  /*
           * RTEMS Malloc Get Status Information
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mallocinfo.c,  v 1.3 2008/09/17 18:37:55 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          #include <rtems/libcsupport.h>
          #include <rtems/score/protectedheap.h>
          
          extern Heap_Control *RTEMS_Malloc_Heap;
          
          /*
           * Find amount of free heap remaining
           */
          
      30  int malloc_info(  
           Heap_Information_block *the_info
           )
          {
           if (   !the_info  )
           return -1;
          
           _Protected_heap_Get_information(   RTEMS_Malloc_Heap,   the_info  );
           return 0;
          }

libcsupport/src/mallocsetheapptr.c

       1  /*
           * RTEMS Malloc Set Heap Pointer -- Primarily for Debug
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mallocsetheapptr.c,  v 1.1 2010/08/10 13:15:30 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          #include <rtems/libcsupport.h>
          #include "malloc_p.h"
          
      23  void malloc_set_heap_pointer(  
           Heap_Control *new_heap
           )
          {
           RTEMS_Malloc_Heap = new_heap;
          }

libcsupport/src/mkdir.c

       1  /*
           * mkdir(   ) - POSIX 1003.1b 5.4.1 - Make a Directory
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mkdir.c,  v 1.5 2004/04/15 13:24:45 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          
      24  int mkdir(  
           const char *pathname,  
           mode_t mode
           )
          {
           return mknod(   pathname,   mode | S_IFDIR,   0LL );
          }

libcsupport/src/mkfifo.c

       1  /*
           * mkfifo(   ) - POSIX 1003.1b 5.4.1 - Make a FIFO Special File
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mkfifo.c,  v 1.4 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <errno.h>
          
      22  int mkfifo(  
           const char *path,  
           mode_t mode
           )
          {
           return mknod(   path,   mode | S_IFIFO,   0LL  );
          }

libcsupport/src/mknod.c

       1  /*
           * mknod(   )
           *
           * This routine is not defined in the POSIX 1003.1b standard but is
           * commonly supported on most UNIX and POSIX systems. It is the
           * foundation for creating file system objects.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mknod.c,  v 1.15 2010/07/01 15:12:37 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      32  int mknod(  
           const char *pathname,  
           mode_t mode,  
           dev_t dev
           )
          {
           rtems_filesystem_location_info_t temp_loc;
           int i;
           const char *name_start;
           int result;
          
           if (   !(  mode & (  S_IFREG|S_IFCHR|S_IFBLK|S_IFIFO )  )  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           rtems_filesystem_get_start_loc(   pathname,   &i,   &temp_loc  );
          
           result = (  *temp_loc.ops->evalformake_h )(  
           &pathname[i],  
           &temp_loc,  
           &name_start
            );
           if (   result != 0  )
           return -1;
          
           result = (  *temp_loc.ops->mknod_h )(   name_start,   mode,   dev,   &temp_loc  );
          
           rtems_filesystem_freenode(   &temp_loc  );
          
           return result;
          }

libcsupport/src/mount-mgr.c

       1  /*
           * mount(   )
           *
           * Mange the mount table. You can iterate on mounts and file systems,   as well
           * as add and remove file systems not in the file system confiration table.
           *
           * COPYRIGHT (  c ) Chris Johns <chrisj@rtems.org> 2010.
           *
           * Copyright (  c ) 2010 embedded brains GmbH.
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: mount-mgr.c,  v 1.6 2010/08/27 06:41:08 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <rtems/chain.h>
          #include <rtems/seterr.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <string.h>
          
          #include <rtems/libio_.h>
          
          typedef struct {
           rtems_chain_node node;
           rtems_filesystem_table_t entry;
          } filesystem_node;
          
      39  static RTEMS_CHAIN_DEFINE_EMPTY(  filesystem_chain );
          
      41  bool rtems_filesystem_iterate(  
           rtems_per_filesystem_routine routine,  
           void *routine_arg
           )
          {
           const rtems_filesystem_table_t *table_entry = &rtems_filesystem_table [0];
           rtems_chain_node *node = NULL;
           bool stop = false;
          
           while (   table_entry->type && !stop  ) {
           stop = (  *routine )(   table_entry,   routine_arg  );
           ++table_entry;
           }
          
           if (   !stop  ) {
           rtems_libio_lock(   );
           for (  
           node = rtems_chain_first(   &filesystem_chain  );
           !rtems_chain_is_tail(   &filesystem_chain,   node  ) && !stop;
           node = rtems_chain_next(   node  )
            ) {
           const filesystem_node *fsn = (  filesystem_node * ) node;
          
           stop = (  *routine )(   &fsn->entry,   routine_arg  );
           }
           rtems_libio_unlock(   );
           }
          
           return stop;
          }
          
          typedef struct {
           const char *type;
           rtems_filesystem_fsmount_me_t mount_h;
          } find_arg;
          
      77  static bool find_handler(  const rtems_filesystem_table_t *entry,   void *arg )
          {
           find_arg *fa = arg;
          
           if (   strcmp(   entry->type,   fa->type  ) != 0  ) {
           return false;
           } else {
           fa->mount_h = entry->mount_h;
          
           return true;
           }
          }
          
          rtems_filesystem_fsmount_me_t
      91  rtems_filesystem_get_mount_handler(  
           const char *type
           )
          {
           find_arg fa = {
           .type = type,  
           .mount_h = NULL
           };
          
           if (   type != NULL  ) {
           rtems_filesystem_iterate(   find_handler,   &fa  );
           }
          
           return fa.mount_h;
          }
          
          int
     108  rtems_filesystem_register(  
           const char *type,  
           rtems_filesystem_fsmount_me_t mount_h
           )
          {
           size_t type_size = strlen(  type ) + 1;
           size_t fsn_size = sizeof(   filesystem_node  ) + type_size;
           filesystem_node *fsn = malloc(   fsn_size  );
           char *type_storage = (  char * ) fsn + sizeof(   *fsn  );
          
           if (   fsn == NULL  )
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
          
           memcpy(  type_storage,   type,   type_size );
           fsn->entry.type = type_storage;
           fsn->entry.mount_h = mount_h;
          
           rtems_libio_lock(   );
           if (   rtems_filesystem_get_mount_handler(   type  ) == NULL  ) {
           rtems_chain_append(   &filesystem_chain,   &fsn->node  );
           } else {
           rtems_libio_unlock(   );
           free(   fsn  );
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
           rtems_libio_unlock(   );
          
           return 0;
          }
          
          int
     140  rtems_filesystem_unregister(  
           const char *type
           )
          {
           rtems_chain_node *node = NULL;
          
           if (   type == NULL  ) {
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           rtems_libio_lock(   );
           for (  
           node = rtems_chain_first(   &filesystem_chain  );
           !rtems_chain_is_tail(   &filesystem_chain,   node  );
           node = rtems_chain_next(   node  )
            ) {
           filesystem_node *fsn = (  filesystem_node * ) node;
          
           if (   strcmp(   fsn->entry.type,   type  ) == 0  ) {
           rtems_chain_extract(   node  );
           free(   fsn  );
           rtems_libio_unlock(   );
          
           return 0;
           }
           }
           rtems_libio_unlock(   );
          
           rtems_set_errno_and_return_minus_one(   ENOENT  );
          }

libcsupport/src/mount-mktgt.c

       1  /**
           * @file
           *
           * @ingroup LibIO
           *
           * @brief mount_and_make_target_path(   ) implementation.
           */
          
          /*
           * Copyright (  c ) 2010
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * D-82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include <rtems/libio.h>
          
      30  int mount_and_make_target_path(  
           const char *source,  
           const char *target,  
           const char *filesystemtype,  
           rtems_filesystem_options_t options,  
           const void *data
           )
          {
           int rv = -1;
          
           if (  target != NULL ) {
           rv = rtems_mkdir(  target,   S_IRWXU | S_IRWXG | S_IRWXO );
           if (  rv == 0 ) {
           rv = mount(  
           source,  
           target,  
           filesystemtype,  
           options,  
           data
            );
           }
           } else {
           errno = EINVAL;
           }
          
           return rv;
          }

libcsupport/src/mount.c

       1  /*
           * mount(   )
           *
           * XXX
           *
           * XXX make sure no required ops are NULL
           * XXX make sure no optional ops you are using are NULL
           * XXX unmount should be required.
           *
           * COPYRIGHT (  c ) 1989-2010.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * Copyright (  c ) 2010 embedded brains GmbH.
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: mount.c,  v 1.41 2010/08/27 06:29:26 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <rtems/chain.h>
          #include <rtems/seterr.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <string.h>
          
          #include <rtems/libio_.h>
          
      38  static RTEMS_CHAIN_DEFINE_EMPTY(  mount_chain );
          
          /*
           * Default pathconfs.
           */
          const rtems_filesystem_limits_and_options_t rtems_filesystem_default_pathconf = {
           5,   /* link_max: count */
           128,   /* max_canon: max formatted input line size */
           7,   /* max_input: max input line size */
           255,   /* name_max: max name */
           255,   /* path_max: max path */
           1024,   /* pipe_buf: pipe buffer size */
           0,   /* posix_async_io: async IO supported on fs,   0=no,   1=yes */
           0 ,   /* posix_chown_restrictions: can chown: 0=no,   1=yes */
           1,   /* posix_no_trunc: error on filenames > max name,   0=no,   1=yes */
           0,   /* posix_prio_io: priority IO,   0=no,   1=yes */
           0,   /* posix_sync_io: file can be sync'ed,   0=no,   1=yes */
           0 /* posix_vdisable: special char processing,   0=no,   1=yes */
          };
          
      58  static bool is_node_fs_root(  
           const rtems_filesystem_mount_table_entry_t *mt_entry,  
           void *arg
           )
          {
           return arg == mt_entry->mt_fs_root.node_access;
          }
          
      66  static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(  
           const char *source_or_null,  
           const char *target_or_null,  
           const char *filesystemtype,  
           size_t *target_length_ptr
           )
          {
           const char *target = target_or_null != NULL ? target_or_null : "/";
           size_t filesystemtype_size = strlen(   filesystemtype  ) + 1;
           size_t source_size = source_or_null != NULL ?
           strlen(   source_or_null  ) + 1 : 0;
           size_t target_size = strlen(   target  ) + 1;
           size_t size = sizeof(   rtems_filesystem_mount_table_entry_t  )
           + filesystemtype_size + source_size + target_size;
           rtems_filesystem_mount_table_entry_t *mt_entry = calloc(   1,   size  );
          
           if (   mt_entry != NULL  ) {
           char *str = (  char * ) mt_entry + sizeof(   *mt_entry  );
          
           memcpy(   str,   filesystemtype,   filesystemtype_size  );
           mt_entry->type = str;
           str += filesystemtype_size;
          
           memcpy(   str,   source_or_null,   source_size  );
           mt_entry->dev = str;
           str += source_size;
          
           memcpy(   str,   target,   target_size  );
           mt_entry->target = str;
           }
          
           *target_length_ptr = target_size - 1;
          
           return mt_entry;
          }
          
          /*
           * mount
           *
           * This routine will attempt to mount a new file system at the specified
           * mount point. A series of tests will be run to determine if any of the
           * following reasons exist to prevent the mount operation:
           *
           * 1 ) The file system type or options are not valid
           * 2 ) No new file system root node is specified
           * 3 ) The selected file system has already been mounted
           * 4 ) The mount point exists with the proper permissions to allow mounting
           * 5 ) The selected mount point already has a file system mounted to it
           *
           */
          
     117  int mount(  
           const char *source,  
           const char *target,  
           const char *filesystemtype,  
           rtems_filesystem_options_t options,  
           const void *data
           )
          {
           rtems_filesystem_fsmount_me_t mount_h = NULL;
           rtems_filesystem_location_info_t loc;
           rtems_filesystem_mount_table_entry_t *mt_entry = NULL;
           rtems_filesystem_location_info_t *loc_to_free = NULL;
           bool has_target = target != NULL;
           size_t target_length = 0;
          
           /*
           * Are the file system options valid?
           */
          
           if (   options != RTEMS_FILESYSTEM_READ_ONLY &&
           options != RTEMS_FILESYSTEM_READ_WRITE  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /*
           * Get mount handler
           */
           mount_h = rtems_filesystem_get_mount_handler(   filesystemtype  );
           if (   !mount_h  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /*
           * Allocate a mount table entry
           */
           mt_entry = alloc_mount_table_entry(  
           source,  
           target,  
           filesystemtype,  
           &target_length
            );
           if (   !mt_entry  )
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
          
           mt_entry->mt_fs_root.mt_entry = mt_entry;
           mt_entry->options = options;
           mt_entry->pathconf_limits_and_options = rtems_filesystem_default_pathconf;
          
           /*
           * The mount_point should be a directory with read/write/execute
           * permissions in the existing tree.
           */
          
           if (   has_target  ) {
           if (   rtems_filesystem_evaluate_path(  
           target,   target_length,   RTEMS_LIBIO_PERMS_RWX,   &loc,   true  ) == -1  )
           goto cleanup_and_bail;
          
           loc_to_free = &loc;
          
           /*
           * Test to see if it is a directory
           */
          
           if (   loc.ops->node_type_h(   &loc  ) != RTEMS_FILESYSTEM_DIRECTORY  ) {
           errno = ENOTDIR;
           goto cleanup_and_bail;
           }
          
           /*
           * You can only mount one file system onto a single mount point.
           */
          
           if (   rtems_filesystem_mount_iterate(   is_node_fs_root,   loc.node_access  )  ) {
           errno = EBUSY;
           goto cleanup_and_bail;
           }
          
           /*
           * This must be a good mount point,   so move the location information
           * into the allocated mount entry. Note: the information that
           * may have been allocated in loc should not be sent to freenode
           * until the system is unmounted. It may be needed to correctly
           * traverse the tree.
           */
          
           mt_entry->mt_point_node.node_access = loc.node_access;
           mt_entry->mt_point_node.handlers = loc.handlers;
           mt_entry->mt_point_node.ops = loc.ops;
           mt_entry->mt_point_node.mt_entry = loc.mt_entry;
          
           /*
           * This link to the parent is only done when we are dealing with system
           * below the base file system
           */
          
           if (   loc.ops->mount_h(   mt_entry  )  ) {
           goto cleanup_and_bail;
           }
           } else {
           /*
           * Do we already have a base file system ?
           */
           if (   !rtems_chain_is_empty(   &mount_chain  )  ) {
           errno = EINVAL;
           goto cleanup_and_bail;
           }
          
           /*
           * This is a mount of the base file system --> The
           * mt_point_node.node_access will be left to null to indicate that this
           * is the root of the entire file system.
           */
           }
          
           if (   (  *mount_h )(   mt_entry,   data  )  ) {
           /*
           * Try to undo the mount operation
           */
           loc.ops->unmount_h(   mt_entry  );
           goto cleanup_and_bail;
           }
          
           /*
           * Add the mount table entry to the mount table chain
           */
           rtems_libio_lock(   );
           rtems_chain_append(   &mount_chain,   &mt_entry->Node  );
           rtems_libio_unlock(   );
          
           if (   !has_target  )
           rtems_filesystem_root = mt_entry->mt_fs_root;
          
           return 0;
          
          cleanup_and_bail:
          
           free(   mt_entry  );
          
           if (   loc_to_free  )
           rtems_filesystem_freenode(   loc_to_free  );
          
           return -1;
          }
          
     260  bool rtems_filesystem_mount_iterate(  
           rtems_per_filesystem_mount_routine routine,  
           void *routine_arg
           )
          {
           rtems_chain_node *node = NULL;
           bool stop = false;
          
           rtems_libio_lock(   );
           for (  
           node = rtems_chain_first(   &mount_chain  );
           !rtems_chain_is_tail(   &mount_chain,   node  ) && !stop;
           node = rtems_chain_next(   node  )
            ) {
           const rtems_filesystem_mount_table_entry_t *mt_entry =
           (  rtems_filesystem_mount_table_entry_t * ) node;
          
           stop = (  *routine )(   mt_entry,   routine_arg  );
           }
           rtems_libio_unlock(   );
          
           return stop;
          }

libcsupport/src/newlibc_exit.c

       1  /*
           * Implementation of hooks for the CYGNUS newlib libc
           * These hooks set things up so that:
           * + '_REENT' is switched at task switch time.
           *
           * COPYRIGHT (  c ) 1994 by Division Incorporated
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: newlibc_exit.c,  v 1.9 2009/11/29 13:35:32 ralf Exp $
           *
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          
          #if defined(  RTEMS_NEWLIB )
          #include <rtems/libcsupport.h>
          
          /* Since we compile with strict ANSI we need to undef it to get
           * prototypes for extensions
           */
          #undef __STRICT_ANSI__
          
          #include <stdlib.h> /* for free(   ) */
          #include <string.h> /* for memset(   ) */
          
          #include <sys/reent.h> /* for extern of _REENT (  aka _impure_ptr ) */
          #include <errno.h>
          
          #include <stdio.h>
          
      39  int _fwalk(  struct _reent *ptr,   int (  *function ) (  FILE * )  );
          
          /* do we think we are reentrant? */
          extern int libc_reentrant;
          extern struct _reent * const _global_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
          
          /*
           * CYGNUS newlib routine that does atexit(   ) processing and flushes
           * stdio streams
           * undocumented
           */
          
      51  extern void _wrapup_reent(  struct _reent * );
      52  extern void _reclaim_reent(  struct _reent * );
          
      54  void libc_wrapup(  void )
          {
           /*
           * In case RTEMS is already down,   don't do this. It could be
           * dangerous.
           */
          
           if (  !_System_state_Is_up(  _System_state_Get(   ) ) )
           return;
          
           /*
           * This was already done if the user called exit(   ) directly .
           _wrapup_reent(  0 );
           */
          
           if (  _REENT != _global_impure_ptr ) {
           _wrapup_reent(  _global_impure_ptr );
          #if 0
           /* Don't reclaim this one,   just in case we do printfs
           * on the way out to ROM.
           */
           _reclaim_reent(  &libc_global_reent );
          #endif
           _REENT = _global_impure_ptr;
           }
          
           /*
           * Try to drain output buffers.
           *
           * Should this be changed to do *all* file streams?
           * _fwalk (  _REENT,   fclose );
           */
          
           fclose (  stdin );
           fclose (  stdout );
           fclose (  stderr );
          }
          
          /*
           * Function: _exit
           * Created: 94/12/10
           *
           * Description:
           * Called from exit(   ) after it does atexit(   ) processing and stdio fflush's
           *
           * called from bottom of exit(   ) to really delete the task.
           * If we are using reentrant libc,   then let the delete extension
           * do all the work,   otherwise if a shutdown is in progress,  
           * then just do it.
           *
           * Parameters:
           * exit status
           *
           * Returns:
           * does not return
           *
           * Side Effects:
           *
           * Notes:
           *
           *
           * Deficiencies/ToDo:
           *
           *
           */
          
          #include <unistd.h>
          
          /* FIXME: These defines are a blatant hack */
           #define EXIT_SYMBOL _exit
          
           #if defined(  __AVR__ )
           #undef __USE_INIT_FINI__
           #endif
           #if defined(  __USE_INIT_FINI__ )
           #if defined(  __m32r__ )
           #define FINI_SYMBOL __fini
           #else
           #define FINI_SYMBOL _fini
           #endif
          
     135   extern void FINI_SYMBOL(   void  );
           #endif
          
     138  void EXIT_SYMBOL(  int status )
          {
           /*
           * If the toolset uses init/fini sections,   then we need to
           * run the global destructors now.
           */
           #if defined(  __USE_INIT_FINI__ )
           FINI_SYMBOL(   );
           #endif
          
           /*
           * We need to do the exit processing on the global reentrancy structure.
           * This has already been done on the per task reentrancy structure
           * associated with this task.
           */
          
           libc_wrapup(   );
           rtems_shutdown_executive(  status );
           for (  ;; ) ; /* to avoid warnings */
          }
          
          
          #endif

libcsupport/src/newlibc_init.c

       1  /*
           * Implementation of hooks for the CYGNUS newlib libc
           * These hooks set things up so that:
           * + '_REENT' is switched at task switch time.
           *
           * COPYRIGHT (  c ) 1994 by Division Incorporated
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: newlibc_init.c,  v 1.3 2009/11/29 13:35:32 ralf Exp $
           *
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB )
          
          /*
           * Init libc for CYGNUS newlib
           *
           * Set up _REENT to use our global libc_global_reent.
           * (  newlib provides a global of its own,   but we prefer our own name for it )
           *
           * If reentrancy is desired (  which it should be ),   then
           * we install the task extension hooks to maintain the
           * newlib reentrancy global variable _REENT on task
           * create,   delete,   switch,   exit,   etc.
           *
           */
          
          
          void
      37  libc_init(  void )
          {
          }
          
          #endif

libcsupport/src/newlibc_reent.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: newlibc_reent.c,  v 1.4 2009/10/14 16:27:54 ralf Exp $
           *
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          
          #if defined(  RTEMS_NEWLIB )
          #include <rtems/libcsupport.h>
          
          /* Since we compile with strict ANSI we need to undef it to get
           * prototypes for extensions
           */
          #undef __STRICT_ANSI__
          
          #include <stdlib.h> /* for free(   ) */
          #include <string.h> /* for memset(   ) */
          
          #include <sys/reent.h> /* for extern of _REENT (  aka _impure_ptr ) */
          #include <errno.h>
          
          /*
           * NOTE:
           * There is some problem with doing this on the hpux version
           * of the UNIX simulator (  symptom is printf core dumps ),   so
           * we just don't for now.
           * Not sure if this is a problem with hpux,   newlib,   or something else.
           */
          
          #include <stdio.h>
          
      41  int _fwalk(  struct _reent *ptr,   int (  *function ) (  FILE * )  );
          
          extern struct _reent * const _global_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
          /*
           * reent struct allocation moved here from libc_start_hook(   ) to avoid
           * mutual exclusion problems when memory is allocated from the start hook.
           *
           * Memory is also now allocated from the workspace rather than the heap.
           * -- ptorre 9/30/03
           */
      51  bool newlib_create_hook(  
           rtems_tcb *current_task __attribute__(  (  unused ) ),  
           rtems_tcb *creating_task
           )
          {
           struct _reent *ptr;
          
           if (  _Thread_libc_reent == 0 )
           {
           _REENT = _global_impure_ptr;
          
           _Thread_Set_libc_reent (  &_REENT );
           }
          
           /* NOTE: The RTEMS malloc is reentrant without a reent ptr since
           * it is based on the Classic API Region Manager.
           */
          
           #define REENT_MALLOCED 0
           #if REENT_MALLOCED
           ptr = (  struct _reent * ) calloc(  1,   sizeof(  struct _reent ) );
           #else
           /* It is OK to allocate from the workspace because these
           * hooks run with thread dispatching disabled.
           */
           ptr = (  struct _reent * ) _Workspace_Allocate(  sizeof(  struct _reent ) );
           #endif
          
           if (  ptr ) {
           _REENT_INIT_PTR(  (  ptr ) ); /* GCC extension: structure constants */
           creating_task->libc_reent = ptr;
           return TRUE;
           }
          
           return FALSE;
          }
          
          /*
           * Called for all user TASKS (  system tasks are MPCI Receive Server and IDLE )
           */
          
          #ifdef NEED_SETVBUF
      93  void newlib_begin_hook(  rtems_tcb *current_task )
          {
           setvbuf(   stdout,   NULL,   _IOLBF,   BUFSIZ  );
          }
          #endif
          
          /*
           * Called when a task is deleted.
           * Must restore the new lib reentrancy state for the new current
           * task.
           *
           */
          
     106  int newlib_free_buffers(  
           FILE *fp
           )
          {
           switch (   fileno(  fp )  ) {
           case 0:
           case 1:
           case 2:
           if (  fp->_flags & __SMBF ) {
           free(   fp->_bf._base  );
           fp->_flags &= ~__SMBF;
           fp->_bf._base = fp->_p = (  unsigned char * ) NULL;
           }
           break;
           default:
           fclose(  fp );
           }
           return 0;
          }
          
     126  void newlib_delete_hook(  
           rtems_tcb *current_task,  
           rtems_tcb *deleted_task
           )
          {
           struct _reent *ptr;
          
           /*
           * The reentrancy structure was allocated by newlib using malloc(   )
           */
          
           if (  current_task == deleted_task ) {
           ptr = _REENT;
           } else {
           ptr = deleted_task->libc_reent;
           }
          
           if (  ptr && ptr != _global_impure_ptr ) {
          /*
           _wrapup_reent(  ptr );
           _reclaim_reent(  ptr );
          */
           /*
           * Just in case there are some buffers lying around.
           */
           _fwalk(  ptr,   newlib_free_buffers );
          #if REENT_MALLOCED
           free(  ptr );
          #else
           _Workspace_Free(  ptr );
          #endif
           }
          
           deleted_task->libc_reent = NULL;
          
           /*
           * Require the switch back to another task to install its own
           */
          
           if (   current_task == deleted_task  ) {
           _REENT = 0;
           }
          }
          
          #endif

libcsupport/src/open.c

       1  /*
           * open(   ) - POSIX 1003.1 5.3.1 - Open a File
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: open.c,  v 1.28 2010/08/23 23:19:07 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          #include <fcntl.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          #include <unistd.h>
          
          /*
           * Returns file descriptor on success or -1 and errno set to one of the
           * following:
           *
           * EACCESS - Seach permission is denied on a component of the path prefix,  
           * or the file exists and the permissions specified by the
           * flags are denied,   or the file does not exist and write
           * permission is denied for the parent directory of the file
           * to be created,   or O_TRUNC is specified and write permission
           * is denied.
           * EEXIST - O_CREAT and O_EXCL are set and the named file exists.
           * EINTR - The open(   operation was interrupted by a signal.
           * EINVAL - This implementation does not support synchronized IO for this
           * file.
           * EISDIR - The named file is a directory and the flags argument
           * specified write or read/write access.
           * EMFILE - Too many file descriptors are in used by this process.
           * ENAMETOOLONG -
           * The length of the path exceeds PATH_MAX or a pathname
           * component is longer than NAME_MAX while POSIX_NO_TRUNC
           * is in effect.
           * ENFILE - Too many files are open in the system.
           * ENOENT - O_CREAT is not set and and the anmed file does not exist,  
           * or O_CREAT is set and either the path prefix does not exist
           * or the path argument points to an empty string.
           * ENOSPC - The directory or file system that would contain the new file
           * cannot be extended.
           * ENOTDIR - A component of the path prefix is not a directory.
           * ENXIO - O_NONBLOCK is set,   the named file is a FIFO,   O_WRONLY is
           * set,   and no process has the file open for reading.
           * EROFS - The named file resides on a read-only file system and either
           * O_WRONLY,   O_RDWR,   O_CREAT (  if the file does not exist ),   or
           * O_TRUNC is set in the flags argument.
           */
          
      60  int open(  
           const char *pathname,  
           int flags,  
           ...
           )
          {
           va_list ap;
           int mode;
           int rc;
           rtems_libio_t *iop = 0;
           int status;
           rtems_filesystem_location_info_t loc;
           rtems_filesystem_location_info_t *loc_to_free = NULL;
           int eval_flags;
          
           /*
           * Set the Evaluation flags
           */
           eval_flags = 0;
           status = flags + 1;
           if (   (   status & _FREAD  ) == _FREAD  )
           eval_flags |= RTEMS_LIBIO_PERMS_READ;
           if (   (   status & _FWRITE  ) == _FWRITE  )
           eval_flags |= RTEMS_LIBIO_PERMS_WRITE;
          
           va_start(  ap,   flags );
          
           mode = va_arg(   ap,   int  );
          
           /*
           * NOTE: This comment is OBSOLETE. The proper way to do this now
           * would be to support a magic mounted file system.
           *
           * Additional external I/O handlers would be supported by adding
           * code to pick apart the pathname appropriately. The networking
           * code does not require changes here since network file
           * descriptors are obtained using socket(   ),   not open(   ).
           */
          
           /* allocate a file control block */
           iop = rtems_libio_allocate(   );
           if (   iop == 0  ) {
           rc = ENFILE;
           goto done;
           }
          
           /*
           * See if the file exists.
           */
           status = rtems_filesystem_evaluate_path(  
           pathname,   strlen(   pathname  ),   eval_flags,   &loc,   true  );
          
           if (   status == -1  ) {
           if (   errno != ENOENT  ) {
           rc = errno;
           goto done;
           }
          
           /* If the file does not exist and we are not trying to create it--> error */
           if (   !(  flags & O_CREAT )  ) {
           rc = ENOENT;
           goto done;
           }
          
           /* Create the node for the new regular file */
           rc = mknod(   pathname,   S_IFREG | mode,   0LL  );
           if (   rc  ) {
           rc = errno;
           goto done;
           }
          
           /*
           * After we do the mknod(   ),   we have to evaluate the path to get the
           * "loc" structure needed to actually have the file itself open.
           * So we created it,   and then we need to have "look it up."
           */
           status = rtems_filesystem_evaluate_path(  
           pathname,   strlen(   pathname  ),   0x0,   &loc,   true  );
           if (   status != 0  ) { /* The file did not exist */
           rc = EACCES;
           goto done;
           }
          
           } else if (  (  flags & (  O_EXCL|O_CREAT ) ) == (  O_EXCL|O_CREAT ) ) {
           /* We were trying to create a file that already exists */
           rc = EEXIST;
           loc_to_free = &loc;
           goto done;
           }
          
           loc_to_free = &loc;
          
           /*
           * Fill in the file control block based on the loc structure
           * returned by successful path evaluation.
           */
           iop->flags |= rtems_libio_fcntl_flags(   flags  );
           iop->pathinfo = loc;
          
           rc = (  *iop->pathinfo.handlers->open_h )(   iop,   pathname,   flags,   mode  );
           if (   rc  ) {
           rc = errno;
           goto done;
           }
          
           /*
           * Optionally truncate the file.
           */
           if (   (  flags & O_TRUNC ) == O_TRUNC  ) {
           rc = ftruncate(   iop - rtems_libio_iops,   0  );
           if (   rc  ) {
           if(  errno ) rc = errno;
           close(   iop - rtems_libio_iops  );
           /* those are released by close(   ): */
           iop = 0;
           loc_to_free = NULL;
           }
           }
          
           /*
           * Single exit and clean up path.
           */
          done:
           va_end(  ap );
          
           if (   rc  ) {
           if (   iop  )
           rtems_libio_free(   iop  );
           if (   loc_to_free  )
           rtems_filesystem_freenode(   loc_to_free  );
           rtems_set_errno_and_return_minus_one(   rc  );
           }
          
           return iop - rtems_libio_iops;
          }
          
          /*
           * _open_r
           *
           * This is the Newlib dependent reentrant version of open(   ).
           */
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__OPEN_R )
          
          #include <reent.h>
          
     206  int _open_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           const char *buf,  
           int flags,  
           int mode
           )
          {
           return open(   buf,   flags,   mode  );
          }
          #endif

libcsupport/src/open_dev_console.c

       1  /*
           * open_dev_console - open /dev/console
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: open_dev_console.c,  v 1.3 2009/11/29 13:35:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <fcntl.h>
          
          /*
           * This is a replaceable stub which opens the console,   if present.
           */
      25  void open_dev_console(  void )
          {
           int stdin_fd;
           int stdout_fd;
           int stderr_fd;
          
           /*
           * Attempt to open /dev/console.
           */
           if (  (  stdin_fd = open(  "/dev/console",   O_RDONLY,   0 ) ) == -1 ) {
           /*
           * There may not be a console driver so this is OK.
           */
           return;
           }
          
           /*
           * But if we find /dev/console once,   we better find it twice more
           * or something is REALLY wrong.
           */
           if (  (  stdout_fd = open(  "/dev/console",   O_WRONLY,   0 ) ) == -1 )
           rtems_fatal_error_occurred(   0x55544431  ); /* error STD1 */
          
           if (  (  stderr_fd = open(  "/dev/console",   O_WRONLY,   0 ) ) == -1 )
           rtems_fatal_error_occurred(   0x55544432  ); /* error STD2 */
          }
          

libcsupport/src/opendir.c

       1  /*
           * opendir(   ) - POSIX 1003.1b - XXX
           *
           * This was copied from Newlib 1.8.0.
           *
           *
           * Copyright (  c ) 1983 Regents of the University of California.
           * 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.
           * 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.
           */
          
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          static char sccsid[] = "@(  # )opendir.c 5.11 (  Berkeley ) 2/23/91";
          #endif /* LIBC_SCCS and not lint */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_OPENDIR
          
          #include <dirent.h>
          #include <fcntl.h>
          #include <stdlib.h>
          #include <unistd.h>
          
          /*
           * open a directory.
           */
          DIR *
      58  opendir(  
           const char *name  )
          {
           register DIR *dirp;
           register int fd;
          
           if (  (  fd = open(  name,   0 ) ) == -1 )
           return NULL;
           if (  fcntl(  fd,   F_SETFD,   1 ) == -1 ||
           (  dirp = (  DIR * )malloc(  sizeof(  DIR ) ) ) == NULL ) {
           close (  fd );
           return NULL;
           }
           /*
           * If CLSIZE is an exact multiple of DIRBLKSIZ,   use a CLSIZE
           * buffer that it cluster boundary aligned.
           * Hopefully this can be a big win someday by allowing page trades
           * to user space to be done by getdirentries(   )
           */
           dirp->dd_buf = malloc (  512 );
           dirp->dd_len = 512;
          
           if (  dirp->dd_buf == NULL ) {
           close (  fd );
           return NULL;
           }
           dirp->dd_fd = fd;
           dirp->dd_loc = 0;
           dirp->dd_seek = 0;
           /*
           * Set up seek point for rewinddir.
           */
           return dirp;
          }
          
          #endif

libcsupport/src/pathconf.c

       1  /*
           * pathconf(   ) - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pathconf.c,  v 1.4 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          #include <errno.h>
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          
      24  long pathconf(  
           const char *path,  
           int name
           )
          {
           int status;
           int fd;
          
           fd = open(   path,   O_RDONLY  );
           if (   fd == -1  )
           return -1;
          
           status = fpathconf(   fd,   name  );
          
           (  void ) close(   fd  );
          
           return status;
          }

libcsupport/src/pipe.c

       1  /*
           * pipe(   ) - POSIX 1003.1b 6.1.1 Create an Inter-Process Channel
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pipe.c,  v 1.6 2010/06/28 22:14:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <sys/types.h>
          #include <rtems/seterr.h>
          
      22  extern int pipe_create(  int filsdes[2] );
          
      24  int pipe(  
           int filsdes[2]
           )
          {
           if (  filsdes == NULL )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           return pipe_create(  filsdes );
          }

libcsupport/src/posix_memalign.c

       1  /*
           * posix_memalign(   )
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: posix_memalign.c,  v 1.4 2008/01/31 14:14:45 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include "malloc_p.h"
          
          #include <stdlib.h>
          #include <errno.h>
          
      24  int posix_memalign(  
           void **pointer,  
           size_t alignment,  
           size_t size
           )
          {
           /*
           * Update call statistics
           */
           MSBUMP(  memalign_calls,   1 );
          
           if (  (  (  alignment - 1 ) & alignment ) != 0 || (  alignment < sizeof(  void * ) ) )
           return EINVAL;
          
           /*
           * rtems_memalign does all of the error checking work EXCEPT
           * for adding restrictionso on the alignment.
           */
           return rtems_memalign(   pointer,   alignment,   size  );
          }
          #endif

libcsupport/src/printk.c

       1  /*
           * (  C ) Copyright 1997 -
           * - NavIST Group - Real-Time Distributed Systems and Industrial Automation
           *
           * http://pandora.ist.utl.pt
           *
           * Instituto Superior Tecnico * Lisboa * PORTUGAL
           *
           * Disclaimer:
           *
           * This file is provided "AS IS" without warranty of any kind,   either
           * expressed or implied.
           *
           * This code is based on code by: Jose Rufino - IST
           *
           * $Id: printk.c,  v 1.20 2009/05/15 15:02:43 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          #include <stdio.h>
          #include <rtems/bspIo.h>
          
          /*
           * printk
           *
           * Kernel printf function requiring minimal infrastrure.
           */
      32  void printk(  const char *fmt,   ... )
          {
           va_list ap; /* points to each unnamed argument in turn */
          
           va_start(  ap,   fmt ); /* make ap point to 1st unnamed arg */
           vprintk(  fmt,   ap );
           va_end(  ap ); /* clean up when done */
          }

libcsupport/src/printk_plugin.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: printk_plugin.c,  v 1.5 2009/11/29 13:35:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          #include <rtems/bspIo.h>
          
      19  int printk_plugin(  
           void *ignored __attribute__(  (  unused ) ),  
           const char *format,  
           ...
           )
          {
           va_list arg_pointer;
          
           va_start (  arg_pointer,   format );
          
           vprintk(   format,   arg_pointer  );
          
           va_end(  arg_pointer ); /* clean up when done */
          
           return 0;
          }

libcsupport/src/privateenv.c

       1  /*
           * Instantiate a private user environment for the calling thread.
           *
           * Submitted by: fernando.ruiz@ctv.es (  correo@fernando-ruiz.com )
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: privateenv.c,  v 1.17 2010/09/08 07:31:28 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h> /* free */
          
          #include <rtems.h>
          #include <rtems/chain.h>
          #include <rtems/libio_.h>
          
          /* cleanup a user environment
           * NOTE: this must be called with
           * thread dispatching disabled!
           */
          static void
      31  free_user_env(  void *venv )
          {
           rtems_user_env_t *env = (  rtems_user_env_t* ) venv ;
          
           if (  env != &rtems_global_user_env
           #ifdef HAVE_USERENV_REFCNT
           && --env->refcnt <= 0
           #endif
            ) {
           rtems_filesystem_freenode(   &env->current_directory );
           rtems_filesystem_freenode(   &env->root_directory );
           free(  env );
           }
          }
          
      46  rtems_status_code rtems_libio_set_private_env(  void )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           rtems_id task_id = rtems_task_self(   );
           rtems_filesystem_location_info_t root_loc;
           rtems_filesystem_location_info_t current_loc;
           rtems_user_env_t *new_env = NULL;
           int rv = 0;
          
           rv = rtems_filesystem_evaluate_path(  "/",   1,   0,   &root_loc,   0 );
           if (  rv != 0 )
           goto error_0;
          
           rv = rtems_filesystem_evaluate_path(  "/",   1,   0,   &current_loc,   0 );
           if (  rv != 0 )
           goto error_1;
          
           /*
           * Malloc is necessary whenever the current task does not
           * have its own environment in place. This could be:
           * a ) it never had one
           * OR
           * b ) it shared another task's environment
           */
          
           /*
           * Bharath: I'm not sure if the check can be reduced to
           * if(   rtems_current_user_env->task_id != task_id  ) {
           */
          
           if (  
           rtems_current_user_env == &rtems_global_user_env
           || rtems_current_user_env->task_id != task_id
            ) {
           new_env = malloc(  sizeof(  rtems_user_env_t ) );
           if (  new_env == NULL )
           goto error_2;
          
           #ifdef HAVE_USERENV_REFCNT
           new_env->refcnt = 1;
           #endif
          
           sc = rtems_task_variable_add(  
           RTEMS_SELF,  
           (  void* )&rtems_current_user_env,  
           (  void(  * )(  void * ) )free_user_env
            );
           if (  sc != RTEMS_SUCCESSFUL )
           goto error_3;
          
           rtems_current_user_env = new_env;
           }
          
           /* Inherit the global values */
           *rtems_current_user_env = rtems_global_user_env;
          
           rtems_current_user_env->task_id = task_id;
          
           /*
           * Clone the pathlocs. In contrast to most other code we must _not_ free the
           * original locs because what we are trying to do here is forking off clones.
           * The reason is a pathloc can be allocated by the file system and needs to
           * be freed when deleting the environment.
           */
           rtems_filesystem_root = root_loc;
           rtems_filesystem_current = current_loc;
          
           return RTEMS_SUCCESSFUL;
          
          error_3:
           free(  new_env );
          
          error_2:
           rtems_filesystem_freenode(  &current_loc );
          
          error_1:
           rtems_filesystem_freenode(  &root_loc );
          
          error_0:
           return RTEMS_NO_MEMORY;
          }
          
          /*
           * Share the same private environment between two tasks:
           * Task_id (  remote ) and RTEMS_SELF(  current ).
           */
          
          /* NOTE:
           *
           * THIS CODE HAS NO PROTECTION IMPLEMENTED
           *
           * Tasks who wish to share their environments must
           *
           * a ) assert that no participants are concurrently
           * executing
           * libio_share_private_env(   ) and/or libio_set_private_env(   )
           *
           * b ) mutex access to rtems_filesystem_current,   rtems_filesytem_root
           * while changing any of those (  chdir(   ),   chroot(   ) ).
           */
          
     147  rtems_status_code rtems_libio_share_private_env(  rtems_id task_id )
          {
           rtems_status_code sc;
           rtems_user_env_t * shared_user_env;
           rtems_id current_task_id;
          
           /*
           * get current task id
           */
           current_task_id = rtems_task_self(   );
          
           /*
           * If this was an attempt to share the task with self,  
           * if somebody wanted to do it... Lets tell them,   its shared
           */
          
           if(   task_id == current_task_id  )
           return RTEMS_SUCCESSFUL;
           /*
           * Try to get the requested user environment
           */
           sc = rtems_task_variable_get(  
           task_id,  
           (  void* )&rtems_current_user_env,  
           (  void* )&shared_user_env  );
          
           /*
           * If it was not successful,   return the error code
           */
           if (  sc != RTEMS_SUCCESSFUL )
           return sc;
          
           /*
           * If we are here,   we have the required environment to be
           * shared with the current task
           */
          
           /*
           * If we have a current environment in place,   we need to
           * free it,   since we will be sharing the variable with the
           * shared_user_env
           */
          
           if (  rtems_current_user_env->task_id==current_task_id ) {
           rtems_user_env_t *tmp = rtems_current_user_env;
           free_user_env(   tmp  );
           }
          
           /* the current_user_env is the same pointer that remote env */
           rtems_current_user_env = shared_user_env;
          
           /* increase the reference count */
          #ifdef HAVE_USERENV_REFCNT
           rtems_current_user_env->refcnt++;
          #endif
          
           return RTEMS_SUCCESSFUL;
          }

libcsupport/src/putk.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: putk.c,  v 1.2 2009/11/29 13:35:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/bspIo.h>
          
          /*
           * putk
           *
           * Kernel putk (  e.g. puts ) function requiring minimal infrastrure.
           */
      23  void putk(  const char *s )
          {
           const char *p = s;
          
           for (  p=s ; *p ; p++  )
           BSP_output_char(  *p );
           BSP_output_char(  '\n' );
          }

libcsupport/src/read.c

       1  /*
           * read(   ) - POSIX 1003.1b 6.4.1 - Read From a File
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: read.c,  v 1.19 2010/08/23 23:19:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      21  ssize_t read(  
           int fd,  
           void *buffer,  
           size_t count
           )
          {
           ssize_t rc;
           rtems_libio_t *iop;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(   iop  );
           rtems_libio_check_buffer(   buffer  );
           rtems_libio_check_count(   count  );
           rtems_libio_check_permissions(   iop,   LIBIO_FLAGS_READ  );
          
           /*
           * Now process the read(   ).
           */
           rc = (  *iop->pathinfo.handlers->read_h )(   iop,   buffer,   count  );
          
           if (   rc > 0  )
           iop->offset += rc;
          
           return rc;
          }
          
          /*
           * _read_r
           *
           * This is the Newlib dependent reentrant version of read(   ).
           */
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE__READ_R )
          
          #include <reent.h>
          
      58  ssize_t _read_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           int fd,  
           void *buf,  
           size_t nbytes
           )
          {
           return read(   fd,   buf,   nbytes  );
          }
          #endif

libcsupport/src/readdir.c

       1  /*
           * readdir(   ) - POSIX 1003.1b - XXX
           *
           * This was copied from Newlib 1.8.0.
           *
           *
           * Copyright (  c ) 1983 Regents of the University of California.
           * 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.
           * 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.
           */
          
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          static char sccsid[] = "@(  # )readdir.c 5.7 (  Berkeley ) 6/1/90";
          #endif /* LIBC_SCCS and not lint */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_READDIR
          
          #include <dirent.h>
          #include <stdint.h>
          
      52  extern int getdents(  
           int dd_fd,  
           char *dd_buf,  
           int dd_len
           );
          
          /*
           * get next entry in a directory.
           */
          struct dirent *
      62  readdir(   DIR *dirp  )
          {
           register struct dirent *dp;
          
           if (   !dirp  )
           return NULL;
          
           for (  ;; ) {
           if (  dirp->dd_loc == 0 ) {
           dirp->dd_size = getdents (  dirp->dd_fd,  
           dirp->dd_buf,  
           dirp->dd_len );
          
           if (  dirp->dd_size <= 0 )
           return NULL;
           }
           if (  dirp->dd_loc >= dirp->dd_size ) {
           dirp->dd_loc = 0;
           continue;
           }
           dp = (  struct dirent * )(  dirp->dd_buf + dirp->dd_loc );
           if (  (  intptr_t )dp & 03 ) /* bogus pointer check */
           return NULL;
           if (  dp->d_reclen <= 0 ||
           dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc )
           return NULL;
           dirp->dd_loc += dp->d_reclen;
           if (  dp->d_ino == 0 )
           continue;
           return (  dp );
           }
          }
          
          #endif

libcsupport/src/readdir_r.c

       1  /*
           * readdir_r - reentrant version of readdir(   )
           *
           * $Id: readdir_r.c,  v 1.3 2008/12/05 06:42:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_READDIR_R
          
          #include <sys/types.h>
          #include <dirent.h>
          #include <errno.h>
          #include <stdio.h>
          
          /*
           * The RTEMS version of readdir is already thread-safe.
           */
          
      22  int readdir_r(  DIR *dirp,   struct dirent *entry,   struct dirent **result )
          {
           *result = readdir(  dirp );
           if (  *result )
           *entry = **result;
           return *result ? 0 : errno;
          }
          
          #endif

libcsupport/src/readlink.c

       1  /*
           * readlink(   ) - POSIX 1003.1b - X.X.X - XXX
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: readlink.c,  v 1.14 2010/07/01 15:12:37 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      21  ssize_t readlink(  
           const char *pathname,  
           char *buf,  
           size_t bufsize
           )
          {
           rtems_filesystem_location_info_t loc;
           int result;
          
           if (  !buf )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           result = rtems_filesystem_evaluate_path(   pathname,   strlen(   pathname  ),  
           0,   &loc,   false  );
           if (   result != 0  )
           return -1;
          
           if (   (  *loc.ops->node_type_h )(   &loc  ) != RTEMS_FILESYSTEM_SYM_LINK  ){
           rtems_filesystem_freenode(   &loc  );
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           result = (  *loc.ops->readlink_h )(   &loc,   buf,   bufsize  );
          
           rtems_filesystem_freenode(   &loc  );
          
           return result;
          }

libcsupport/src/readv.c

       1  /*
           * readv(   ) - POSIX 1003.1 - Read a Vector
           *
           * OpenGroup URL:
           *
           * http://www.opengroup.org/onlinepubs/009695399/functions/readv.html
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: readv.c,  v 1.7 2010/08/25 22:25:18 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/uio.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      28  ssize_t readv(  
           int fd,  
           const struct iovec *iov,  
           int iovcnt
           )
          {
           ssize_t total;
           int v;
           int bytes;
           rtems_libio_t *iop;
           bool all_zeros;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(   iop  );
           rtems_libio_check_permissions(   iop,   LIBIO_FLAGS_READ  );
          
           /*
           * Argument validation on IO vector
           */
           if (   !iov  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   iovcnt <= 0  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   iovcnt > IOV_MAX  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /*
           * OpenGroup says that you are supposed to return EINVAL if the
           * sum of the iov_len values in the iov array would overflow a
           * ssize_t.
           *
           * Also we would like to ensure that no IO is performed if there
           * are obvious errors in the iovec. So this extra loop ensures
           * that we do not do anything if there is an argument error.
           */
          
           all_zeros = true;
           for (   total=0,   v=0 ; v < iovcnt ; v++  ) {
           ssize_t old;
          
           /*
           * iov[v].iov_len cannot be less than 0 because size_t is unsigned.
           * So we only check for zero.
           */
           if (   iov[v].iov_base == 0  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /* check for wrap */
           old = total;
           total += iov[v].iov_len;
           if (   total < old  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   iov[v].iov_len  )
           all_zeros = false;
           }
          
           /*
           * A readv with all zeros logically has no effect. Even though
           * OpenGroup didn't address this case as they did with writev(   ),  
           * we will handle it the same way for symmetry.
           */
           if (   all_zeros == true  ) {
           return 0;
           }
          
           /*
           * Now process the readv(   ).
           */
           for (   total=0,   v=0 ; v < iovcnt ; v++  ) {
           bytes = (  *iop->pathinfo.handlers->read_h )(  
           iop,  
           iov[v].iov_base,  
           iov[v].iov_len
            );
          
           if (   bytes < 0  )
           return -1;
          
           if (   bytes > 0  ) {
           iop->offset += bytes;
           total += bytes;
           }
          
           if (  bytes != iov[ v ].iov_len )
           break;
           }
          
           return total;
          }

libcsupport/src/realloc.c

       1  /*
           * calloc(   )
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: realloc.c,  v 1.7 2010/06/30 15:36:48 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include "malloc_p.h"
          #include <stdlib.h>
          #include <errno.h>
          
      23  void *realloc(  
           void *ptr,  
           size_t size
           )
          {
           uintptr_t old_size;
           char *new_area;
          
           MSBUMP(  realloc_calls,   1 );
          
           /*
           * Do not attempt to allocate memory if in a critical section or ISR.
           */
          
           if (  _System_state_Is_up(  _System_state_Get(   ) ) ) {
           if (  _Thread_Dispatch_disable_level > 0 )
           return (  void * ) 0;
          
           if (  _ISR_Nest_level > 0 )
           return (  void * ) 0;
           }
          
           /*
           * Continue with realloc(   ).
           */
           if (   !ptr  )
           return malloc(   size  );
          
           if (   !size  ) {
           free(   ptr  );
           return (  void * ) 0;
           }
          
           if (   !_Protected_heap_Get_block_size(  RTEMS_Malloc_Heap,   ptr,   &old_size )  ) {
           errno = EINVAL;
           return (  void * ) 0;
           }
          
           /*
           * Now resize it.
           */
           if (   _Protected_heap_Resize_block(   RTEMS_Malloc_Heap,   ptr,   size  )  ) {
           return ptr;
           }
          
           /*
           * There used to be a free on this error case but it is wrong to
           * free the memory per OpenGroup Single UNIX Specification V2
           * and the C Standard.
           */
          
           new_area = malloc(   size  );
          
           MSBUMP(  malloc_calls,   (  uint32_t ) -1 ); /* subtract off the malloc */
          
           if (   !new_area  ) {
           return (  void * ) 0;
           }
          
           memcpy(   new_area,   ptr,   (  size < old_size ) ? size : old_size  );
           free(   ptr  );
          
           return new_area;
          
          }
          #endif

libcsupport/src/rewinddir.c

       1  /*
           * rewinddir(   ) - POSIX 1003.1b - XXX
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_REWINDDIR
          
          #include <sys/types.h>
          #include <dirent.h>
          #include <stdio.h>
          #include <errno.h>
          #include <unistd.h>
          
      25  void rewinddir(  
           DIR *dirp
           )
          {
           off_t status;
          
           if (   !dirp  )
           return;
          
           status = lseek(   dirp->dd_fd,   0,   SEEK_SET  );
          
           if(   status == -1  )
           return;
          
           dirp->dd_loc = 0;
          }
          
          #endif

libcsupport/src/rmdir.c

       1  /*
           * rmdir(   ) - POSIX 1003.1b - 5.2.2 - Remove a Directory
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rmdir.c,  v 1.19 2010/07/30 22:36:32 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      27  int rmdir(  
           const char *pathname
           )
          {
           int parentpathlen;
           const char *name;
           rtems_filesystem_location_info_t parentloc;
           rtems_filesystem_location_info_t loc;
           int i;
           int result;
           bool free_parentloc = false;
          
           /*
           * Get the parent node of the node we wish to remove. Find the parent path.
           */
          
           parentpathlen = rtems_filesystem_dirname (   pathname  );
          
           if (   parentpathlen == 0  )
           rtems_filesystem_get_start_loc(   pathname,   &i,   &parentloc  );
           else {
           result = rtems_filesystem_evaluate_path(  pathname,   parentpathlen,  
           RTEMS_LIBIO_PERMS_WRITE,  
           &parentloc,  
           false  );
           if (   result != 0  )
           return -1;
          
           free_parentloc = true;
           }
          
           /*
           * Start from the parent to find the node that should be under it.
           */
          
           loc = parentloc;
           name = pathname + parentpathlen;
           name += rtems_filesystem_prefix_separators(   name,   strlen(   name  )  );
          
           result = rtems_filesystem_evaluate_relative_path(   name ,   strlen(   name  ),  
           0,   &loc,   false  );
           if (   result != 0  ) {
           if (   free_parentloc  )
           rtems_filesystem_freenode(   &parentloc  );
           return -1;
           }
          
           /*
           * Verify you can remove this node as a directory.
           */
           if (   (  *loc.ops->node_type_h )(   &loc  ) != RTEMS_FILESYSTEM_DIRECTORY  ) {
           rtems_filesystem_freenode(   &loc  );
           if (   free_parentloc  )
           rtems_filesystem_freenode(   &parentloc  );
           rtems_set_errno_and_return_minus_one(   ENOTDIR  );
           }
          
           /*
           * Use the filesystems rmnod to remove the node.
           */
          
           result = (  *loc.handlers->rmnod_h )(   &parentloc,   &loc  );
          
           rtems_filesystem_freenode(   &loc  );
           if (   free_parentloc  )
           rtems_filesystem_freenode(   &parentloc  );
          
           return result;
          }

libcsupport/src/rtems_malloc.c

       1  /**
           * @file
           *
           * @ingroup libcsupport
           *
           * @brief rtems_malloc(   ) implementation.
           */
          
          /*
           * Copyright (  c ) 2009
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * D-82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems_malloc.c,  v 1.2 2009/11/30 13:05:29 thomas Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include "malloc_p.h"
          
      31  void *rtems_heap_allocate_aligned_with_boundary(  
           size_t size,  
           uintptr_t alignment,  
           uintptr_t boundary
           )
          {
           if (  
           _System_state_Is_up(   _System_state_Get(   )  )
           && !malloc_is_system_state_OK(   )
            ) {
           return NULL;
           }
          
           malloc_deferred_frees_process(   );
          
           /* FIXME: Statistics,   boundary checks */
          
           return _Protected_heap_Allocate_aligned_with_boundary(  
           RTEMS_Malloc_Heap,  
           size,  
           alignment,  
           boundary
            );
          }
          
          #endif

libcsupport/src/rtems_memalign.c

       1  /*
           * rtems_memalign(   ) - Raw aligned allocate from Protected Heap
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtems_memalign.c,  v 1.5 2010/07/01 15:39:59 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_NEWLIB
          #include "malloc_p.h"
          
          #include <stdlib.h>
          #include <errno.h>
          
      24  int rtems_memalign(  
           void **pointer,  
           size_t alignment,  
           size_t size
           )
          {
           void *return_this;
          
           /*
           * Parameter error checks
           */
           if (   !pointer  )
           return EINVAL;
          
           *pointer = NULL;
          
           /*
           * Do not attempt to allocate memory if not in correct system state.
           */
           if (   _System_state_Is_up(  _System_state_Get(   ) ) &&
           !malloc_is_system_state_OK(   )  )
           return EINVAL;
          
           /*
           * If some free's have been deferred,   then do them now.
           */
           malloc_deferred_frees_process(   );
          
           /*
           * Perform the aligned allocation requested
           */
           return_this = _Protected_heap_Allocate_aligned(  
           RTEMS_Malloc_Heap,  
           size,  
           alignment
            );
           if (   !return_this  )
           return ENOMEM;
          
           /*
           * If configured,   update the more involved statistics
           */
           if (   rtems_malloc_statistics_helpers  )
           (  *rtems_malloc_statistics_helpers->at_malloc )(  pointer );
          
           *pointer = return_this;
           return 0;
          }
          #endif

libcsupport/src/rtems_mkdir.c

       1  /**
           * @file
           *
           * @ingroup LibIO
           *
           * @brief rtems_mkdir(   ) implementation.
           *
           * The implementation is based on FreeBSD 'bin/mkdir/mkdir.c' revision 163213.
           */
          
          /*-
           * Copyright (  c ) 2010 embedded brains GmbH.
           *
           * Copyright (  c ) 1983,   1992,   1993
           * The Regents of the University of California. 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.
           * 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.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          
          #include <errno.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          
          #include <rtems/libio.h>
          
          /*
           * Returns 1 if a directory has been created,  
           * 2 if it already existed,   and 0 on failure.
           */
          static int
      61  build(  char *path,   mode_t omode )
          {
           struct stat sb;
           mode_t numask,   oumask;
           int first,   last,   retval;
           char *p;
          
           p = path;
           oumask = 0;
           retval = 1;
           if (  p[0] == '/' ) /* Skip leading '/'. */
           ++p;
           for (  first = 1,   last = 0; !last ; ++p ) {
           if (  p[0] == '\0' )
           last = 1;
           else if (  p[0] != '/' )
           continue;
           *p = '\0';
           if (  !last && p[1] == '\0' )
           last = 1;
           if (  first ) {
           /*
           * POSIX 1003.2:
           * For each dir operand that does not name an existing
           * directory,   effects equivalent to those caused by the
           * following command shall occcur:
           *
           * mkdir -p -m $(  umask -S ),  u+wx $(  dirname dir ) &&
           * mkdir [-m mode] dir
           *
           * We change the user's umask and then restore it,  
           * instead of doing chmod's.
           */
           oumask = umask(  0 );
           numask = oumask & ~(  S_IWUSR | S_IXUSR );
           (  void )umask(  numask );
           first = 0;
           }
           if (  last )
           (  void )umask(  oumask );
           if (  mkdir(  path,   last ? omode : S_IRWXU | S_IRWXG | S_IRWXO ) < 0 ) {
           if (  errno == EEXIST || errno == EISDIR ) {
           if (  stat(  path,   &sb ) < 0 ) {
           retval = 0;
           break;
           } else if (  !S_ISDIR(  sb.st_mode ) ) {
           if (  last )
           errno = EEXIST;
           else
           errno = ENOTDIR;
           retval = 0;
           break;
           }
           if (  last )
           retval = 2;
           } else {
           retval = 0;
           break;
           }
           }
           if (  !last )
           *p = '/';
           }
           if (  !first && !last )
           (  void )umask(  oumask );
           return (  retval );
          }
          
          int
     130  rtems_mkdir(  const char *path,   mode_t mode )
          {
           int success = 0;
           char *dup_path = strdup(  path );
          
           if (  dup_path != NULL ) {
           success = build(  dup_path,   mode );
           free(  dup_path );
           }
          
           return success != 0 ? 0 : -1;
          }

libcsupport/src/scandir.c

       1  /*
           * scandir(   ) - POSIX 1003.1b - XXX
           *
           * This was copied from Newlib 1.8.0.
           *
           *
           * Copyright (  c ) 1983 Regents of the University of California.
           * 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.
           * 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.
           */
          
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          static char sccsid[] = "@(  # )scandir.c 5.10 (  Berkeley ) 2/23/91";
          #endif /* LIBC_SCCS and not lint */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Scan the directory dirname calling select to make a list of selected
           * directory entries then sort using qsort and compare routine dcomp.
           * Returns the number of entries and a pointer to a list of pointers to
           * struct dirent (  through namelist ). Returns -1 if there were any errors.
           */
          
          #ifndef HAVE_SCANDIR
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <dirent.h>
          #include <stdlib.h>
          #include <string.h>
          
          /*
           * The DIRSIZ macro gives the minimum record length which will hold
           * the directory entry. This requires the amount of space in struct dirent
           * without the d_name field,   plus enough space for the name with a terminating
           * null byte (  dp->d_namlen+1 ),   rounded up to a 4 byte boundary.
           */
          #undef DIRSIZ
          /*
          #define DIRSIZ(  dp ) \
           (  (  sizeof (  struct dirent ) - (  MAXNAMLEN+1 ) ) + (  (  (  dp )->d_namlen+1 + 3 ) &~ 3 ) )
          */
          
          #define DIRSIZ(  dp ) \
           (  (  sizeof (  struct dirent ) - (  NAME_MAX+1 ) ) + (  (  (  dp )->d_namlen+1 + 3 ) &~ 3 ) )
          
      77  int
          scandir(  
           const char *dirname,  
           struct dirent ***namelist,  
           int (  *select )(  struct dirent * ),  
           int (  *dcomp )(  const struct dirent **,   const struct dirent ** ) )
          {
           register struct dirent *d = NULL;
           register struct dirent *p = NULL;
           register struct dirent **names = NULL;
           register size_t nitems = 0;
           struct stat stb;
           size_t arraysz;
           DIR *dirp = NULL;
           int i;
          
           if (  (  dirp = opendir(  dirname ) ) == NULL )
           return(  -1 );
           if (  fstat(  dirp->dd_fd,   &stb ) < 0 )
           goto cleanup_and_bail;
          
           /*
           * estimate the array size by taking the size of the directory file
           * and dividing it by a multiple of the minimum size entry.
           */
           arraysz = (  stb.st_size / 24 );
           names = (  struct dirent ** )malloc(  arraysz * sizeof(  struct dirent * ) );
           if (  names == NULL )
           goto cleanup_and_bail;
          
           while (  (  d = readdir(  dirp ) ) != NULL ) {
           if (  select != NULL && !(  *select )(  d ) )
           continue; /* just selected names */
           /*
           * Make a minimum size copy of the data
           */
           p = (  struct dirent * )malloc(  DIRSIZ(  d ) );
           if (  p == NULL )
           goto cleanup_and_bail;
           p->d_ino = d->d_ino;
           p->d_reclen = d->d_reclen;
           p->d_namlen = d->d_namlen;
           strncpy(  p->d_name,   d->d_name,   p->d_namlen + 1 );
           /*
           * Check to make sure the array has space left and
           * realloc the maximum size.
           */
           if (  ++nitems >= arraysz ) {
           if (  fstat(  dirp->dd_fd,   &stb ) < 0 )
           goto cleanup_and_bail; /* just might have grown */
           arraysz = stb.st_size / 12;
           names = (  struct dirent ** )realloc(  (  char * )names,  
           arraysz * sizeof(  struct dirent * ) );
           if (  names == NULL )
           goto cleanup_and_bail;
           }
           names[nitems-1] = p;
           }
           closedir(  dirp );
           if (  nitems && dcomp != NULL ){
           qsort(  names,   nitems,   sizeof(  struct dirent * ),  
           (  int (  * )(  const void *,   const void * ) ) dcomp );
           }
           *namelist = names;
           return(  nitems );
          
          cleanup_and_bail:
          
           if (   dirp  )
           closedir(   dirp  );
          
           if (   names  ) {
           for (  i=0; i < nitems; i++  )
           free(   names[i]  );
           free(   names  );
           }
          
           return(  -1 );
          }
          
          /*
           * Alphabetic order comparison routine for those who want it.
           */
     160  int
          alphasort(  
           const void *d1,  
           const void *d2  )
          {
           return(  strcmp(  (  *(  struct dirent ** )d1 )->d_name,  
           (  *(  struct dirent ** )d2 )->d_name ) );
          }
          #endif

libcsupport/src/seekdir.c

       1  /*
           * seekdir(   ) - POSIX 1003.1b - XXX
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_SEEKDIR
          
          #include <sys/param.h>
          #include <dirent.h>
          #include <stdio.h>
          #include <unistd.h>
          #include <errno.h>
          
      25  void seekdir(  
           DIR *dirp,  
           long loc
           )
          {
           off_t status;
          
           if (   !dirp  )
           return;
          
           status = lseek(   dirp->dd_fd,   loc,   SEEK_SET  );
          
           /*
           * This is not a nice way to error out,   but we have no choice here.
           */
          
           if (   status == -1  )
           return;
          
           dirp->dd_loc = 0;
          }
          
          #endif

libcsupport/src/setegid.c

       1  /*
           * $Id: setegid.c,  v 1.2 2010/08/03 15:56:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/seterr.h>
          #include <rtems/userenv.h>
          
          /*
           * 4.2.1 Get Real User,   Effective User,   Ral Group,   and Effective Group IDs,  
           * P1003.1b-1993,   p. 84
           */
      20  int setegid(  
           gid_t gid
           )
          {
           _POSIX_types_Egid = gid;
           return 0;
          }

libcsupport/src/seteuid.c

       1  /*
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: seteuid.c,  v 1.2 2010/08/03 15:56:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          #include <rtems/userenv.h>
          
      20  int seteuid(   uid_t euid  )
          {
           _POSIX_types_Euid = euid;
           return 0;
          }

libcsupport/src/setgid.c

       1  /*
           * $Id: setgid.c,  v 1.1 2010/08/03 15:46:52 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/userenv.h>
          
          /*
           *
           * 4.2.2 Set User and Group IDs,   P1003.1b-1993,   p. 84
           */
      15  int setgid(  
           gid_t gid
           )
          {
           _POSIX_types_Gid = gid;
           return 0;
          }

libcsupport/src/setpgid.c

       1  /*
           * $Id: setpgid.c,  v 1.3 2009/09/30 04:42:18 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          #include <errno.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 4.3.3 Set Process Group ID for Job Control,   P1003.1b-1993,   p. 89
           */
          
      18  int setpgid(  
           pid_t pid __attribute__(  (  unused ) ),  
           pid_t pgid __attribute__(  (  unused ) )
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

libcsupport/src/setsid.c

       1  /*
           * $Id: setsid.c,  v 1.3 2010/08/03 15:56:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 4.3.2 Create Session and Set Process Group ID,   P1003.1b-1993,   p. 88
           */
          
      18  pid_t setsid(   void  )
          {
           rtems_set_errno_and_return_minus_one(   EPERM  );
          }

libcsupport/src/setuid.c

       1  /*
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: setuid.c,  v 1.2 2010/08/03 15:56:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          #include <rtems/userenv.h>
          
          /*
           *
           * 4.2.2 Set User and Group IDs,   P1003.1b-1993,   p. 84
           */
      24  int setuid(  
           uid_t uid
           )
          {
           _POSIX_types_Uid = uid;
           return 0;
          }

libcsupport/src/sleep_noposix.c

       1  /*
           * Marginal implementations of some POSIX API routines
           * to be used when POSIX is disabled.
           *
           * + kill
           * + _kill_r
           * + __kill
           * + sleep
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: sleep_noposix.c,  v 1.2 2010/03/22 13:38:04 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          
          #include <unistd.h>
          
          /*
           * 3.4.3 Delay Process Execution,   P1003.1b-1993,   p. 81
           *
           * $Id: sleep_noposix.c,  v 1.2 2010/03/22 13:38:04 joel Exp $
           */
          
          #include <time.h>
          #include <unistd.h>
          
          #include <rtems.h>
          
          #if !defined(  RTEMS_POSIX_API )
      37  unsigned int sleep(  
           unsigned int seconds
           )
          {
           rtems_status_code status;
           rtems_interval ticks_per_second;
          
           ticks_per_second = rtems_clock_get_ticks_per_second(   ) * seconds;
          
           status = rtems_task_wake_after(   ticks_per_second  );
          
           /*
           * Returns the "unslept" amount of time. In RTEMS signals are not
           * interruptable,   so tasks really sleep all of the requested time.
           */
          
           return 0;
          }
          #endif

libcsupport/src/stat.c

       1  /*
           * stat(   ) - POSIX 1003.1b 5.6.2 - Get File Status
           *
           * Reused from lstat(   ).
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: stat.c,  v 1.17 2010/07/01 15:12:38 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * lstat(   ) and stat(   ) share the same implementation with a minor
           * difference on how links are evaluated.
           */
          
          #ifndef _STAT_NAME
          #define _STAT_NAME stat
          #define _STAT_R_NAME _stat_r
          #define _STAT_FOLLOW_LINKS true
          #endif
          
          
          #include <rtems.h>
          
          #include <rtems/libio.h>
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <unistd.h>
          #include <fcntl.h>
          #include <errno.h>
          #include <string.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      45  int _STAT_NAME(  
           const char *path,  
           struct stat *buf
           )
          {
           int status;
           rtems_filesystem_location_info_t loc;
          
           /*
           * Check to see if we were passed a valid pointer.
           */
          
           if (   !buf  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           status = rtems_filesystem_evaluate_path(   path,   strlen(   path  ),  
           0,   &loc,   _STAT_FOLLOW_LINKS  );
           if (   status != 0  )
           return -1;
          
           /*
           * Zero out the stat structure so the various support
           * versions of stat don't have to.
           */
          
           memset(   buf,   0,   sizeof(  struct stat )  );
          
           status = (  *loc.handlers->fstat_h )(   &loc,   buf  );
          
           rtems_filesystem_freenode(   &loc  );
          
           return status;
          }
          
          /*
           * _stat_r,   _lstat_r
           *
           * This is the Newlib dependent reentrant version of stat(   ) and lstat(   ).
           */
          
          #if defined(  RTEMS_NEWLIB )
          
          #include <reent.h>
          
      89  int _STAT_R_NAME(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           const char *path,  
           struct stat *buf
           )
          {
           return _STAT_NAME(   path,   buf  );
          }
          #endif

libcsupport/src/statvfs.c

       1  /*
           * COPYRIGHT (  c ) 2009 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: statvfs.c,  v 1.4 2010/07/01 15:12:38 jennifer Exp $
           */
          /*
           * The statvfs as defined by the SUS:
           * http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          #include <sys/statvfs.h>
          
          int
      25  statvfs (  const char *path,   struct statvfs *sb )
          {
           rtems_filesystem_location_info_t loc;
           rtems_filesystem_location_info_t *fs_mount_root;
           rtems_filesystem_mount_table_entry_t *mt_entry;
           int result;
          
           /*
           * Get
           * The root node of the mounted filesytem.
           * The node for the directory that the fileystem is mounted on.
           * The mount entry that is being refered to.
           */
          
           if (   rtems_filesystem_evaluate_path(   path,   strlen(   path  ),   0x0,   &loc,   true  )  )
           return -1;
          
           mt_entry = loc.mt_entry;
           fs_mount_root = &mt_entry->mt_fs_root;
          
           memset (  sb,   0,   sizeof (  struct statvfs ) );
          
           result = (   fs_mount_root->ops->statvfs_h  )(   fs_mount_root,   sb  );
          
           rtems_filesystem_freenode(   &loc  );
          
           return result;
          }

libcsupport/src/strlcat.c

       1  /*
           * utils.c - various utility functions used in pppd.
           *
           * Copyright (  c ) 1999 The Australian National University.
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms are permitted
           * provided that the above copyright notice and this paragraph are
           * duplicated in all such forms and that any documentation,  
           * advertising materials,   and other materials related to such
           * distribution and use acknowledge that the software was developed
           * by the Australian National University. The name of the University
           * may not be used to endorse or promote products derived from this
           * software without specific prior written permission.
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
           * IMPLIED WARRANTIES,   INCLUDING,   WITHOUT LIMITATION,   THE IMPLIED
           * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          
          #ifndef HAVE_STRLCAT
          /*
           * strlcat - like strcat/strncat,   doesn't overflow destination buffer,  
           * always leaves destination null-terminated (  for len > 0 ).
           */
          size_t
      32  strlcat(  
           char *dest,  
           const char *src,  
           size_t len  )
          {
           size_t dlen = strlen(  dest );
          
           return dlen + strlcpy(  dest + dlen,   src,   (  len > dlen? len - dlen: 0 ) );
          }
          #endif

libcsupport/src/strlcpy.c

          /*
           * utils.c - various utility functions used in pppd.
           *
           * Copyright (  c ) 1999 The Australian National University.
           * All rights reserved.
           *
           * Redistribution and use in source and binary forms are permitted
           * provided that the above copyright notice and this paragraph are
           * duplicated in all such forms and that any documentation,  
           * advertising materials,   and other materials related to such
           * distribution and use acknowledge that the software was developed
           * by the Australian National University. The name of the University
           * may not be used to endorse or promote products derived from this
           * software without specific prior written permission.
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
           * IMPLIED WARRANTIES,   INCLUDING,   WITHOUT LIMITATION,   THE IMPLIED
           * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          
          #ifndef HAVE_STRLCPY
          /*
           * strlcpy - like strcpy/strncpy,   doesn't overflow destination buffer,  
           * always leaves destination null-terminated (  for len > 0 ).
           */
          size_t
      32  strlcpy(  dest,   src,   len )
           char *dest;
           const char *src;
           size_t len;
          {
           size_t ret = strlen(  src );
          
           if (  len != 0 ) {
           if (  ret < len )
           strcpy(  dest,   src );
           else {
           strncpy(  dest,   src,   len - 1 );
           dest[len-1] = 0;
           }
           }
           return ret;
          }
          #endif

libcsupport/src/sup_fs_get_start_loc.c

       1   /**
           * @file src/sup_fs_get_start_loc.c
           */
          
          /*
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sup_fs_get_start_loc.c,  v 1.1 2010/06/07 15:07:39 jennifer Exp $
           */
          
          /*
           * rtems_filesystem_get_start_loc
           *
           * Function to determine if path is absolute or relative
           *
           * Parameters:
           *
           * path : IN - path to be checked
           * index: OUT - 0,   if relative,   1 if absolute
           * loc : OUT - location info of root fs if absolute
           * location info of current fs if relative
           *
           * Returns: void
           */
          
          /* Includes */
          
          #include "rtems/libio_.h"
          
      36  void rtems_filesystem_get_start_loc(  const char *path,  
           int *index,  
           rtems_filesystem_location_info_t *loc )
          {
           if (  rtems_filesystem_is_separator(  path[0] ) ) {
           *loc = rtems_filesystem_root;
           *index = 1;
           }
           else {
           *loc = rtems_filesystem_current;
           *index = 0;
           }
          }

libcsupport/src/sup_fs_get_sym_start_loc.c

       1   /**
           * @file src/sup_fs_get_sym_start_loc.c
           */
          
          /*
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sup_fs_get_sym_start_loc.c,  v 1.1 2010/06/07 15:07:39 jennifer Exp $
           */
          
          /*
           * rtems_filesystem_get_sym_start_loc
           *
           * Function to determine if path is absolute or relative
           *
           * Parameters:
           *
           * path : IN - path to be checked
           * index: OUT - 0,   if relative,   1 if absolute
           * loc : OUT - location info of root fs if absolute
           * location info of current fs if relative
           *
           * Returns: void
           */
          
          /* Includes */
          
          #include "rtems/libio_.h"
          
      36  void rtems_filesystem_get_sym_start_loc(  const char *path,  
           int *index,  
           rtems_filesystem_location_info_t *loc )
          {
           if (  rtems_filesystem_is_separator(  path[0] ) ) {
           *loc = rtems_filesystem_root;
           *index = 1;
           }
           else {
           *index = 0;
           }
          }

libcsupport/src/sup_fs_is_separator.c

       1  /**
           * @file src/sup_fs_is_separator.c
           */
          
          /*
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sup_fs_is_separator.c,  v 1.1 2010/06/07 15:07:39 jennifer Exp $
           */
          
          
          /*
           * rtems_filesystem_is_separator
           *
           * Function to determine if a character is a path name separator.
           * This was originally a macro in libio_.h
           *
           * NOTE: This function handles MS-DOS and UNIX style names.
           */
          
      27  int rtems_filesystem_is_separator(  char ch )
          {
           return (  (  ch == '/' ) || (  ch == '\\' ) || (  ch == '\0' ) );
          }

libcsupport/src/symlink.c

       1  /*
           * symlink(   ) - POSIX 1003.1b - X.X.X - XXX
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: symlink.c,  v 1.13 2010/07/01 15:12:38 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      21  int symlink(  
           const char *actualpath,  
           const char *sympath
           )
          {
           rtems_filesystem_location_info_t loc;
           int i;
           const char *name_start;
           int result;
          
           rtems_filesystem_get_start_loc(   sympath,   &i,   &loc  );
          
           result = (  *loc.ops->evalformake_h )(   &sympath[i],   &loc,   &name_start  );
           if (   result != 0  )
           return -1;
          
           result = (  *loc.ops->symlink_h )(   &loc,   actualpath,   name_start );
          
           rtems_filesystem_freenode(   &loc  );
          
           return result;
          }

libcsupport/src/sync.c

       1  /*
           * sync(   ) - XXX ??? where is this defined
           *
           * This function operates by as follows:
           * for all threads
           * for all FILE *
           * fsync(   )
           * fdatasync(   )
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sync.c,  v 1.11 2010/08/26 21:42:21 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* Since we compile with strict ANSI we need to undef it to get
           * prototypes for extensions
           */
          #undef __STRICT_ANSI__
      28  int fdatasync(  int ); /* still not always prototyped */
          
          
          #include <unistd.h>
          #include <stdio.h>
          
          #include <rtems.h>
          /*
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          */
          
          /* XXX check standards -- Linux version appears to be void */
      43  void _fwalk(  struct _reent *,   void * );
          
          
      46  static void sync_wrapper(  FILE *f )
          {
           int fn = fileno(  f );
          
           /*
           * We are explicitly NOT checking the return values as it does not
           * matter if they succeed. We are just making a best faith attempt
           * at both and trusting that we were passed a good FILE pointer.
           */
           fsync(  fn );
           fdatasync(  fn );
          }
          
          /* iterate over all FILE *'s for this thread */
      60  static void sync_per_thread(  Thread_Control *t )
          {
           struct _reent *current_reent;
           struct _reent *this_reent;
          
           /*
           * The sync_wrapper(   ) function will operate on the current thread's
           * reent structure so we will temporarily use that.
           */
           this_reent = t->libc_reent;
           if (   this_reent  ) {
           current_reent = _Thread_Executing->libc_reent;
           _Thread_Executing->libc_reent = this_reent;
           _fwalk (  t->libc_reent,   sync_wrapper );
           _Thread_Executing->libc_reent = current_reent;
           }
          }
          
          /*
           * _global_impure_ptr is not prototyped in any .h files.
           * We have to extern it here.
           */
          extern struct _reent * const _global_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
          
      84  void sync(  void )
          {
          
           /*
           * Walk the one used initially by RTEMS.
           */
           _fwalk(  _global_impure_ptr,   sync_wrapper );
          
           /*
           * XXX Do we walk the one used globally by newlib?
           * XXX Do we need the RTEMS global one?
           */
          
           /*
           * Now walk all the per-thread reentrancy structures.
           */
           rtems_iterate_over_all_threads(  sync_per_thread );
          }

libcsupport/src/tcdrain.c

       1  /*
           * tcdrain(   ) - POSIX 1003.1b 7.2.2 - Line Control Functions
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tcdrain.c,  v 1.8 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #if defined(  RTEMS_NEWLIB )
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <errno.h>
          #include <termios.h>
          /* #include <sys/ioctl.h> */
          
          #include <rtems/libio.h>
          
      29  int tcdrain(  
           int fd
           )
          {
           return ioctl(   fd,   RTEMS_IO_TCDRAIN,   0  );
          }
          
          #endif

libcsupport/src/tcflow.c

       1  /*
           * tcflow(   ) - POSIX 1003.1b 7.2.2 - Line Control Functions
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tcflow.c,  v 1.9 2010/06/07 18:37:16 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB )
          #include <termios.h>
          #include <unistd.h>
          #include <errno.h>
          #include <rtems/seterr.h>
          
      24  int tcflow (  
           int fd __attribute__(  (  unused ) ),  
           int action
           )
          {
           switch (  action ) {
           case TCOOFF:
           case TCOON:
           case TCIOFF:
           case TCION:
           default:
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           /* fd is not validated */
          
           /* When this is supported,   implement it here */
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }
          
          #endif

libcsupport/src/tcflush.c

       1  /*
           * tcflush(   ) - POSIX 1003.1b 7.2.2 - Line Control Functions
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tcflush.c,  v 1.7 2010/06/07 18:37:16 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #if defined(  RTEMS_NEWLIB )
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <errno.h>
          #include <termios.h>
          /* #include <sys/ioctl.h> */
          
          #include <rtems/seterr.h>
          #include <rtems/libio.h>
          
      30  int tcflush (  
           int fd __attribute__(  (  unused ) ),  
           int queue
           )
          {
           switch (  queue ) {
           case TCIFLUSH:
           case TCOFLUSH:
           case TCIOFLUSH:
           default:
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           /* fd is not validated */
          
           /* When this is supported,   implement it here */
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
           return 0;
          }
          
          #endif

libcsupport/src/tcgetattr.c

       1  /*
           * tcgetattr(   ) - POSIX 1003.1b 7.2.1 - Get and Set State
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tcgetattr.c,  v 1.7 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #if defined(  RTEMS_NEWLIB )
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <errno.h>
          #include <termios.h>
          /* #include <sys/ioctl.h> */
          
          #include <rtems/libio.h>
          
      29  int tcgetattr(  
           int fd,  
           struct termios *tp
           )
          {
           return ioctl(   fd,   RTEMS_IO_GET_ATTRIBUTES,   tp  );
          }
          #endif

libcsupport/src/tcgetpgrp.c

       1  /*
           * tcgetprgrp(   ) - POSIX 1003.1b 7.2.3 - Get Foreground Process Group ID
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tcgetpgrp.c,  v 1.1 2009/09/15 05:32:49 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_NEWLIB ) && !defined(  HAVE_TCGETPGRP )
          
          #include <sys/types.h>
          #include <unistd.h>
          
      23  pid_t tcgetpgrp(  int fd __attribute__(  (  unused ) ) )
          {
           return getpid(   );
          }
          
          #endif

libcsupport/src/tcsendbreak.c

       1  /*
           * tcsendbreak(   ) - POSIX 1003.1b 7.2.2 - Line Control Functions
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tcsendbreak.c,  v 1.6 2009/09/15 09:42:46 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #if defined(  RTEMS_NEWLIB )
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <errno.h>
          #include <termios.h>
          /* #include <sys/ioctl.h> */
          
          #include <rtems/libio.h>
          
      29  int tcsendbreak (  
           int fd __attribute__(  (  unused ) ),  
           int duration __attribute__(  (  unused ) )  )
          {
           return 0;
          }
          
          #endif

libcsupport/src/tcsetattr.c

       1  /*
           * tcsetattr(   ) - POSIX 1003.1b 7.2.1 - Get and Set State
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tcsetattr.c,  v 1.10 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #if defined(  RTEMS_NEWLIB )
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <errno.h>
          #include <termios.h>
          /* #include <sys/ioctl.h> */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      31  int tcsetattr(  
           int fd,  
           int opt,  
           struct termios *tp
           )
          {
           switch (  opt ) {
           default:
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          
           case TCSADRAIN:
           if (  ioctl(   fd,   RTEMS_IO_TCDRAIN,   NULL  ) < 0 )
           return -1;
           /*
           * Fall through to....
           */
           case TCSANOW:
           return ioctl(   fd,   RTEMS_IO_SET_ATTRIBUTES,   tp  );
           }
          }
          #endif

libcsupport/src/tcsetpgrp.c

       1  /*
           * tcsetprgrp(   ) - POSIX 1003.1b 7.2.4 - Set Foreground Process Group ID
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tcsetpgrp.c,  v 1.7 2010/06/07 18:37:16 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #if defined(  RTEMS_NEWLIB )
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <errno.h>
          #include <termios.h>
          /* #include <sys/ioctl.h> */
          
          #include <rtems/libio.h>
          
      29  int tcsetpgrp(  
           int fd __attribute__(  (  unused ) ),  
           pid_t pid __attribute__(  (  unused ) )  )
          {
           return 0;
          }
          
          #endif

libcsupport/src/telldir.c

       1  /*
           * telldir(   ) - XXX
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_TELLDIR
          
          #include <sys/param.h>
          #include <dirent.h>
          #include <stdlib.h>
          #include <unistd.h>
          #include <errno.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      28  long telldir(  
           DIR *dirp
           )
          {
           rtems_libio_t *iop;
          
           if (   !dirp  )
           rtems_set_errno_and_return_minus_one(   EBADF  );
          
           /*
           * Get the file control block structure associated with the
           * file descriptor
           */
          
           iop = rtems_libio_iop(   dirp->dd_fd  );
           if (   !iop  )
           rtems_set_errno_and_return_minus_one(   EBADF  );
          
           return (  long )(   iop->offset  );
          }
          
          #endif

libcsupport/src/termios.c

       1  /*
           * TERMIOS serial line support
           *
           * Author:
           * W. Eric Norum
           * Saskatchewan Accelerator Laboratory
           * University of Saskatchewan
           * Saskatoon,   Saskatchewan,   CANADA
           * eric@skatter.usask.ca
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: termios.c,  v 1.64 2010/08/10 22:15:32 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <ctype.h>
          #include <errno.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <termios.h>
          #include <unistd.h>
          #include <sys/ttycom.h>
          
          #include <rtems/termiostypes.h>
          
          /*
           * The size of the cooked buffer
           */
          #define CBUFSIZE (  rtems_termios_cbufsize )
          
          /*
           * The sizes of the raw message buffers.
           * On most architectures it is quite a bit more
           * efficient if these are powers of two.
           */
          #define RAW_INPUT_BUFFER_SIZE (  rtems_termios_raw_input_size )
          #define RAW_OUTPUT_BUFFER_SIZE (  rtems_termios_raw_output_size )
          
          /* fields for "flow_ctrl" status */
          #define FL_IREQXOF 1 /* input queue requests stop of incoming data */
          #define FL_ISNTXOF 2 /* XOFF has been sent to other side of line */
          #define FL_IRTSOFF 4 /* RTS has been turned off for other side.. */
          
          #define FL_ORCVXOF 0x10 /* XOFF has been received */
          #define FL_OSTOP 0x20 /* output has been stopped due to XOFF */
          
          #define FL_MDRTS 0x100 /* input controlled with RTS/CTS handshake */
          #define FL_MDXON 0x200 /* input controlled with XON/XOFF protocol */
          #define FL_MDXOF 0x400 /* output controlled with XON/XOFF protocol */
          
          #define NODISC(  n ) \
           { NULL,   NULL,   NULL,   NULL,   \
           NULL,   NULL,   NULL,   NULL }
          /*
           * FIXME: change rtems_termios_linesw entries consistent
           * with rtems_termios_linesw entry usage...
           */
          struct rtems_termios_linesw rtems_termios_linesw[MAXLDISC] =
          {
           NODISC(  0 ),   /* 0- termios-built-in */
           NODISC(  1 ),   /* 1- defunct */
           NODISC(  2 ),   /* 2- NTTYDISC */
           NODISC(  3 ),   /* TABLDISC */
           NODISC(  4 ),   /* SLIPDISC */
           NODISC(  5 ),   /* PPPDISC */
           NODISC(  6 ),   /* loadable */
           NODISC(  7 ),   /* loadable */
          };
          
          int rtems_termios_nlinesw =
           sizeof (  rtems_termios_linesw ) / sizeof (  rtems_termios_linesw[0] );
          
          extern struct rtems_termios_tty *rtems_termios_ttyHead;
          extern struct rtems_termios_tty *rtems_termios_ttyTail;
          extern rtems_id rtems_termios_ttyMutex;
          
          static int rtems_termios_cbufsize = 256;
          static int rtems_termios_raw_input_size = 128;
      87  static int rtems_termios_raw_output_size = 64;
      88  
          static rtems_task rtems_termios_rxdaemon(  rtems_task_argument argument );
          static rtems_task rtems_termios_txdaemon(  rtems_task_argument argument );
          /*
           * some constants for I/O daemon task creation
           */
          #define TERMIOS_TXTASK_PRIO 10
          #define TERMIOS_RXTASK_PRIO 9
          #define TERMIOS_TXTASK_STACKSIZE 1024
          #define TERMIOS_RXTASK_STACKSIZE 1024
          /*
           * some events to be sent to the I/O tasks
           */
          #define TERMIOS_TX_START_EVENT RTEMS_EVENT_1
          #define TERMIOS_TX_TERMINATE_EVENT RTEMS_EVENT_0
          
          #define TERMIOS_RX_PROC_EVENT RTEMS_EVENT_1
          #define TERMIOS_RX_TERMINATE_EVENT RTEMS_EVENT_0
          
          /*
           * Open a termios device
     109   */
          rtems_status_code
          rtems_termios_open (  
           rtems_device_major_number major,  
           rtems_device_minor_number minor,  
           void *arg,  
           const rtems_termios_callbacks *callbacks
           )
          {
           rtems_status_code sc;
           rtems_libio_open_close_args_t *args = arg;
           struct rtems_termios_tty *tty;
          
           /*
           * See if the device has already been opened
           */
           sc = rtems_semaphore_obtain(  
           rtems_termios_ttyMutex,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           return sc;
          
           for (  tty = rtems_termios_ttyHead ; tty != NULL ; tty = tty->forw ) {
           if (  (  tty->major == major ) && (  tty->minor == minor ) )
           break;
           }
          
           if (  tty == NULL ) {
           static char c = 'a';
          
           /*
           * Create a new device
           */
           tty = calloc (  1,   sizeof (  struct rtems_termios_tty ) );
           if (  tty == NULL ) {
           rtems_semaphore_release (  rtems_termios_ttyMutex );
           return RTEMS_NO_MEMORY;
           }
           /*
           * allocate raw input buffer
           */
           tty->rawInBuf.Size = RAW_INPUT_BUFFER_SIZE;
           tty->rawInBuf.theBuf = malloc (  tty->rawInBuf.Size );
           if (  tty->rawInBuf.theBuf == NULL ) {
           free(  tty );
           rtems_semaphore_release (  rtems_termios_ttyMutex );
           return RTEMS_NO_MEMORY;
           }
           /*
           * allocate raw output buffer
           */
           tty->rawOutBuf.Size = RAW_OUTPUT_BUFFER_SIZE;
           tty->rawOutBuf.theBuf = malloc (  tty->rawOutBuf.Size );
           if (  tty->rawOutBuf.theBuf == NULL ) {
           free(  (  void * )(  tty->rawInBuf.theBuf ) );
           free(  tty );
           rtems_semaphore_release (  rtems_termios_ttyMutex );
           return RTEMS_NO_MEMORY;
           }
           /*
           * allocate cooked buffer
           */
           tty->cbuf = malloc (  CBUFSIZE );
           if (  tty->cbuf == NULL ) {
           free(  (  void * )(  tty->rawOutBuf.theBuf ) );
           free(  (  void * )(  tty->rawInBuf.theBuf ) );
           free(  tty );
           rtems_semaphore_release (  rtems_termios_ttyMutex );
           return RTEMS_NO_MEMORY;
           }
           /*
           * Initialize wakeup callbacks
           */
           tty->tty_snd.sw_pfn = NULL;
           tty->tty_snd.sw_arg = NULL;
           tty->tty_rcv.sw_pfn = NULL;
           tty->tty_rcv.sw_arg = NULL;
           tty->tty_rcvwakeup = 0;
          
           /*
           * link tty
           */
           tty->forw = rtems_termios_ttyHead;
           tty->back = NULL;
           if (  rtems_termios_ttyHead != NULL )
           rtems_termios_ttyHead->back = tty;
           rtems_termios_ttyHead = tty;
           if (  rtems_termios_ttyTail == NULL )
           rtems_termios_ttyTail = tty;
          
           tty->minor = minor;
           tty->major = major;
          
           /*
           * Set up mutex semaphores
           */
           sc = rtems_semaphore_create (  
           rtems_build_name (  'T',   'R',   'i',   c ),  
           1,  
           RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,  
           RTEMS_NO_PRIORITY,  
           &tty->isem );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           sc = rtems_semaphore_create (  
           rtems_build_name (  'T',   'R',   'o',   c ),  
           1,  
           RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,  
           RTEMS_NO_PRIORITY,  
           &tty->osem );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           sc = rtems_semaphore_create (  
           rtems_build_name (  'T',   'R',   'x',   c ),  
           0,  
           RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_FIFO,  
           RTEMS_NO_PRIORITY,  
           &tty->rawOutBuf.Semaphore );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           tty->rawOutBufState = rob_idle;
          
           /*
           * Set callbacks
           */
           tty->device = *callbacks;
          
           /*
           * Create I/O tasks
           */
           if (  tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN ) {
           sc = rtems_task_create (  
           rtems_build_name (  'T',   'x',   'T',   c ),  
           TERMIOS_TXTASK_PRIO,  
           TERMIOS_TXTASK_STACKSIZE,  
           RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE |
           RTEMS_NO_ASR,  
           RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,  
           &tty->txTaskId );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           sc = rtems_task_create (  
           rtems_build_name (  'R',   'x',   'T',   c ),  
           TERMIOS_RXTASK_PRIO,  
           TERMIOS_RXTASK_STACKSIZE,  
           RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE |
           RTEMS_NO_ASR,  
           RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,  
           &tty->rxTaskId );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
          
           }
           if (  (  tty->device.pollRead == NULL ) ||
           (  tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN ) ){
           sc = rtems_semaphore_create (  
           rtems_build_name (  'T',   'R',   'r',   c ),  
           0,  
           RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY,  
           RTEMS_NO_PRIORITY,  
           &tty->rawInBuf.Semaphore );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           }
          
           /*
           * Set default parameters
           */
           tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
           tty->termios.c_oflag = OPOST | ONLCR | XTABS;
           tty->termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
           tty->termios.c_lflag =
           ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL;
          
           tty->termios.c_cc[VINTR] = '\003';
           tty->termios.c_cc[VQUIT] = '\034';
           tty->termios.c_cc[VERASE] = '\177';
           tty->termios.c_cc[VKILL] = '\025';
           tty->termios.c_cc[VEOF] = '\004';
           tty->termios.c_cc[VEOL] = '\000';
           tty->termios.c_cc[VEOL2] = '\000';
           tty->termios.c_cc[VSTART] = '\021';
           tty->termios.c_cc[VSTOP] = '\023';
           tty->termios.c_cc[VSUSP] = '\032';
           tty->termios.c_cc[VREPRINT] = '\022';
           tty->termios.c_cc[VDISCARD] = '\017';
           tty->termios.c_cc[VWERASE] = '\027';
           tty->termios.c_cc[VLNEXT] = '\026';
          
           /* start with no flow control,   clear flow control flags */
           tty->flow_ctrl = 0;
           /*
           * set low/highwater mark for XON/XOFF support
           */
           tty->lowwater = tty->rawInBuf.Size * 1/2;
           tty->highwater = tty->rawInBuf.Size * 3/4;
           /*
           * Bump name characer
           */
           if (  c++ == 'z' )
           c = 'a';
          
           }
           args->iop->data1 = tty;
           if (  !tty->refcount++ ) {
           if (  tty->device.firstOpen )
           (  *tty->device.firstOpen )(  major,   minor,   arg );
          
           /*
           * start I/O tasks,   if needed
           */
           if (  tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN ) {
           sc = rtems_task_start(  
           tty->rxTaskId,   rtems_termios_rxdaemon,   (  rtems_task_argument )tty );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
          
           sc = rtems_task_start(  
           tty->txTaskId,   rtems_termios_txdaemon,   (  rtems_task_argument )tty );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           }
           }
           rtems_semaphore_release (  rtems_termios_ttyMutex );
           return RTEMS_SUCCESSFUL;
          }
          
          /*
           * Drain output queue
     337   */
          static void
          drainOutput (  struct rtems_termios_tty *tty )
          {
           rtems_interrupt_level level;
           rtems_status_code sc;
          
           if (  tty->device.outputUsesInterrupts != TERMIOS_POLLED ) {
           rtems_interrupt_disable (  level );
           while (  tty->rawOutBuf.Tail != tty->rawOutBuf.Head ) {
           tty->rawOutBufState = rob_wait;
           rtems_interrupt_enable (  level );
           sc = rtems_semaphore_obtain(  
           tty->rawOutBuf.Semaphore,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           rtems_interrupt_disable (  level );
           }
           rtems_interrupt_enable (  level );
           }
          }
     358  
          rtems_status_code
          rtems_termios_close (  void *arg )
          {
           rtems_libio_open_close_args_t *args = arg;
           struct rtems_termios_tty *tty = args->iop->data1;
           rtems_status_code sc;
          
           sc = rtems_semaphore_obtain(  
           rtems_termios_ttyMutex,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           if (  --tty->refcount == 0 ) {
           if (  rtems_termios_linesw[tty->t_line].l_close != NULL ) {
           /*
           * call discipline-specific close
           */
           sc = rtems_termios_linesw[tty->t_line].l_close(  tty );
           } else {
           /*
           * default: just flush output buffer
           */
           sc = rtems_semaphore_obtain(  tty->osem,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL ) {
           rtems_fatal_error_occurred (  sc );
           }
           drainOutput (  tty );
           rtems_semaphore_release (  tty->osem );
           }
          
           if (  tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN ) {
           /*
           * send "terminate" to I/O tasks
           */
           sc = rtems_event_send(   tty->rxTaskId,   TERMIOS_RX_TERMINATE_EVENT  );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           sc = rtems_event_send(   tty->txTaskId,   TERMIOS_TX_TERMINATE_EVENT  );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           }
           if (  tty->device.lastClose )
           (  *tty->device.lastClose )(  tty->major,   tty->minor,   arg );
           if (  tty->forw == NULL ) {
           rtems_termios_ttyTail = tty->back;
           if (   rtems_termios_ttyTail != NULL  ) {
           rtems_termios_ttyTail->forw = NULL;
           }
           } else {
           tty->forw->back = tty->back;
           }
          
           if (  tty->back == NULL ) {
           rtems_termios_ttyHead = tty->forw;
           if (   rtems_termios_ttyHead != NULL  ) {
           rtems_termios_ttyHead->back = NULL;
           }
           } else {
           tty->back->forw = tty->forw;
           }
          
           rtems_semaphore_delete (  tty->isem );
           rtems_semaphore_delete (  tty->osem );
           rtems_semaphore_delete (  tty->rawOutBuf.Semaphore );
           if (  (  tty->device.pollRead == NULL ) ||
           (  tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN ) )
           rtems_semaphore_delete (  tty->rawInBuf.Semaphore );
           free (  tty->rawInBuf.theBuf );
           free (  tty->rawOutBuf.theBuf );
           free (  tty->cbuf );
           free (  tty );
           }
           rtems_semaphore_release (  rtems_termios_ttyMutex );
           return RTEMS_SUCCESSFUL;
     432  }
          
          rtems_status_code rtems_termios_bufsize (  
           int cbufsize,  
           int raw_input,  
           int raw_output
           )
          {
           rtems_termios_cbufsize = cbufsize;
           rtems_termios_raw_input_size = raw_input;
           rtems_termios_raw_output_size = raw_output;
           return RTEMS_SUCCESSFUL;
          }
     445  
          static void
          termios_set_flowctrl(  struct rtems_termios_tty *tty )
          {
           rtems_interrupt_level level;
           /*
           * check for flow control options to be switched off
           */
          
           /* check for outgoing XON/XOFF flow control switched off */
           if (  (   tty->flow_ctrl & FL_MDXON ) &&
           !(  tty->termios.c_iflag & IXON ) ) {
           /* clear related flags in flow_ctrl */
           tty->flow_ctrl &= ~(  FL_MDXON | FL_ORCVXOF );
          
           /* has output been stopped due to received XOFF? */
           if (  tty->flow_ctrl & FL_OSTOP ) {
           /* disable interrupts */
           rtems_interrupt_disable(  level );
           tty->flow_ctrl &= ~FL_OSTOP;
           /* check for chars in output buffer (  or rob_state? ) */
           if (  tty->rawOutBufState != rob_idle ) {
           /* if chars available,   call write function... */
           (  *tty->device.write )(  
           tty->minor,   &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],  1 );
           }
           /* reenable interrupts */
           rtems_interrupt_enable(  level );
           }
           }
           /* check for incoming XON/XOFF flow control switched off */
           if (  (   tty->flow_ctrl & FL_MDXOF ) && !(  tty->termios.c_iflag & IXOFF ) ) {
           /* clear related flags in flow_ctrl */
           tty->flow_ctrl &= ~(  FL_MDXOF );
           /* FIXME: what happens,   if we had sent XOFF but not yet XON? */
           tty->flow_ctrl &= ~(  FL_ISNTXOF );
           }
          
           /* check for incoming RTS/CTS flow control switched off */
           if (  (   tty->flow_ctrl & FL_MDRTS ) && !(  tty->termios.c_cflag & CRTSCTS ) ) {
           /* clear related flags in flow_ctrl */
           tty->flow_ctrl &= ~(  FL_MDRTS );
          
           /* restart remote Tx,   if it was stopped */
           if (  (  tty->flow_ctrl & FL_IRTSOFF ) && (  tty->device.startRemoteTx != NULL ) ) {
           tty->device.startRemoteTx(  tty->minor );
           }
           tty->flow_ctrl &= ~(  FL_IRTSOFF );
           }
          
           /*
           * check for flow control options to be switched on
           */
           /* check for incoming RTS/CTS flow control switched on */
           if (  tty->termios.c_cflag & CRTSCTS ) {
           tty->flow_ctrl |= FL_MDRTS;
           }
           /* check for incoming XON/XOF flow control switched on */
           if (  tty->termios.c_iflag & IXOFF ) {
           tty->flow_ctrl |= FL_MDXOF;
           }
           /* check for outgoing XON/XOF flow control switched on */
           if (  tty->termios.c_iflag & IXON ) {
           tty->flow_ctrl |= FL_MDXON;
           }
          }
     511  
          rtems_status_code
          rtems_termios_ioctl (  void *arg )
          {
           rtems_libio_ioctl_args_t *args = arg;
           struct rtems_termios_tty *tty = args->iop->data1;
           struct ttywakeup *wakeup = (  struct ttywakeup * )args->buffer;
           rtems_status_code sc;
          
           args->ioctl_return = 0;
           sc = rtems_semaphore_obtain (  tty->osem,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL ) {
           args->ioctl_return = sc;
           return sc;
           }
           switch (  args->command ) {
           default:
           if (  rtems_termios_linesw[tty->t_line].l_ioctl != NULL ) {
           sc = rtems_termios_linesw[tty->t_line].l_ioctl(  tty,  args );
           }
           else {
           sc = RTEMS_INVALID_NUMBER;
           }
           break;
          
           case RTEMS_IO_GET_ATTRIBUTES:
           *(  struct termios * )args->buffer = tty->termios;
           break;
          
           case RTEMS_IO_SET_ATTRIBUTES:
           tty->termios = *(  struct termios * )args->buffer;
          
           /* check for and process change in flow control options */
           termios_set_flowctrl(  tty );
          
           if (  tty->termios.c_lflag & ICANON ) {
           tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
           tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
           tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
           } else {
           tty->vtimeTicks = tty->termios.c_cc[VTIME] *
           rtems_clock_get_ticks_per_second(   ) / 10;
           if (  tty->termios.c_cc[VTIME] ) {
           tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
           tty->rawInBufSemaphoreTimeout = tty->vtimeTicks;
           if (  tty->termios.c_cc[VMIN] )
           tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
           else
           tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks;
           } else {
           if (  tty->termios.c_cc[VMIN] ) {
           tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
           tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
           tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
           } else {
           tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT;
           }
           }
           }
           if (  tty->device.setAttributes )
           (  *tty->device.setAttributes )(  tty->minor,   &tty->termios );
           break;
          
           case RTEMS_IO_TCDRAIN:
           drainOutput (  tty );
           break;
          
           case RTEMS_IO_SNDWAKEUP:
           tty->tty_snd = *wakeup;
           break;
          
           case RTEMS_IO_RCVWAKEUP:
           tty->tty_rcv = *wakeup;
           break;
          
           /*
           * FIXME: add various ioctl code handlers
           */
          
          #if 1 /* FIXME */
           case TIOCSETD:
           /*
           * close old line discipline
           */
           if (  rtems_termios_linesw[tty->t_line].l_close != NULL ) {
           sc = rtems_termios_linesw[tty->t_line].l_close(  tty );
           }
           tty->t_line=*(  int* )(  args->buffer );
           tty->t_sc = NULL; /* ensure that no more valid data */
           /*
           * open new line discipline
           */
           if (  rtems_termios_linesw[tty->t_line].l_open != NULL ) {
           sc = rtems_termios_linesw[tty->t_line].l_open(  tty );
           }
           break;
           case TIOCGETD:
           *(  int* )(  args->buffer )=tty->t_line;
           break;
          #endif
           case FIONREAD: {
           int rawnc = tty->rawInBuf.Tail - tty->rawInBuf.Head;
           if (   rawnc < 0  )
           rawnc += tty->rawInBuf.Size;
           /* Half guess that this is the right operation */
           *(  int * )args->buffer = tty->ccount - tty->cindex + rawnc;
           }
           break;
           }
          
           rtems_semaphore_release (  tty->osem );
           args->ioctl_return = sc;
           return sc;
          }
          
          /*
           * Send characters to device-specific code
     628   */
          void
          rtems_termios_puts (  
           const void *_buf,   int len,   struct rtems_termios_tty *tty )
          {
           const unsigned char *buf = _buf;
           unsigned int newHead;
           rtems_interrupt_level level;
           rtems_status_code sc;
          
           if (  tty->device.outputUsesInterrupts == TERMIOS_POLLED ) {
           (  *tty->device.write )(  tty->minor,   (  void * )buf,   len );
           return;
           }
           newHead = tty->rawOutBuf.Head;
           while (  len ) {
           /*
           * Performance improvement could be made here.
           * Copy multiple bytes to raw buffer:
           * if (  len > 1 ) && (  space to buffer end,   or tail > 1 )
           * ncopy = MIN (  len,   space to buffer end or tail )
           * memcpy (  raw buffer,   buf,   ncopy )
           * buf += ncopy
           * len -= ncopy
           *
           * To minimize latency,   the memcpy should be done
           * with interrupts enabled.
           */
           newHead = (  newHead + 1 ) % tty->rawOutBuf.Size;
           rtems_interrupt_disable (  level );
           while (  newHead == tty->rawOutBuf.Tail ) {
           tty->rawOutBufState = rob_wait;
           rtems_interrupt_enable (  level );
           sc = rtems_semaphore_obtain(  
           tty->rawOutBuf.Semaphore,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           rtems_interrupt_disable (  level );
           }
           tty->rawOutBuf.theBuf[tty->rawOutBuf.Head] = *buf++;
           tty->rawOutBuf.Head = newHead;
           if (  tty->rawOutBufState == rob_idle ) {
           /* check,   whether XOFF has been received */
           if (  !(  tty->flow_ctrl & FL_ORCVXOF ) ) {
           (  *tty->device.write )(  tty->minor,  
           (  char * )&tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],  1 );
           } else {
           /* remember that output has been stopped due to flow ctrl*/
           tty->flow_ctrl |= FL_OSTOP;
           }
           tty->rawOutBufState = rob_busy;
           }
           rtems_interrupt_enable (  level );
           len--;
           }
          }
          
          /*
           * Handle output processing
     687   */
          static void
          oproc (  unsigned char c,   struct rtems_termios_tty *tty )
          {
           int i;
          
           if (  tty->termios.c_oflag & OPOST ) {
           switch (  c ) {
           case '\n':
           if (  tty->termios.c_oflag & ONLRET )
           tty->column = 0;
           if (  tty->termios.c_oflag & ONLCR ) {
           rtems_termios_puts (  "\r",   1,   tty );
           tty->column = 0;
           }
           break;
          
           case '\r':
           if (  (  tty->termios.c_oflag & ONOCR ) && (  tty->column == 0 ) )
           return;
           if (  tty->termios.c_oflag & OCRNL ) {
           c = '\n';
           if (  tty->termios.c_oflag & ONLRET )
           tty->column = 0;
           break;
           }
           tty->column = 0;
           break;
          
           case '\t':
           i = 8 - (  tty->column & 7 );
           if (  (  tty->termios.c_oflag & TABDLY ) == XTABS ) {
           tty->column += i;
           rtems_termios_puts (   " ",   i,   tty );
           return;
           }
           tty->column += i;
           break;
          
           case '\b':
           if (  tty->column > 0 )
           tty->column--;
           break;
          
           default:
           if (  tty->termios.c_oflag & OLCUC )
           c = toupper(  c );
           if (  !iscntrl(  c ) )
           tty->column++;
           break;
           }
           }
           rtems_termios_puts (  &c,   1,   tty );
          }
     741  
          rtems_status_code
          rtems_termios_write (  void *arg )
          {
           rtems_libio_rw_args_t *args = arg;
           struct rtems_termios_tty *tty = args->iop->data1;
           rtems_status_code sc;
          
           sc = rtems_semaphore_obtain (  tty->osem,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           return sc;
           if (  rtems_termios_linesw[tty->t_line].l_write != NULL ) {
           sc = rtems_termios_linesw[tty->t_line].l_write(  tty,  args );
           rtems_semaphore_release (  tty->osem );
           return sc;
           }
           if (  tty->termios.c_oflag & OPOST ) {
           uint32_t count = args->count;
           char *buffer = args->buffer;
           while (  count-- )
           oproc (  *buffer++,   tty );
           args->bytes_moved = args->count;
           } else {
           rtems_termios_puts (  args->buffer,   args->count,   tty );
           args->bytes_moved = args->count;
           }
           rtems_semaphore_release (  tty->osem );
           return sc;
          }
          
          /*
           * Echo a typed character
     773   */
          static void
          echo (  unsigned char c,   struct rtems_termios_tty *tty )
          {
           if (  (  tty->termios.c_lflag & ECHOCTL ) &&
           iscntrl(  c ) && (  c != '\t' ) && (  c != '\n' ) ) {
           char echobuf[2];
          
           echobuf[0] = '^';
           echobuf[1] = c ^ 0x40;
           rtems_termios_puts (  echobuf,   2,   tty );
           tty->column += 2;
           } else {
           oproc (  c,   tty );
           }
          }
          
          /*
           * Erase a character or line
           * FIXME: Needs support for WERASE and ECHOPRT.
           * FIXME: Some of the tests should check for IEXTEN,   too.
     794   */
          static void
          erase (  struct rtems_termios_tty *tty,   int lineFlag )
          {
           if (  tty->ccount == 0 )
           return;
           if (  lineFlag ) {
           if (  !(  tty->termios.c_lflag & ECHO ) ) {
           tty->ccount = 0;
           return;
           }
           if (  !(  tty->termios.c_lflag & ECHOE ) ) {
           tty->ccount = 0;
           echo (  tty->termios.c_cc[VKILL],   tty );
           if (  tty->termios.c_lflag & ECHOK )
           echo (  '\n',   tty );
           return;
           }
           }
          
           while (  tty->ccount ) {
           unsigned char c = tty->cbuf[--tty->ccount];
          
           if (  tty->termios.c_lflag & ECHO ) {
           if (  !lineFlag && !(  tty->termios.c_lflag & ECHOE ) ) {
           echo (  tty->termios.c_cc[VERASE],   tty );
           } else if (  c == '\t' ) {
           int col = tty->read_start_column;
           int i = 0;
          
           /*
           * Find the character before the tab
           */
           while (  i != tty->ccount ) {
           c = tty->cbuf[i++];
           if (  c == '\t' ) {
           col = (  col | 7 ) + 1;
           } else if (  iscntrl (  c ) ) {
           if (  tty->termios.c_lflag & ECHOCTL )
           col += 2;
           } else {
           col++;
           }
           }
          
           /*
           * Back up over the tab
           */
           while (  tty->column > col ) {
           rtems_termios_puts (  "\b",   1,   tty );
           tty->column--;
           }
           }
           else {
           if (  iscntrl (  c ) && (  tty->termios.c_lflag & ECHOCTL ) ) {
           rtems_termios_puts (  "\b \b",   3,   tty );
           if (  tty->column )
           tty->column--;
           }
           if (  !iscntrl (  c ) || (  tty->termios.c_lflag & ECHOCTL ) ) {
           rtems_termios_puts (  "\b \b",   3,   tty );
           if (  tty->column )
           tty->column--;
           }
           }
           }
           if (  !lineFlag )
           break;
           }
          }
          
          /*
           * Process a single input character
     867   */
          static int
          iproc (  unsigned char c,   struct rtems_termios_tty *tty )
          {
           if (  tty->termios.c_iflag & ISTRIP )
           c &= 0x7f;
          
           if (  tty->termios.c_iflag & IUCLC )
           c = tolower (  c );
          
           if (  c == '\r' ) {
           if (  tty->termios.c_iflag & IGNCR )
           return 0;
           if (  tty->termios.c_iflag & ICRNL )
           c = '\n';
           } else if (  (  c == '\n' ) && (  tty->termios.c_iflag & INLCR ) ) {
           c = '\r';
           }
          
           if (  (  c != '\0' ) && (  tty->termios.c_lflag & ICANON ) ) {
           if (  c == tty->termios.c_cc[VERASE] ) {
           erase (  tty,   0 );
           return 0;
           }
           else if (  c == tty->termios.c_cc[VKILL] ) {
           erase (  tty,   1 );
           return 0;
           }
           else if (  c == tty->termios.c_cc[VEOF] ) {
           return 1;
           } else if (  c == '\n' ) {
           if (  tty->termios.c_lflag & (  ECHO | ECHONL ) )
           echo (  c,   tty );
           tty->cbuf[tty->ccount++] = c;
           return 1;
           } else if (  (  c == tty->termios.c_cc[VEOL] ) ||
           (  c == tty->termios.c_cc[VEOL2] ) ) {
           if (  tty->termios.c_lflag & ECHO )
           echo (  c,   tty );
           tty->cbuf[tty->ccount++] = c;
           return 1;
           }
           }
          
           /*
           * FIXME: Should do IMAXBEL handling somehow
           */
           if (  tty->ccount < (  CBUFSIZE-1 ) ) {
           if (  tty->termios.c_lflag & ECHO )
           echo (  c,   tty );
           tty->cbuf[tty->ccount++] = c;
           }
           return 0;
          }
          
          /*
           * Process input character,   with semaphore.
     924   */
          static int
          siproc (  unsigned char c,   struct rtems_termios_tty *tty )
          {
           int i;
          
           /*
           * Obtain output semaphore if character will be echoed
           */
           if (  tty->termios.c_lflag & (  ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE ) ) {
           rtems_semaphore_obtain (  tty->osem,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           i = iproc (  c,   tty );
           rtems_semaphore_release (  tty->osem );
           }
           else {
           i = iproc (  c,   tty );
           }
           return i;
          }
          
          /*
           * Fill the input buffer by polling the device
     946   */
          static rtems_status_code
          fillBufferPoll (  struct rtems_termios_tty *tty )
          {
           int n;
          
           if (  tty->termios.c_lflag & ICANON ) {
           for (  ;; ) {
           n = (  *tty->device.pollRead )(  tty->minor );
           if (  n < 0 ) {
           rtems_task_wake_after (  1 );
           } else {
           if (  siproc (  n,   tty ) )
           break;
           }
           }
           } else {
           rtems_interval then,   now;
          
           then = rtems_clock_get_ticks_since_boot(   );
           for (  ;; ) {
           n = (  *tty->device.pollRead )(  tty->minor );
           if (  n < 0 ) {
           if (  tty->termios.c_cc[VMIN] ) {
           if (  tty->termios.c_cc[VTIME] && tty->ccount ) {
           now = rtems_clock_get_ticks_since_boot(   );
           if (  (  now - then ) > tty->vtimeTicks ) {
           break;
           }
           }
           } else {
           if (  !tty->termios.c_cc[VTIME] )
           break;
           now = rtems_clock_get_ticks_since_boot(   );
           if (  (  now - then ) > tty->vtimeTicks ) {
           break;
           }
           }
           rtems_task_wake_after (  1 );
           } else {
           siproc (  n,   tty );
           if (  tty->ccount >= tty->termios.c_cc[VMIN] )
           break;
           if (  tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME] )
           then = rtems_clock_get_ticks_since_boot(   );
           }
           }
           }
           return RTEMS_SUCCESSFUL;
          }
          
          /*
           * Fill the input buffer from the raw input queue
     999   */
          static rtems_status_code
          fillBufferQueue (  struct rtems_termios_tty *tty )
          {
           rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout;
           rtems_status_code sc;
           int wait = (  int )1;
          
           while (   wait  ) {
           /*
           * Process characters read from raw queue
           */
           while (  (  tty->rawInBuf.Head != tty->rawInBuf.Tail ) &&
           (  tty->ccount < (  CBUFSIZE-1 ) ) ) {
           unsigned char c;
           unsigned int newHead;
          
           newHead = (  tty->rawInBuf.Head + 1 ) % tty->rawInBuf.Size;
           c = tty->rawInBuf.theBuf[newHead];
           tty->rawInBuf.Head = newHead;
           if(  (  (  tty->rawInBuf.Tail-newHead+tty->rawInBuf.Size )
           % tty->rawInBuf.Size )
           < tty->lowwater ) {
           tty->flow_ctrl &= ~FL_IREQXOF;
           /* if tx stopped and XON should be sent... */
           if (  (  (  tty->flow_ctrl & (  FL_MDXON | FL_ISNTXOF ) )
           == (  FL_MDXON | FL_ISNTXOF ) )
           && (  (  tty->rawOutBufState == rob_idle )
           || (  tty->flow_ctrl & FL_OSTOP ) ) ) {
           /* XON should be sent now... */
           (  *tty->device.write )(  
           tty->minor,   (  void * )&(  tty->termios.c_cc[VSTART] ),   1 );
           } else if (  tty->flow_ctrl & FL_MDRTS ) {
           tty->flow_ctrl &= ~FL_IRTSOFF;
           /* activate RTS line */
           if (  tty->device.startRemoteTx != NULL ) {
           tty->device.startRemoteTx(  tty->minor );
           }
           }
           }
          
           /* continue processing new character */
           if (  tty->termios.c_lflag & ICANON ) {
           if (  siproc (  c,   tty ) )
           wait = 0;
           } else {
           siproc (  c,   tty );
           if (  tty->ccount >= tty->termios.c_cc[VMIN] )
           wait = 0;
           }
           timeout = tty->rawInBufSemaphoreTimeout;
           }
          
           /*
           * Wait for characters
           */
           if (   wait  ) {
           sc = rtems_semaphore_obtain(  
           tty->rawInBuf.Semaphore,   tty->rawInBufSemaphoreOptions,   timeout );
           if (  sc != RTEMS_SUCCESSFUL )
           break;
           }
           }
           return RTEMS_SUCCESSFUL;
          }
    1064  
          rtems_status_code
          rtems_termios_read (  void *arg )
          {
           rtems_libio_rw_args_t *args = arg;
           struct rtems_termios_tty *tty = args->iop->data1;
           uint32_t count = args->count;
           char *buffer = args->buffer;
           rtems_status_code sc;
          
           sc = rtems_semaphore_obtain (  tty->isem,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           return sc;
          
           if (  rtems_termios_linesw[tty->t_line].l_read != NULL ) {
           sc = rtems_termios_linesw[tty->t_line].l_read(  tty,  args );
           tty->tty_rcvwakeup = 0;
           rtems_semaphore_release (  tty->isem );
           return sc;
           }
          
           if (  tty->cindex == tty->ccount ) {
           tty->cindex = tty->ccount = 0;
           tty->read_start_column = tty->column;
           if (  tty->device.pollRead != NULL &&
           tty->device.outputUsesInterrupts == TERMIOS_POLLED )
           sc = fillBufferPoll (  tty );
           else
           sc = fillBufferQueue (  tty );
          
           if (  sc != RTEMS_SUCCESSFUL )
           tty->cindex = tty->ccount = 0;
           }
           while (  count && (  tty->cindex < tty->ccount ) ) {
           *buffer++ = tty->cbuf[tty->cindex++];
           count--;
           }
           args->bytes_moved = args->count - count;
           tty->tty_rcvwakeup = 0;
           rtems_semaphore_release (  tty->isem );
           return sc;
          }
          
          /*
           * signal receive interrupt to rx daemon
           * NOTE: This routine runs in the context of the
    1110   * device receive interrupt handler.
           */
          void rtems_termios_rxirq_occured(  struct rtems_termios_tty *tty )
          {
           /*
           * send event to rx daemon task
           */
           rtems_event_send(  tty->rxTaskId,  TERMIOS_RX_PROC_EVENT );
          }
          
          /*
           * Place characters on raw queue.
           * NOTE: This routine runs in the context of the
           * device receive interrupt handler.
           * Returns the number of characters dropped because of overflow.
    1125   */
          int
          rtems_termios_enqueue_raw_characters (  void *ttyp,   char *buf,   int len )
          {
           struct rtems_termios_tty *tty = ttyp;
           unsigned int newTail;
           char c;
           int dropped = 0;
           bool flow_rcv = false; /* true,   if flow control char received */
           rtems_interrupt_level level;
          
           if (  rtems_termios_linesw[tty->t_line].l_rint != NULL ) {
           while (  len-- ) {
           c = *buf++;
           rtems_termios_linesw[tty->t_line].l_rint(  c,  tty );
           }
          
           /*
           * check to see if rcv wakeup callback was set
           */
           if (  (   !tty->tty_rcvwakeup  ) && (   tty->tty_rcv.sw_pfn != NULL  ) ) {
           (  *tty->tty_rcv.sw_pfn )(  &tty->termios,   tty->tty_rcv.sw_arg );
           tty->tty_rcvwakeup = 1;
           }
           return 0;
           }
          
           while (  len-- ) {
           c = *buf++;
           /* FIXME: implement IXANY: any character restarts output */
           /* if incoming XON/XOFF controls outgoing stream: */
           if (  tty->flow_ctrl & FL_MDXON ) {
           /* if received char is V_STOP and V_START (  both are equal value ) */
           if (  c == tty->termios.c_cc[VSTOP] ) {
           if (  c == tty->termios.c_cc[VSTART] ) {
           /* received VSTOP and VSTART==VSTOP? */
           /* then toggle "stop output" status */
           tty->flow_ctrl = tty->flow_ctrl ^ FL_ORCVXOF;
           }
           else {
           /* VSTOP received (  other code than VSTART ) */
           /* stop output */
           tty->flow_ctrl |= FL_ORCVXOF;
           }
           flow_rcv = true;
           }
           else if (  c == tty->termios.c_cc[VSTART] ) {
           /* VSTART received */
           /* restart output */
           tty->flow_ctrl &= ~FL_ORCVXOF;
           flow_rcv = true;
           }
           }
           if (  flow_rcv ) {
           /* restart output according to FL_ORCVXOF flag */
           if (  (  tty->flow_ctrl & (  FL_ORCVXOF | FL_OSTOP ) ) == FL_OSTOP ) {
           /* disable interrupts */
           rtems_interrupt_disable(  level );
           tty->flow_ctrl &= ~FL_OSTOP;
           /* check for chars in output buffer (  or rob_state? ) */
           if (  tty->rawOutBufState != rob_idle ) {
           /* if chars available,   call write function... */
           (  *tty->device.write )(  
           tty->minor,   &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],   1 );
           }
           /* reenable interrupts */
           rtems_interrupt_enable(  level );
           }
           } else {
           newTail = (  tty->rawInBuf.Tail + 1 ) % tty->rawInBuf.Size;
           /* if chars_in_buffer > highwater */
           rtems_interrupt_disable(  level );
           if (  (  (  (  newTail - tty->rawInBuf.Head + tty->rawInBuf.Size )
           % tty->rawInBuf.Size ) > tty->highwater ) &&
           !(  tty->flow_ctrl & FL_IREQXOF ) ) {
           /* incoming data stream should be stopped */
           tty->flow_ctrl |= FL_IREQXOF;
           if (  (  tty->flow_ctrl & (  FL_MDXOF | FL_ISNTXOF ) )
           == (  FL_MDXOF  )  ) {
           if (  (  tty->flow_ctrl & FL_OSTOP ) ||
           (  tty->rawOutBufState == rob_idle ) ) {
           /* if tx is stopped due to XOFF or out of data */
           /* call write function here */
           tty->flow_ctrl |= FL_ISNTXOF;
           (  *tty->device.write )(  tty->minor,  
           (  void * )&(  tty->termios.c_cc[VSTOP] ),   1 );
           }
           } else if (  (  tty->flow_ctrl & (  FL_MDRTS | FL_IRTSOFF ) ) == (  FL_MDRTS )  ) {
           tty->flow_ctrl |= FL_IRTSOFF;
           /* deactivate RTS line */
           if (  tty->device.stopRemoteTx != NULL ) {
           tty->device.stopRemoteTx(  tty->minor );
           }
           }
           }
          
           /* reenable interrupts */
           rtems_interrupt_enable(  level );
          
           if (  newTail == tty->rawInBuf.Head ) {
           dropped++;
           } else {
           tty->rawInBuf.theBuf[newTail] = c;
           tty->rawInBuf.Tail = newTail;
          
           /*
           * check to see if rcv wakeup callback was set
           */
           if (  (   !tty->tty_rcvwakeup  ) && (   tty->tty_rcv.sw_pfn != NULL  ) ) {
           (  *tty->tty_rcv.sw_pfn )(  &tty->termios,   tty->tty_rcv.sw_arg );
           tty->tty_rcvwakeup = 1;
           }
           }
           }
           }
          
           tty->rawInBufDropped += dropped;
           rtems_semaphore_release (  tty->rawInBuf.Semaphore );
           return dropped;
          }
          
          /*
           * in task-driven mode,   this function is called in Tx task context
           * in interrupt-driven mode,   this function is called in TxIRQ context
    1249   */
          int
          rtems_termios_refill_transmitter (  struct rtems_termios_tty *tty )
          {
           unsigned int newTail;
           int nToSend;
           rtems_interrupt_level level;
           int len;
          
           /* check for XOF/XON to send */
           if (  (  tty->flow_ctrl & (  FL_MDXOF | FL_IREQXOF | FL_ISNTXOF ) )
           == (  FL_MDXOF | FL_IREQXOF ) ) {
           /* XOFF should be sent now... */
           (  *tty->device.write )(  tty->minor,   (  void * )&(  tty->termios.c_cc[VSTOP] ),   1 );
          
           rtems_interrupt_disable(  level );
           tty->t_dqlen--;
           tty->flow_ctrl |= FL_ISNTXOF;
           rtems_interrupt_enable(  level );
          
           nToSend = 1;
          
           } else if (  (  tty->flow_ctrl & (  FL_IREQXOF | FL_ISNTXOF ) ) == FL_ISNTXOF ) {
           /* NOTE: send XON even,   if no longer in XON/XOFF mode... */
           /* XON should be sent now... */
           /*
           * FIXME: this .write call will generate another
           * dequeue callback. This will advance the "Tail" in the data
           * buffer,   although the corresponding data is not yet out!
           * Therefore the dequeue "length" should be reduced by 1
           */
           (  *tty->device.write )(  tty->minor,   (  void * )&(  tty->termios.c_cc[VSTART] ),   1 );
          
           rtems_interrupt_disable(  level );
           tty->t_dqlen--;
           tty->flow_ctrl &= ~FL_ISNTXOF;
           rtems_interrupt_enable(  level );
          
           nToSend = 1;
           } else {
           if (   tty->rawOutBuf.Head == tty->rawOutBuf.Tail  ) {
           /*
           * buffer was empty
           */
           if (  tty->rawOutBufState == rob_wait ) {
           /*
           * this should never happen...
           */
           rtems_semaphore_release (  tty->rawOutBuf.Semaphore );
           }
           return 0;
           }
          
           rtems_interrupt_disable(  level );
           len = tty->t_dqlen;
           tty->t_dqlen = 0;
           rtems_interrupt_enable(  level );
          
           newTail = (  tty->rawOutBuf.Tail + len ) % tty->rawOutBuf.Size;
           tty->rawOutBuf.Tail = newTail;
           if (  tty->rawOutBufState == rob_wait ) {
           /*
           * wake up any pending writer task
           */
           rtems_semaphore_release (  tty->rawOutBuf.Semaphore );
           }
          
           if (  newTail == tty->rawOutBuf.Head ) {
           /*
           * Buffer has become empty
           */
           tty->rawOutBufState = rob_idle;
           nToSend = 0;
          
           /*
           * check to see if snd wakeup callback was set
           */
           if (   tty->tty_snd.sw_pfn != NULL ) {
           (  *tty->tty_snd.sw_pfn )(  &tty->termios,   tty->tty_snd.sw_arg );
           }
           }
           /* check,   whether output should stop due to received XOFF */
           else if (  (  tty->flow_ctrl & (  FL_MDXON | FL_ORCVXOF ) )
           == (  FL_MDXON | FL_ORCVXOF ) ) {
           /* Buffer not empty,   but output stops due to XOFF */
           /* set flag,   that output has been stopped */
           rtems_interrupt_disable(  level );
           tty->flow_ctrl |= FL_OSTOP;
           tty->rawOutBufState = rob_busy; /*apm*/
           rtems_interrupt_enable(  level );
           nToSend = 0;
           } else {
           /*
           * Buffer not empty,   start tranmitter
           */
           if (  newTail > tty->rawOutBuf.Head )
           nToSend = tty->rawOutBuf.Size - newTail;
           else
           nToSend = tty->rawOutBuf.Head - newTail;
           /* when flow control XON or XOF,   don't send blocks of data */
           /* to allow fast reaction on incoming flow ctrl and low latency*/
           /* for outgoing flow control */
           if (  tty->flow_ctrl & (  FL_MDXON | FL_MDXOF ) ) {
           nToSend = 1;
           }
           tty->rawOutBufState = rob_busy; /*apm*/
           (  *tty->device.write )(  
           tty->minor,   &tty->rawOutBuf.theBuf[newTail],   nToSend );
           }
           tty->rawOutBuf.Tail = newTail; /*apm*/
           }
           return nToSend;
          }
          
          /*
           * Characters have been transmitted
           * NOTE: This routine runs in the context of the
           * device transmit interrupt handler.
           * The second argument is the number of characters transmitted so far.
           * This value will always be 1 for devices which generate an interrupt
           * for each transmitted character.
           * It returns number of characters left to transmit
    1371   */
          int
          rtems_termios_dequeue_characters (  void *ttyp,   int len )
          {
           struct rtems_termios_tty *tty = ttyp;
           rtems_status_code sc;
          
           /*
           * sum up character count already sent
           */
           tty->t_dqlen += len;
          
           if (  tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN ) {
           /*
           * send wake up to transmitter task
           */
           sc = rtems_event_send(  tty->txTaskId,   TERMIOS_TX_START_EVENT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           return 0; /* nothing to output in IRQ... */
           }
          
           if (  tty->t_line == PPPDISC  ) {
           /*
           * call any line discipline start function
           */
           if (  rtems_termios_linesw[tty->t_line].l_start != NULL ) {
           rtems_termios_linesw[tty->t_line].l_start(  tty );
           }
           return 0; /* nothing to output in IRQ... */
           }
          
           return rtems_termios_refill_transmitter(  tty );
          }
          
          /*
    1407   * this task actually processes any transmit events
           */
          static rtems_task rtems_termios_txdaemon(  rtems_task_argument argument )
          {
           struct rtems_termios_tty *tty = (  struct rtems_termios_tty * )argument;
           rtems_event_set the_event;
          
           while (  1 ) {
           /*
           * wait for rtems event
           */
           rtems_event_receive(  
           (  TERMIOS_TX_START_EVENT | TERMIOS_TX_TERMINATE_EVENT ),  
           RTEMS_EVENT_ANY | RTEMS_WAIT,  
           RTEMS_NO_TIMEOUT,  
           &the_event
            );
           if (  (  the_event & TERMIOS_TX_TERMINATE_EVENT ) != 0 ) {
           tty->txTaskId = 0;
           rtems_task_delete(  RTEMS_SELF );
           }
          
           /*
           * call any line discipline start function
           */
           if (  rtems_termios_linesw[tty->t_line].l_start != NULL ) {
           rtems_termios_linesw[tty->t_line].l_start(  tty );
           }
          
           /*
           * try to push further characters to device
           */
           rtems_termios_refill_transmitter(  tty );
           }
          }
          
          /*
    1444   * this task actually processes any receive events
           */
          static rtems_task rtems_termios_rxdaemon(  rtems_task_argument argument )
          {
           struct rtems_termios_tty *tty = (  struct rtems_termios_tty * )argument;
           rtems_event_set the_event;
           int c;
           char c_buf;
          
           while (  1 ) {
           /*
           * wait for rtems event
           */
           rtems_event_receive(  
           (  TERMIOS_RX_PROC_EVENT | TERMIOS_RX_TERMINATE_EVENT ),  
           RTEMS_EVENT_ANY | RTEMS_WAIT,  
           RTEMS_NO_TIMEOUT,  
           &the_event
            );
           if (  (  the_event & TERMIOS_RX_TERMINATE_EVENT ) != 0 ) {
           tty->rxTaskId = 0;
           rtems_task_delete(  RTEMS_SELF );
           }
          
           /*
           * do something
           */
           c = tty->device.pollRead(  tty->minor );
           if (  c != EOF ) {
           /*
           * pollRead did call enqueue on its own
           */
           c_buf = c;
           rtems_termios_enqueue_raw_characters (   tty,  &c_buf,  1 );
           }
           }
          }

libcsupport/src/termios_baud2index.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: termios_baud2index.c,  v 1.3 2010/03/27 05:36:46 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/termios.h>
          #include <rtems/termiostypes.h>
          
      19  int rtems_termios_baud_to_index(  
           rtems_termios_baud_t termios_baud
           )
          {
           int baud_index;
          
           switch (  termios_baud ) {
           case B0: baud_index = 0; break;
           case B50: baud_index = 1; break;
           case B75: baud_index = 2; break;
           case B110: baud_index = 3; break;
           case B134: baud_index = 4; break;
           case B150: baud_index = 5; break;
           case B200: baud_index = 6; break;
           case B300: baud_index = 7; break;
           case B600: baud_index = 8; break;
           case B1200: baud_index = 9; break;
           case B1800: baud_index = 10; break;
           case B2400: baud_index = 11; break;
           case B4800: baud_index = 12; break;
           case B9600: baud_index = 13; break;
           case B19200: baud_index = 14; break;
           case B38400: baud_index = 15; break;
           case B57600: baud_index = 16; break;
           case B115200: baud_index = 17; break;
           case B230400: baud_index = 18; break;
           case B460800: baud_index = 19; break;
           default: baud_index = -1; break;
           }
          
           return baud_index;
          }

libcsupport/src/termios_baud2num.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: termios_baud2num.c,  v 1.5 2010/07/24 16:12:49 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/termios.h>
          #include <rtems/termiostypes.h>
          #include <rtems/assoc.h>
          
          extern rtems_assoc_t termios_assoc_table[];
          
      22  int32_t rtems_termios_baud_to_number(  
           int termios_baud
           )
          {
           int baud;
          
           baud = rtems_assoc_local_by_remote(   termios_assoc_table,   termios_baud  );
           if (   baud == 0 && termios_baud != 0  )
           return -1;
          
           return baud;
          }

libcsupport/src/termios_baudtable.c

       1  /*
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: termios_baudtable.c,  v 1.1 2010/07/24 16:12:49 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/termios.h>
          #include <rtems/termiostypes.h>
          #include <rtems/assoc.h>
          
          rtems_assoc_t termios_assoc_table[] = {
           { "B0",   0,   B0 },  
           { "B50",   50,   B50 },  
           { "B75",   75,   B75 },  
           { "B110",   110,   B110 },  
           { "B134",   134,   B134 },  
           { "B150",   150,   B150 },  
           { "B200",   200,   B200 },  
           { "B300",   300,   B300 },  
           { "B600",   600,   B600 },  
           { "B1200",   1200,   B1200 },  
           { "B1800",   1800,   B1800 },  
           { "B2400",   2400,   B2400 },  
           { "B4800",   4800,   B4800 },  
           { "B9600",   9600,   B9600 },  
           { "B19200",   19200,   B19200 },  
           { "B38400",   38400,   B38400 },  
           { "B57600",   57600,   B57600 },  
           { "B115200",   115200,   B115200 },  
           { "B230400",   230400,   B230400 },  
           { "B460800",   460800,   B460800 },  
           { NULL,   0,   0 }
          };

libcsupport/src/termios_num2baud.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: termios_num2baud.c,  v 1.4 2010/07/24 16:12:49 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/termios.h>
          #include <rtems/termiostypes.h>
          #include <rtems/assoc.h>
          
          extern rtems_assoc_t termios_assoc_table[];
          
      22  int rtems_termios_number_to_baud(  
           int32_t baud
           )
          {
           int termios_baud;
          
           termios_baud = rtems_assoc_remote_by_local(   termios_assoc_table,   baud  );
           if (   termios_baud == 0 && baud != 0  )
           return -1;
           return termios_baud;
          }

libcsupport/src/termios_setinitialbaud.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: termios_setinitialbaud.c,  v 1.4 2010/03/27 05:36:47 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/termios.h>
          #include <rtems/termiostypes.h>
          
      19  int rtems_termios_set_initial_baud(  
           struct rtems_termios_tty *ttyp,  
           int32_t baud
           )
          {
           int cflags_baud;
          
           cflags_baud = rtems_termios_number_to_baud(  baud );
           if (   cflags_baud == -1  )
           return -1;
          
           ttyp->termios.c_cflag = (  ttyp->termios.c_cflag & ~CBAUD ) | cflags_baud;
          
           return 0;
          }

libcsupport/src/termiosinitialize.c

       1  /*
           * Termios initialization routine
           *
           * Author:
           * W. Eric Norum
           * Saskatchewan Accelerator Laboratory
           * University of Saskatchewan
           * Saskatoon,   Saskatchewan,   CANADA
           * eric@skatter.usask.ca
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: termiosinitialize.c,  v 1.3 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <ctype.h>
          #include <errno.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <termios.h>
          #include <unistd.h>
          
          struct rtems_termios_tty *rtems_termios_ttyHead;
          struct rtems_termios_tty *rtems_termios_ttyTail;
          rtems_id rtems_termios_ttyMutex;
          
          void
      37  rtems_termios_initialize (  void )
          {
           rtems_status_code sc;
          
           /*
           * Create the mutex semaphore for the tty list
           */
           if (  !rtems_termios_ttyMutex ) {
           sc = rtems_semaphore_create (  
           rtems_build_name (  'T',   'R',   'm',   'i' ),  
           1,  
           RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,  
           RTEMS_NO_PRIORITY,  
           &rtems_termios_ttyMutex );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred (  sc );
           }
          }

libcsupport/src/truncate.c

       1  /*
           * truncate(   ) - Truncate a File to the Specified Length
           *
           * This routine is not defined in the POSIX 1003.1b standard but is
           * commonly supported on most UNIX and POSIX systems. It is provided
           * for compatibility.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: truncate.c,  v 1.5 2004/04/15 13:24:45 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          #include <errno.h>
          #include <fcntl.h>
          
      26  int truncate(  
           const char *path,  
           off_t length
           )
          {
           int status;
           int fd;
          
           fd = open(   path,   O_WRONLY  );
           if (   fd == -1  )
           return -1;
          
           status = ftruncate(   fd,   length  );
          
           (  void ) close(   fd  );
          
           return status;
          }

libcsupport/src/ttyname.c

       1  /*
           * Copyright (  c ) 1988,   1993
           * The Regents of the University of California. 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.
           * 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.
           */
          
          /*
           * $Id: ttyname.c,  v 1.12 2010/03/11 19:14:41 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_TTYNAME
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <dirent.h>
          #include <termios.h>
          #include <unistd.h>
          #include <string.h>
          #include <paths.h>
          #include <_syslist.h>
          #include <errno.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          static char ttyname_buf[sizeof (  _PATH_DEV ) + MAXNAMLEN];
          
          /*
           * ttyname_r(   ) - POSIX 1003.1b 4.7.2 - Demetermine Terminal Device Name
           */
      63  int ttyname_r(  
           int fd,  
           char *name,  
           size_t namesize
           )
          {
           struct stat sb;
           struct termios tty;
           struct dirent *dirp;
           DIR *dp;
           struct stat dsb;
           char *rval;
          
           /* Must be a terminal. */
           if (  tcgetattr (  fd,   &tty ) < 0 )
           rtems_set_errno_and_return_minus_one(  EBADF );
          
           /* Must be a character device. */
           if (  fstat (  fd,   &sb ) || !S_ISCHR (  sb.st_mode ) )
           rtems_set_errno_and_return_minus_one(  EBADF );
          
           if (  (  dp = opendir (  _PATH_DEV ) ) == NULL )
           rtems_set_errno_and_return_minus_one(  EBADF );
          
           /* Place the base directory in the path. */
           strncpy (  name,   _PATH_DEV,   namesize );
          
           for (  rval = NULL; (  dirp = readdir (  dp ) ) != NULL ; )
           {
           if (  dirp->d_ino != sb.st_ino )
           continue;
           strcpy (  name + sizeof (  _PATH_DEV ) - 1,   dirp->d_name );
           if (  stat (  name,   &dsb ) || sb.st_dev != dsb.st_dev ||
           sb.st_ino != dsb.st_ino )
           continue;
           rval = name;
           break;
           }
           (  void ) closedir (  dp );
           return 0;
          }
          
          /*
           * ttyname(   ) - POSIX 1003.1b 4.7.2 - Determine Terminal Device Name
           */
          
     109  char *ttyname(  
           int fd
           )
          {
           if (   !ttyname_r(   fd,   ttyname_buf,   sizeof(  ttyname_buf )  )  )
           return ttyname_buf;
           return NULL;
          }
          
          #endif

libcsupport/src/umask.c

       1  /*
           * umask(   ) - POSIX 1003.1b 5.3.3 - Set File Creation Mask
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: umask.c,  v 1.5 2003/09/04 18:54:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          
          #include <rtems/libio_.h>
          
      23  mode_t umask(  
           mode_t cmask
           )
          {
           mode_t old_mask;
          
           old_mask = rtems_filesystem_umask;
           rtems_filesystem_umask = cmask;
          
           return old_mask;
          }

libcsupport/src/unlink.c

       1  /*
           * unlink(   ) - POSIX 1003.1b - 5.5.1 - Remove an existing link
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: unlink.c,  v 1.21 2010/07/01 17:47:46 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      23  int unlink(  
           const char *path
           )
          {
           int parentpathlen;
           const char *name;
           rtems_filesystem_location_info_t parentloc;
           rtems_filesystem_location_info_t loc;
           int i;
           int result;
           bool free_parentloc = false;
          
           /*
           * Get the node to be unlinked. Find the parent path first.
           */
          
           parentpathlen = rtems_filesystem_dirname (   path  );
          
           if (   parentpathlen == 0  )
           rtems_filesystem_get_start_loc(   path,   &i,   &parentloc  );
           else {
           result = rtems_filesystem_evaluate_path(   path,   parentpathlen,  
           RTEMS_LIBIO_PERMS_WRITE,  
           &parentloc,  
           false  );
           if (   result != 0  )
           return -1;
          
           free_parentloc = true;
           }
          
           /*
           * Start from the parent to find the node that should be under it.
           */
          
           loc = parentloc;
           name = path + parentpathlen;
           name += rtems_filesystem_prefix_separators(   name,   strlen(   name  )  );
          
           result = rtems_filesystem_evaluate_relative_path(   name ,   strlen(   name  ),  
           0,   &loc,   false  );
           if (   result != 0  ) {
           if (   free_parentloc  )
           rtems_filesystem_freenode(   &parentloc  );
           return -1;
           }
          
           if (   (  *loc.ops->node_type_h )(   &loc  ) == RTEMS_FILESYSTEM_DIRECTORY  ) {
           rtems_filesystem_freenode(   &loc  );
           if (   free_parentloc  )
           rtems_filesystem_freenode(   &parentloc  );
           rtems_set_errno_and_return_minus_one(   EISDIR  );
           }
          
           result = (  *loc.ops->unlink_h )(   &parentloc,   &loc  );
          
           rtems_filesystem_freenode(   &loc  );
           if (   free_parentloc  )
           rtems_filesystem_freenode(   &parentloc  );
          
           return result;
          }
          
          /*
           * _unlink_r
           *
           * This is the Newlib dependent reentrant version of unlink(   ).
           */
          
          #if defined(  RTEMS_NEWLIB )
          
          #include <reent.h>
          
      96  int _unlink_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           const char *path
           )
          {
           return unlink(   path  );
          }
          #endif

libcsupport/src/unmount.c

       1  /*
           * unmount(   ) - Unmount a File System
           *
           * This routine is not defined in the POSIX 1003.1b standard but
           * in some form is supported on most UNIX and POSIX systems. This
           * routine is necessary to mount instantiations of a file system
           * into the file system name space.
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: unmount.c,  v 1.29 2010/07/04 14:53:45 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <string.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          #include <rtems/chain.h>
          
      35  static bool is_fs_below_mount_point(  
           const rtems_filesystem_mount_table_entry_t *mt_entry,  
           void *arg
           )
          {
           return arg == mt_entry->mt_point_node.mt_entry;
          }
          
          /*
           * unmount
           *
           * This routine will attempt to unmount the file system that has been
           * is mounted a path. If the operation is successful,   0 will
           * be returned to the calling routine. Otherwise,   1 will be returned.
           */
          
      51  int unmount(  
           const char *path
           )
          {
           rtems_filesystem_location_info_t loc;
           rtems_filesystem_location_info_t *fs_root_loc;
           rtems_filesystem_location_info_t *fs_mount_loc;
           rtems_filesystem_mount_table_entry_t *mt_entry;
          
           /*
           * Get
           * The root node of the mounted filesytem.
           * The node for the directory that the fileystem is mounted on.
           * The mount entry that is being refered to.
           */
          
           if (   rtems_filesystem_evaluate_path(   path,   strlen(   path  ),   0x0,   &loc,   true  )  )
           return -1;
          
           mt_entry = loc.mt_entry;
           fs_mount_loc = &mt_entry->mt_point_node;
           fs_root_loc = &mt_entry->mt_fs_root;
          
           /*
           * Verify this is the root node for the file system to be unmounted.
           */
          
           if (   fs_root_loc->node_access != loc.node_access  ){
           rtems_filesystem_freenode(   &loc  );
           rtems_set_errno_and_return_minus_one(   EACCES  );
           }
          
           /*
           * Free the loc node and just use the nodes from the mt_entry .
           */
          
           rtems_filesystem_freenode(   &loc  );
          
           /*
           * Verify the current node is not in this filesystem.
           * XXX - Joel I have a question here wasn't code added
           * that made the current node thread based instead
           * of system based? I thought it was but it doesn't
           * look like it in this version.
           */
          
           if (   rtems_filesystem_current.mt_entry == mt_entry  )
           rtems_set_errno_and_return_minus_one(   EBUSY  );
          
           /*
           * Verify there are no file systems below the path specified
           */
          
           if (   rtems_filesystem_mount_iterate(   is_fs_below_mount_point,  
           fs_root_loc->mt_entry  )  )
           rtems_set_errno_and_return_minus_one(   EBUSY  );
          
           /*
           * Run the file descriptor table to determine if there are any file
           * descriptors that are currently active and reference nodes in the
           * file system that we are trying to unmount
           */
          
           if (   rtems_libio_is_open_files_in_fs(   mt_entry  ) == 1  )
           rtems_set_errno_and_return_minus_one(   EBUSY  );
          
           /*
           * Allow the file system being unmounted on to do its cleanup.
           * If it fails it will set the errno to the approprate value
           * and the fileystem will not be modified.
           */
          
           if (  (   fs_mount_loc->ops->unmount_h  )(   mt_entry  ) != 0  )
           return -1;
          
           /*
           * Allow the mounted filesystem to unmark the use of the root node.
           *
           * Run the unmount function for the subordinate file system.
           *
           * If we fail to unmount the filesystem remount it on the base filesystems
           * directory node.
           *
           * NOTE: Fatal error is called in a case which should never happen
           * This was response was questionable but the best we could
           * come up with.
           */
          
           if (  (  fs_root_loc->ops->fsunmount_me_h  )(   mt_entry  ) != 0 ){
           if (  (   fs_mount_loc->ops->mount_h  )(   mt_entry  ) != 0  )
           rtems_fatal_error_occurred(   0  );
           return -1;
           }
          
           /*
           * Extract the mount table entry from the chain
           */
          
           rtems_libio_lock(   );
           rtems_chain_extract(   &mt_entry->Node  );
           rtems_libio_unlock(   );
          
           /*
           * Free the memory node that was allocated in mount
           * Free the memory associated with the extracted mount table entry.
           */
          
           rtems_filesystem_freenode(   fs_mount_loc  );
           free(   mt_entry  );
          
           return 0;
          }

libcsupport/src/utime.c

       1  /*
           * utime(   ) - POSIX 1003.1b 5.5.6 - Set File Access and Modification Times
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: utime.c,  v 1.15 2010/07/01 17:47:47 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <utime.h>
          #include <errno.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      25  int utime(  
           const char *path,  
           const struct utimbuf *times
           )
          {
           rtems_filesystem_location_info_t temp_loc;
           int result;
           struct utimbuf now;
          
           if (   rtems_filesystem_evaluate_path(   path,   strlen(   path  ),   0x00,   &temp_loc,   true  )  )
           return -1;
          
           if (   times == NULL  ) {
           now.actime = now.modtime = time(   NULL  );
           times = &now;
           }
          
           result = (  *temp_loc.ops->utime_h )(   &temp_loc,   times->actime,   times->modtime  );
          
           rtems_filesystem_freenode(   &temp_loc  );
          
           return result;
          }

libcsupport/src/utimes.c

       1  /*
           * Written by: Vinu Rajashekhar <vinutheraj@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: utimes.c,  v 1.1 2010/07/01 17:22:03 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <utime.h>
          #include <sys/time.h>
          
      19  int utimes(  
           const char *path,  
           const struct timeval times[2]
           )
          {
           struct utimbuf timeinsecs;
          
           if (   times == NULL  )
           return utime(   path,   NULL  );
          
           timeinsecs.actime = (  time_t ) times[0].tv_sec;
           timeinsecs.modtime = (  time_t ) times[1].tv_sec;
          
           return utime(   path,   &timeinsecs  );
          }

libcsupport/src/utsname.c

       1  /*
           * $Id: utsname.c,  v 1.18 2010/08/24 05:51:51 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <string.h>
          #include <sys/utsname.h>
          #include <inttypes.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 4.4.1 Get System Name,   P1003.1b-1993,   p. 90
           */
          
      23  int uname(  
           struct utsname *name
           )
          {
           /* XXX: Here is what Solaris returns...
           sysname = SunOS
           nodename = node_name
           release = 5.3
           version = Generic_101318-12
           machine = sun4m
           */
          
           if (   !name  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           strncpy(   name->sysname,   "RTEMS",   sizeof(  name->sysname )  );
          
           snprintf(   name->nodename,   sizeof(  name->nodename ),   "Node %" PRId16,   _Objects_Local_node  );
          
           strncpy(   name->release,   RTEMS_VERSION,   sizeof(  name->release )  );
          
           strncpy(   name->version,   "",   sizeof(  name->version )  );
          
           snprintf(   name->machine,   sizeof(  name->machine ),   "%s/%s",   CPU_NAME,   CPU_MODEL_NAME  );
          
           return 0;
          }

libcsupport/src/vprintk.c

       1  /*
           * (  C ) Copyright 1997 -
           * - NavIST Group - Real-Time Distributed Systems and Industrial Automation
           *
           * http://pandora.ist.utl.pt
           *
           * Instituto Superior Tecnico * Lisboa * PORTUGAL
           *
           * Disclaimer:
           *
           * This file is provided "AS IS" without warranty of any kind,   either
           * expressed or implied.
           *
           * This code is based on code by: Jose Rufino - IST
           *
           * $Id: vprintk.c,  v 1.4 2009/12/01 10:12:55 thomas Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          #include <stdio.h>
          #include <stdbool.h>
          #include <rtems/bspIo.h>
          
      28  static void printNum(  
           long num,  
           unsigned base,  
           bool sign,  
           unsigned maxwidth,  
           char lead
           );
          
          /*
           * vprintk
           *
           * A simplified version of printf intended for use when the
           * console is not yet initialized or in ISR's.
           *
           * Arguments:
           * as in printf: fmt - format string,   ... - unnamed arguments.
           */
      45  void vprintk(  
           const char *fmt,  
           va_list ap
           )
          {
           for (  ; *fmt != '\0'; fmt++ ) {
           unsigned base = 0;
           unsigned width = 0;
           bool lflag = false;
           bool minus = false;
           bool sign = false;
           char lead = ' ';
           char c;
          
           if (  *fmt != '%' ) {
           BSP_output_char(  *fmt );
           continue;
           }
           fmt++;
           if (  *fmt == '0'  ) {
           lead = '0';
           fmt++;
           }
           if (  *fmt == '-'  ) {
           minus = true;
           fmt++;
           }
           while (  *fmt >= '0' && *fmt <= '9'  ) {
           width *= 10;
           width += (  (  unsigned ) *fmt - '0' );
           fmt++;
           }
          
           if (  (  c = *fmt ) == 'l' ) {
           lflag = true;
           c = *++fmt;
           }
           if (   c == 'c'  ) {
           /* need a cast here since va_arg(   ) only takes fully promoted types */
           char chr = (  char ) va_arg(  ap,   int );
           BSP_output_char(  chr );
           continue;
           }
           if (   c == 's'  ) {
           unsigned i,   len;
           char *s,   *str;
          
           str = va_arg(  ap,   char * );
          
           if (   str == NULL  ) {
           str = "";
           }
          
           /* calculate length of string */
           for (   len=0,   s=str ; *s ; len++,   s++  )
           ;
          
           /* leading spaces */
           if (   !minus  )
           for (   i=len ; i<width ; i++  )
           BSP_output_char(  ' ' );
          
           /* no width option */
           if (  width == 0 ) {
           width = len;
           }
          
           /* output the string */
           for (   i=0 ; i<width && *str ; str++  )
           BSP_output_char(  *str );
          
           /* trailing spaces */
           if (   minus  )
           for (   i=len ; i<width ; i++  )
           BSP_output_char(  ' ' );
          
           continue;
           }
          
           /* must be a numeric format or something unsupported */
           if (   c == 'o' || c == 'O'  ) {
           base = 8; sign = false;
           } else if (   c == 'i' || c == 'I' ||
           c == 'd' || c == 'D'  ) {
           base = 10; sign = true;
           } else if (   c == 'u' || c == 'U'  ) {
           base = 10; sign = false;
           } else if (   c == 'x' || c == 'X'  ) {
           base = 16; sign = false;
           } else if (   c == 'p'  ) {
           base = 16; sign = false; lflag = true;
           } else {
           BSP_output_char(  c );
           continue;
           }
          
           printNum(  
           lflag ? va_arg(  ap,   long ) : (  long ) va_arg(  ap,   int ),  
           base,  
           sign,  
           width,  
           lead
            );
           }
          }
          
          /*
           * printNum - print number in a given base.
           * Arguments
           * num - number to print
           * base - base used to print the number.
           */
     157  static void printNum(  
           long num,  
           unsigned base,  
           bool sign,  
           unsigned maxwidth,  
           char lead
           )
          {
           unsigned long unsigned_num;
           unsigned long n;
           unsigned count;
           char toPrint[20];
          
           if (   sign && (  num < 0 )  ) {
           BSP_output_char(  '-' );
           unsigned_num = (  unsigned long ) -num;
           if (  maxwidth ) maxwidth--;
           } else {
           unsigned_num = (  unsigned long ) num;
           }
          
           count = 0;
           while (  (  n = unsigned_num / base ) > 0 ) {
           toPrint[count++] = (  char ) (  unsigned_num - (  n * base ) );
           unsigned_num = n;
           }
           toPrint[count++] = (  char ) unsigned_num;
          
           for (  n=maxwidth ; n > count; n--  )
           BSP_output_char(  lead );
          
           for (  n = 0; n < count; n++ ) {
           BSP_output_char(  "0123456789ABCDEF"[(  int )(  toPrint[count-(  n+1 )] )] );
           }
          }

libcsupport/src/write.c

       1  /*
           * write(   ) - POSIX 1003.1b 6.4.2 - Write to a File
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: write.c,  v 1.20 2010/08/23 23:19:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          /*
           * write
           *
           * This routine writes count bytes from from buffer pointed to by buffer
           * to the file associated with the open file descriptor,   fildes.
           */
          
      28  ssize_t write(  
           int fd,  
           const void *buffer,  
           size_t count
           )
          {
           ssize_t rc;
           rtems_libio_t *iop;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(   iop  );
           rtems_libio_check_buffer(   buffer  );
           rtems_libio_check_count(   count  );
           rtems_libio_check_permissions(   iop,   LIBIO_FLAGS_WRITE  );
          
           /*
           * Now process the write(   ) request.
           */
           rc = (  *iop->pathinfo.handlers->write_h )(   iop,   buffer,   count  );
          
           if (   rc > 0  )
           iop->offset += rc;
          
           return rc;
          }

libcsupport/src/write_r.c

       1  /*
           * write_r(   ) - POSIX 1003.1b 6.4.2 - Write to a File
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: write_r.c,  v 1.2 2009/09/15 09:42:46 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          /*
           * _write_r
           *
           * This is the Newlib dependent reentrant version of write(   ).
           */
          
          #if defined(  RTEMS_NEWLIB )
          
          #include <reent.h>
          
      31  _ssize_t _write_r(  
           struct _reent *ptr __attribute__(  (  unused ) ),  
           int fd,  
           const void *buf,  
           size_t nbytes
           )
          {
           return write(   fd,   buf,   nbytes  );
          }
          #endif

libcsupport/src/writev.c

       1  /*
           * writev(   ) - POSIX 1003.1 - Read a Vector
           *
           * OpenGroup URL:
           *
           * http://www.opengroup.org/onlinepubs/009695399/functions/writev.html
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: writev.c,  v 1.6 2010/08/25 22:25:18 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/uio.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      28  ssize_t writev(  
           int fd,  
           const struct iovec *iov,  
           int iovcnt
           )
          {
           ssize_t total;
           int v;
           int bytes;
           rtems_libio_t *iop;
           ssize_t old;
           bool all_zeros;
          
           rtems_libio_check_fd(   fd  );
           iop = rtems_libio_iop(   fd  );
           rtems_libio_check_is_open(   iop  );
           rtems_libio_check_permissions(   iop,   LIBIO_FLAGS_WRITE  );
          
           /*
           * Argument validation on IO vector
           */
           if (   !iov  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   iovcnt <= 0  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   iovcnt > IOV_MAX  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /*
           * OpenGroup says that you are supposed to return EINVAL if the
           * sum of the iov_len values in the iov array would overflow a
           * ssize_t.
           *
           * Also we would like to ensure that no IO is performed if there
           * are obvious errors in the iovec. So this extra loop ensures
           * that we do not do anything if there is an argument error.
           *
           * In addition,  the OpenGroup specification says that if all the
           * iov_len entries are zero,   then the call has no effect. So
           * this loop does that check as well and sets "all-zero" appropriately.
           * The variable "all_zero" is used as an early exit point before
           * entering the write loop.
           */
           all_zeros = true;
           for (   old=0,   total=0,   v=0 ; v < iovcnt ; v++  ) {
          
           /*
           * iov[v].iov_len cannot be less than 0 because size_t is unsigned.
           * So we only check for zero.
           */
           if (   iov[v].iov_base == 0  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   iov[v].iov_len  )
           all_zeros = false;
          
           /* check for wrap */
           old = total;
           total += iov[v].iov_len;
           if (   total < old || total > SSIZE_MAX  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           /*
           * A writev with all zeros is supposed to have no effect per OpenGroup.
           */
           if (   all_zeros == true  ) {
           return 0;
           }
          
           /*
           * Now process the writev(   ).
           */
           for (   total=0,   v=0 ; v < iovcnt ; v++  ) {
           /* all zero lengths has no effect */
           if (   iov[v].iov_len == 0  )
           continue;
          
           bytes = (  *iop->pathinfo.handlers->write_h )(  
           iop,  
           iov[v].iov_base,  
           iov[v].iov_len
            );
          
           if (   bytes < 0  )
           return -1;
          
           if (   bytes > 0  ) {
           iop->offset += bytes;
           total += bytes;
           }
          
           if (  bytes != iov[ v ].iov_len )
           break;
           }
          
           return total;
          }
          

libfs/src/defaults/default_chown.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_chown.c,  v 1.3 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_chown(  
           rtems_filesystem_location_info_t *pathloc,   /* IN */
           uid_t owner,   /* IN */
           gid_t group /* IN */
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_close.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_close.c,  v 1.2 2010/09/27 12:32:40 sh Exp $
           */
          
          #include <rtems/libio.h>
          
      14  int rtems_filesystem_default_close(  
           rtems_libio_t *iop
           )
          {
           return 0;
          }

libfs/src/defaults/default_evalformake.c

       1  /**
           * @file
           *
           * @ingroup LibIO
           *
           * @brief rtems_filesystem_default_evalformake(   ) implementation.
           */
          
          /*
           * Copyright (  c ) 2010
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * D-82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #include <rtems/libio.h>
          #include <rtems/seterr.h>
          
      25  int rtems_filesystem_default_evalformake(  
           const char *path,  
           rtems_filesystem_location_info_t *pathloc,  
           const char **name
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_evalpath.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_evalpath.c,  v 1.4 2010/08/27 06:42:45 sh Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_evalpath(  
           const char *pathname,   /* IN */
           size_t pathnamelen,   /* IN */
           int flags,   /* IN */
           rtems_filesystem_location_info_t *pathloc /* IN/OUT */
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }
          

libfs/src/defaults/default_evaluate_link.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_evaluate_link.c,  v 1.2 2010/08/27 06:42:46 sh Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_evaluate_link(  
           rtems_filesystem_location_info_t *pathloc,   /* IN/OUT */
           int flags /* IN */
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }
          

libfs/src/defaults/default_fchmod.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_fchmod.c,  v 1.2 2010/06/29 01:53:18 joel Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_fchmod(  
           rtems_filesystem_location_info_t *loc,  
           mode_t mode
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_fcntl.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_fcntl.c,  v 1.3 2010/08/25 09:37:48 sh Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_fcntl(  
           int cmd,  
           rtems_libio_t *iop
           )
          {
           return 0;
          }

libfs/src/defaults/default_fdatasync.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_fdatasync.c,  v 1.2 2010/06/29 01:53:18 joel Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_fdatasync(  
           rtems_libio_t *iop
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_fpathconf.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_fpathconf.c,  v 1.1 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_fpathconf(  
           rtems_libio_t *iop,  
           int name
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_freenode.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_freenode.c,  v 1.3 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_freenode(  
           rtems_filesystem_location_info_t *pathloc /* IN */
           )
          {
           return 0;
          }
          

libfs/src/defaults/default_fsmount.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_fsmount.c,  v 1.3 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_fsmount(  
           rtems_filesystem_mount_table_entry_t *mt_entry,   /* IN */
           const void *data /* IN */
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_fstat.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_fstat.c,  v 1.2 2010/06/29 01:53:18 joel Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_fstat(  
           rtems_filesystem_location_info_t *loc,  
           struct stat *buf
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_fsunmount.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_fsunmount.c,  v 1.1 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_fsunmount(  
           rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
           )
          {
           return 0;
          }

libfs/src/defaults/default_fsync.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_fsync.c,  v 1.2 2010/06/29 01:53:18 joel Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_fsync(  
           rtems_libio_t *iop
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_ftruncate.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_ftruncate.c,  v 1.2 2010/06/29 01:53:18 joel Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_ftruncate(  
           rtems_libio_t *iop,  
           rtems_off64_t length
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_handlers.c

       1  /**
           * @file
           *
           * @ingroup LibIO
           *
           * @brief rtems_filesystem_handlers_default definition.
           */
          
          /*
           * Copyright (  c ) 2010
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * D-82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #include <rtems/libio.h>
          
          const rtems_filesystem_file_handlers_r rtems_filesystem_handlers_default = {
           .open_h = rtems_filesystem_default_open,  
           .close_h = rtems_filesystem_default_close,  
           .read_h = rtems_filesystem_default_read,  
           .write_h = rtems_filesystem_default_write,  
           .ioctl_h = rtems_filesystem_default_ioctl,  
           .lseek_h = rtems_filesystem_default_lseek,  
           .fstat_h = rtems_filesystem_default_fstat,  
           .fchmod_h = rtems_filesystem_default_fchmod,  
           .ftruncate_h = rtems_filesystem_default_ftruncate,  
           .fpathconf_h = rtems_filesystem_default_fpathconf,  
           .fsync_h = rtems_filesystem_default_fsync,  
           .fdatasync_h = rtems_filesystem_default_fdatasync,  
           .fcntl_h = rtems_filesystem_default_fcntl,  
           .rmnod_h = rtems_filesystem_default_rmnod
          };

libfs/src/defaults/default_ioctl.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_ioctl.c,  v 1.2 2010/06/29 01:53:18 joel Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_ioctl(  
           rtems_libio_t *iop,  
           uint32_t command,  
           void *buffer
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_link.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_link.c,  v 1.3 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_link(  
           rtems_filesystem_location_info_t *to_loc,   /* IN */
           rtems_filesystem_location_info_t *parent_loc,   /* IN */
           const char *name /* IN */
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }
          

libfs/src/defaults/default_lseek.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_lseek.c,  v 1.2 2010/06/29 01:53:18 joel Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  rtems_off64_t rtems_filesystem_default_lseek(  
           rtems_libio_t *iop,  
           rtems_off64_t length,  
           int whence
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_mknod.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_mknod.c,  v 1.1 2010/06/30 13:58:56 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_mknod(  
           const char *path,   /* IN */
           mode_t mode,   /* IN */
           dev_t dev,   /* IN */
           rtems_filesystem_location_info_t *pathloc /* IN/OUT */
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_mount.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_mount.c,  v 1.3 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_mount (  
           rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
           )
          {
           return 0;
          }

libfs/src/defaults/default_node_type.c

       1  /**
           * @file
           *
           * @ingroup LibIO
           *
           * @brief rtems_filesystem_default_node_type(   ) implementation.
           */
          
          /*
           * Copyright (  c ) 2010
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * D-82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #include <rtems/libio.h>
          
      24  rtems_filesystem_node_types_t rtems_filesystem_default_node_type(  
           rtems_filesystem_location_info_t *pathloc
           )
          {
           return RTEMS_FILESYSTEM_INVALID_NODE_TYPE;
          }

libfs/src/defaults/default_open.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_open.c,  v 1.1 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_open(  
           rtems_libio_t *iop,  
           const char *pathname,  
           uint32_t flag,  
           uint32_t mode
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_ops.c

       1  /**
           * @file
           *
           * @ingroup LibIO
           *
           * @brief rtems_filesystem_operations_default definition.
           */
          
          /*
           * Copyright (  c ) 2010
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * D-82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #include <rtems/libio.h>
          
          const rtems_filesystem_operations_table rtems_filesystem_operations_default = {
           .evalpath_h = rtems_filesystem_default_evalpath,  
           .evalformake_h = rtems_filesystem_default_evalformake,  
           .link_h = rtems_filesystem_default_link,  
           .unlink_h = rtems_filesystem_default_unlink,  
           .node_type_h = rtems_filesystem_default_node_type,  
           .mknod_h = rtems_filesystem_default_mknod,  
           .chown_h = rtems_filesystem_default_chown,  
           .freenod_h = rtems_filesystem_default_freenode,  
           .mount_h = rtems_filesystem_default_mount,  
           .fsmount_me_h = rtems_filesystem_default_fsmount,  
           .unmount_h = rtems_filesystem_default_unmount,  
           .fsunmount_me_h = rtems_filesystem_default_fsunmount,  
           .utime_h = rtems_filesystem_default_utime,  
           .eval_link_h = rtems_filesystem_default_evaluate_link,  
           .symlink_h = rtems_filesystem_default_symlink,  
           .readlink_h = rtems_filesystem_default_readlink,  
           .rename_h = rtems_filesystem_default_rename,  
           .statvfs_h = rtems_filesystem_default_statvfs
          };

libfs/src/defaults/default_read.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_read.c,  v 1.3 2010/07/03 19:13:25 joel Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  ssize_t rtems_filesystem_default_read(  
           rtems_libio_t *iop,  
           void *buffer,  
           size_t count
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_readlink.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_readlink.c,  v 1.3 2010/07/03 19:13:25 joel Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  ssize_t rtems_filesystem_default_readlink(  
           rtems_filesystem_location_info_t *loc,   /* IN */
           char *buf,   /* OUT */
           size_t bufsize
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_rename.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_rename.c,  v 1.3 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_rename(  
           rtems_filesystem_location_info_t *old_parent_loc,   /* IN */
           rtems_filesystem_location_info_t *old_loc,   /* IN */
           rtems_filesystem_location_info_t *new_parent_loc,   /* IN */
           const char *name /* IN */
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_rmnod.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_rmnod.c,  v 1.2 2010/06/29 01:53:18 joel Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_rmnod(  
           rtems_filesystem_location_info_t *parent_loc,   /* IN */
           rtems_filesystem_location_info_t *pathloc /* IN */
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_statvfs.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_statvfs.c,  v 1.3 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_statvfs(  
           rtems_filesystem_location_info_t *loc,   /* IN */
           struct statvfs *buf /* OUT */
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_symlink.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_symlink.c,  v 1.3 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_symlink(  
           rtems_filesystem_location_info_t *loc,   /* IN */
           const char *link_name,   /* IN */
           const char *node_name
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_unlink.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_unlink.c,  v 1.3 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_unlink(  
           rtems_filesystem_location_info_t *parent_pathloc,   /* IN */
           rtems_filesystem_location_info_t *pathloc /* IN */
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/defaults/default_unmount.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_unmount.c,  v 1.1 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_unmount(  
           rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
           )
          {
           return 0;
          }

libfs/src/defaults/default_utime.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_utime.c,  v 1.3 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  int rtems_filesystem_default_utime(  
           rtems_filesystem_location_info_t *pathloc,   /* IN */
           time_t actime,   /* IN */
           time_t modtime /* IN */
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }
          

libfs/src/defaults/default_write.c

       1  /*
           * COPYRIGHT (  c ) 2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: default_write.c,  v 1.2 2010/06/29 01:53:18 joel Exp $
           */
          
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      16  ssize_t rtems_filesystem_default_write(  
           rtems_libio_t *iop,  
           const void *buffer,  
           size_t count
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
          }

libfs/src/devfs/devclose.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: devclose.c,  v 1.5 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/io.h>
          
          #include "devfs.h"
          
      18  int devFS_close(  
           rtems_libio_t *iop
           )
          {
           rtems_libio_open_close_args_t args;
           rtems_status_code status;
           rtems_device_name_t *np;
          
           np = (  rtems_device_name_t * )iop->pathinfo.node_access;
          
           args.iop = iop;
           args.flags = 0;
           args.mode = 0;
          
           status = rtems_io_close(  
           np->major,  
           np->minor,  
           (  void * ) &args
            );
          
           return rtems_deviceio_errno(  status );
          }
          
          

libfs/src/devfs/devfs_eval.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: devfs_eval.c,  v 1.7 2010/08/27 17:32:59 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/seterr.h>
          #include <fcntl.h>
          #include <assert.h>
          #include "devfs.h"
          
          /**
           * The following defines the device-only filesystem operating
           * handlers.
           */
          
          extern rtems_filesystem_operations_table devFS_ops;
          
          /**
           * The following defines the device-only filesystem operating
           * handlers.
           */
          
          extern rtems_filesystem_file_handlers_r devFS_file_handlers;
          
      32  int devFS_evaluate_path(  
           const char *pathname,  
           size_t pathnamelen,  
           int flags,  
           rtems_filesystem_location_info_t *pathloc
           )
          {
           int i;
           rtems_device_name_t *device_name_table;
          
           /* see if 'flags' is valid */
           if (   !rtems_libio_is_valid_perms(   flags  )  )
           rtems_set_errno_and_return_minus_one(   EPERM  );
          
           /* get the device name table */
           device_name_table = (  rtems_device_name_t * )pathloc->node_access;
           if (  !device_name_table )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           for (  i = 0; i < rtems_device_table_size; i++ ) {
           if (  !device_name_table[i].device_name )
           continue;
          
           if (  strncmp(  pathname,   device_name_table[i].device_name,   pathnamelen ) != 0 )
           continue;
          
           if (  device_name_table[i].device_name[pathnamelen] != '\0' )
           continue;
          
           /* find the device,   set proper values */
           pathloc->node_access = (  void * )&device_name_table[i];
           pathloc->handlers = &devFS_file_handlers;
           pathloc->ops = &devFS_ops;
           pathloc->mt_entry = rtems_filesystem_root.mt_entry;
           return 0;
           }
          
           /* no such file or directory */
           rtems_set_errno_and_return_minus_one(   ENOENT  );
          }
          
          
          
      75  int devFS_evaluate_for_make(  
           const char *path,  
           rtems_filesystem_location_info_t *pathloc,  
           const char **name
           )
          {
           /* we do nothing,   just set name to path */
           *name = path;
           return 0;
          }
          

libfs/src/devfs/devfs_init.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: devfs_init.c,  v 1.6 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          #include <rtems.h>
          #include <rtems/seterr.h>
          #include <rtems/score/wkspace.h>
          #include "devfs.h"
          
          rtems_filesystem_operations_table devFS_ops =
          {
           devFS_evaluate_path,  
           devFS_evaluate_for_make,  
           rtems_filesystem_default_link,  
           rtems_filesystem_default_unlink,  
           devFS_node_type,  
           devFS_mknod,  
           rtems_filesystem_default_chown,  
           rtems_filesystem_default_freenode,  
           rtems_filesystem_default_mount,  
           devFS_initialize,  
           rtems_filesystem_default_unmount,  
           rtems_filesystem_default_fsunmount,  
           rtems_filesystem_default_utime,  
           rtems_filesystem_default_evaluate_link,  
           rtems_filesystem_default_symlink,  
           rtems_filesystem_default_readlink,  
           rtems_filesystem_default_rename,  
           rtems_filesystem_default_statvfs
          };
          
          
          rtems_filesystem_file_handlers_r devFS_file_handlers =
          {
           devFS_open,  
           devFS_close,  
           devFS_read,  
           devFS_write,  
           devFS_ioctl,  
           rtems_filesystem_default_lseek,  
           devFS_stat,  
           rtems_filesystem_default_fchmod,  
           rtems_filesystem_default_ftruncate,  
           rtems_filesystem_default_fpathconf,  
           rtems_filesystem_default_fsync,  
           rtems_filesystem_default_fdatasync,  
           rtems_filesystem_default_fcntl,  
           rtems_filesystem_default_rmnod
          };
          
          
          
      62  int devFS_initialize(  
           rtems_filesystem_mount_table_entry_t *temp_mt_entry,  
           const void *data
           )
          {
           rtems_device_name_t *device_name_table;
          
           /* allocate device only filesystem name table */
           device_name_table = (  rtems_device_name_t * )_Workspace_Allocate(  
           sizeof(   rtems_device_name_t  ) * (   rtems_device_table_size  )
            );
          
           /* no memory for device filesystem */
           if (  !device_name_table )
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
          
           memset(  
           device_name_table,   0,  
           sizeof(   rtems_device_name_t  ) * (   rtems_device_table_size  )
            );
          
           /* set file handlers */
           temp_mt_entry->mt_fs_root.handlers = &devFS_file_handlers;
           temp_mt_entry->mt_fs_root.ops = &devFS_ops;
          
           /* Set the node_access to device name table */
           temp_mt_entry->mt_fs_root.node_access = (  void * )device_name_table;
          
           return 0;
          }
          

libfs/src/devfs/devfs_mknod.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: devfs_mknod.c,  v 1.2 2009/11/29 13:18:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          
          #include <rtems/seterr.h>
          #include "devfs.h"
          
      23  int devFS_mknod(  
           const char *path,  
           mode_t mode,  
           dev_t dev,  
           rtems_filesystem_location_info_t *pathloc
           )
          {
           int i;
           int slot;
           rtems_device_name_t *device_name_table;
           rtems_device_major_number major;
           rtems_device_minor_number minor;
           ISR_Level level;
          
           /*
           * This is a special case. In rtems_filesystem_initialize,  
           * a special device '/dev' will be created. We check this
           * condition and do not create the '/dev' and the 'path'
           * actually passed in is 'dev',   not '/dev'. Just return 0 to
           * indicate we are OK.
           */
          
           if (  (  path[0] == 'd' ) && (  path[1] == 'e' ) &&
           (  path[2] == 'v' ) && (  path[3] == '\0' ) )
           return 0;
          
           /* must be a character device or a block device */
           if (  !S_ISBLK(  mode ) && !S_ISCHR(  mode ) )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           else
           rtems_filesystem_split_dev_t(  dev,   major,   minor );
          
           /* Find an empty slot in device name table */
           device_name_table = (  rtems_device_name_t * )pathloc->node_access;
           if (  !device_name_table )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           for (  slot = -1,   i = 0; i < rtems_device_table_size; i++ ){
           if (  device_name_table[i].device_name == NULL )
           slot = i;
           else
           if (  strcmp(  path,   device_name_table[i].device_name ) == 0 )
           rtems_set_errno_and_return_minus_one(   EEXIST  );
           }
          
           if (  slot == -1 )
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
          
           _ISR_Disable(  level );
           device_name_table[slot].device_name = (  char * )path;
           device_name_table[slot].device_name_length = strlen(  path );
           device_name_table[slot].major = major;
           device_name_table[slot].minor = minor;
           device_name_table[slot].mode = mode;
           _ISR_Enable(  level );
          
           return 0;
          }
          

libfs/src/devfs/devfs_node_type.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: devfs_node_type.c,  v 1.3 2010/07/15 07:59:57 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include "devfs.h"
          
      15  rtems_filesystem_node_types_t devFS_node_type(  
           rtems_filesystem_location_info_t *pathloc
           )
          {
           /*
           * There is only one type of node: device
           */
          
           return RTEMS_FILESYSTEM_DEVICE;
          }
          
          

libfs/src/devfs/devfs_show.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: devfs_show.c,  v 1.3 2009/11/29 13:18:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/seterr.h>
          #include "devfs.h"
          
      16  int devFS_Show(  void )
          {
           int i;
           rtems_filesystem_location_info_t *temp_loc;
           rtems_device_name_t *device_name_table;
          
           temp_loc = &rtems_filesystem_root;
           device_name_table = (  rtems_device_name_t * )temp_loc->node_access;
           if (  !device_name_table )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           for (  i = 0; i < rtems_device_table_size; i++ ){
           if (  device_name_table[i].device_name ){
           printk(  "/%s %d %d\n",   device_name_table[i].device_name,  
           device_name_table[i].major,   device_name_table[i].minor );
           }
           }
           return 0;
          }
          
          

libfs/src/devfs/devioctl.c

       1  #if HAVE_CONFIG_H
          /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: devioctl.c,  v 1.4 2010/07/15 08:10:47 sh Exp $
           */
          
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/io.h>
          
          #include "devfs.h"
          
      18  int devFS_ioctl(  
           rtems_libio_t *iop,  
           uint32_t command,  
           void *buffer
           )
          {
           rtems_libio_ioctl_args_t args;
           rtems_status_code status;
           rtems_device_name_t *np;
          
           np = (  rtems_device_name_t * )iop->pathinfo.node_access;
          
           args.iop = iop;
           args.command = command;
           args.buffer = buffer;
          
           status = rtems_io_control(  
           np->major,  
           np->minor,  
           (  void * ) &args
            );
          
           if (   status  )
           return rtems_deviceio_errno(  status );
          
           return args.ioctl_return;
          }
          

libfs/src/devfs/devopen.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: devopen.c,  v 1.5 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/io.h>
          
          #include "devfs.h"
          
      18  int devFS_open(  
           rtems_libio_t *iop,  
           const char *pathname,  
           uint32_t flag,  
           uint32_t mode
           )
          {
           rtems_libio_open_close_args_t args;
           rtems_status_code status;
           rtems_device_name_t *np;
          
           np = (  rtems_device_name_t * )iop->pathinfo.node_access;
          
           args.iop = iop;
           args.flags = iop->flags;
           args.mode = mode;
          
           status = rtems_io_open(  
           np->major,  
           np->minor,  
           (  void * ) &args
            );
          
           return rtems_deviceio_errno(  status );
          }

libfs/src/devfs/devread.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: devread.c,  v 1.4 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/io.h>
          
          #include "devfs.h"
          
      18  ssize_t devFS_read(  
           rtems_libio_t *iop,  
           void *buffer,  
           size_t count
           )
          {
           rtems_libio_rw_args_t args;
           rtems_status_code status;
           rtems_device_name_t *np;
          
           np = (  rtems_device_name_t * )iop->pathinfo.node_access;
          
           args.iop = iop;
           args.offset = iop->offset;
           args.buffer = buffer;
           args.count = count;
           args.flags = iop->flags;
           args.bytes_moved = 0;
          
           status = rtems_io_read(  
           np->major,  
           np->minor,  
           (  void * ) &args
            );
          
           if (   status  )
           return rtems_deviceio_errno(  status );
          
           return (  ssize_t ) args.bytes_moved;
          }
          

libfs/src/devfs/devstat.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: devstat.c,  v 1.3 2010/07/23 00:11:32 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/io.h>
          #include <rtems/seterr.h>
          #include <rtems/libio.h>
          #include <sys/stat.h>
          #include <sys/types.h>
          
          #include "devfs.h"
          
      22  int devFS_stat(  
           rtems_filesystem_location_info_t *loc,  
           struct stat *buf
           )
          {
           rtems_device_name_t *the_dev;
          
           the_dev = (  rtems_device_name_t * )loc->node_access;
          
           /*
           * stat(   ) invokes devFS_evaluate_path(   ) which checks that node_access
           * is not NULL. So this should NEVER be NULL unless someone breaks
           * other code in this filesystem.
           */
           #if defined(  RTEMS_DEBUG )
           if (  !the_dev )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
           #endif
          
           buf->st_rdev = rtems_filesystem_make_dev_t(   the_dev->major,   the_dev->minor  );
           buf->st_mode = the_dev->mode;
           return 0;
          }
          
          

libfs/src/devfs/devwrite.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: devwrite.c,  v 1.4 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/io.h>
          
          #include "devfs.h"
          
      18  ssize_t devFS_write(  
           rtems_libio_t *iop,  
           const void *buffer,  
           size_t count
           )
          {
           rtems_libio_rw_args_t args;
           rtems_status_code status;
           rtems_device_name_t *np;
          
           np = (  rtems_device_name_t * )iop->pathinfo.node_access;
          
           args.iop = iop;
           args.offset = iop->offset;
           args.buffer = (  void * ) buffer;
           args.count = count;
           args.flags = iop->flags;
           args.bytes_moved = 0;
          
           status = rtems_io_write(  
           np->major,  
           np->minor,  
           (  void * ) &args
            );
          
           if (   status  )
           return rtems_deviceio_errno(  status );
          
           return (  ssize_t ) args.bytes_moved;
          }
          

libfs/src/dosfs/fat.c

       1  /*
           * fat.c
           *
           * Low-level operations on a volume with FAT filesystem
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * @(  # ) $Id: fat.c,  v 1.20 2010/07/04 14:53:45 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          
          #include <rtems/libio_.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          
          int
      29  fat_buf_access(  fat_fs_info_t *fs_info,   uint32_t blk,   int op_type,  
           rtems_bdbuf_buffer **buf )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           uint8_t i;
           bool sec_of_fat;
          
          
           if (  fs_info->c.state == FAT_CACHE_EMPTY )
           {
           if (  op_type == FAT_OP_TYPE_READ )
           sc = rtems_bdbuf_read(  fs_info->vol.dev,   blk,   &fs_info->c.buf );
           else
           sc = rtems_bdbuf_get(  fs_info->vol.dev,   blk,   &fs_info->c.buf );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
           fs_info->c.blk_num = blk;
           fs_info->c.modified = 0;
           fs_info->c.state = FAT_CACHE_ACTUAL;
           }
          
           sec_of_fat = (  (  fs_info->c.blk_num >= fs_info->vol.fat_loc ) &&
           (  fs_info->c.blk_num < fs_info->vol.rdir_loc ) );
          
           if (  fs_info->c.blk_num != blk )
           {
           if (  fs_info->c.modified )
           {
           if (  sec_of_fat && !fs_info->vol.mirror )
           memcpy(  fs_info->sec_buf,   fs_info->c.buf->buffer,  
           fs_info->vol.bps );
          
           sc = rtems_bdbuf_release_modified(  fs_info->c.buf );
           fs_info->c.state = FAT_CACHE_EMPTY;
           fs_info->c.modified = 0;
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           if (  sec_of_fat && !fs_info->vol.mirror )
           {
           rtems_bdbuf_buffer *b;
          
           for (  i = 1; i < fs_info->vol.fats; i++ )
           {
           sc = rtems_bdbuf_get(  fs_info->vol.dev,  
           fs_info->c.blk_num +
           fs_info->vol.fat_length * i,  
           &b );
           if (   sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  ENOMEM );
           memcpy(  b->buffer,   fs_info->sec_buf,   fs_info->vol.bps );
           sc = rtems_bdbuf_release_modified(  b );
           if (   sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  ENOMEM );
           }
           }
           }
           else
           {
           sc = rtems_bdbuf_release(  fs_info->c.buf );
           fs_info->c.state = FAT_CACHE_EMPTY;
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           }
           if (  op_type == FAT_OP_TYPE_READ )
           sc = rtems_bdbuf_read(  fs_info->vol.dev,   blk,   &fs_info->c.buf );
           else
           sc = rtems_bdbuf_get(  fs_info->vol.dev,   blk,   &fs_info->c.buf );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
           fs_info->c.blk_num = blk;
           fs_info->c.state = FAT_CACHE_ACTUAL;
           }
           *buf = fs_info->c.buf;
           return RC_OK;
          }
          
          int
     108  fat_buf_release(  fat_fs_info_t *fs_info )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           uint8_t i;
           bool sec_of_fat;
          
           if (  fs_info->c.state == FAT_CACHE_EMPTY )
           return RC_OK;
          
           sec_of_fat = (  (  fs_info->c.blk_num >= fs_info->vol.fat_loc ) &&
           (  fs_info->c.blk_num < fs_info->vol.rdir_loc ) );
          
           if (  fs_info->c.modified )
           {
           if (  sec_of_fat && !fs_info->vol.mirror )
           memcpy(  fs_info->sec_buf,   fs_info->c.buf->buffer,   fs_info->vol.bps );
          
           sc = rtems_bdbuf_release_modified(  fs_info->c.buf );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
           fs_info->c.modified = 0;
          
           if (  sec_of_fat && !fs_info->vol.mirror )
           {
           rtems_bdbuf_buffer *b;
          
           for (  i = 1; i < fs_info->vol.fats; i++ )
           {
           sc = rtems_bdbuf_get(  fs_info->vol.dev,  
           fs_info->c.blk_num +
           fs_info->vol.fat_length * i,  
           &b );
           if (   sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  ENOMEM );
           memcpy(  b->buffer,   fs_info->sec_buf,   fs_info->vol.bps );
           sc = rtems_bdbuf_release_modified(  b );
           if (   sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  ENOMEM );
           }
           }
           }
           else
           {
           sc = rtems_bdbuf_release(  fs_info->c.buf );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
           }
           fs_info->c.state = FAT_CACHE_EMPTY;
           return RC_OK;
          }
          
          /* _fat_block_read --
           * This function reads 'count' bytes from device filesystem is mounted on,  
           * starts at 'start+offset' position where 'start' computed in sectors
           * and 'offset' is offset inside sector (  reading may cross sectors
           * boundary; in this case assumed we want to read sequential sector(  s ) )
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * start - sector num to start read from
           * offset - offset inside sector 'start'
           * count - count of bytes to read
           * buff - buffer provided by user
           *
           * RETURNS:
           * bytes read on success,   or -1 if error occured
           * and errno set appropriately
           */
          ssize_t
     177  _fat_block_read(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t start,  
           uint32_t offset,  
           uint32_t count,  
           void *buff
            )
          {
           int rc = RC_OK;
           register fat_fs_info_t *fs_info = mt_entry->fs_info;
           ssize_t cmpltd = 0;
           uint32_t blk = start;
           uint32_t ofs = offset;
           rtems_bdbuf_buffer *block = NULL;
           uint32_t c = 0;
          
           while (  count > 0 )
           {
           rc = fat_buf_access(  fs_info,   blk,   FAT_OP_TYPE_READ,   &block );
           if (  rc != RC_OK )
           return -1;
          
           c = MIN(  count,   (  fs_info->vol.bps - ofs ) );
           memcpy(  (  buff + cmpltd ),   (  block->buffer + ofs ),   c );
          
           count -= c;
           cmpltd += c;
           blk++;
           ofs = 0;
           }
           return cmpltd;
          }
          
          /* _fat_block_write --
           * This function write 'count' bytes to device filesystem is mounted on,  
           * starts at 'start+offset' position where 'start' computed in sectors
           * and 'offset' is offset inside sector (  writing may cross sectors
           * boundary; in this case assumed we want to write sequential sector(  s ) )
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * start - sector num to start read from
           * offset - offset inside sector 'start'
           * count - count of bytes to write
           * buff - buffer provided by user
           *
           * RETURNS:
           * bytes written on success,   or -1 if error occured
           * and errno set appropriately
           */
          ssize_t
     228  _fat_block_write(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t start,  
           uint32_t offset,  
           uint32_t count,  
           const void *buff )
          {
           int rc = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           ssize_t cmpltd = 0;
           uint32_t blk = start;
           uint32_t ofs = offset;
           rtems_bdbuf_buffer *block = NULL;
           uint32_t c = 0;
          
           while(  count > 0 )
           {
           c = MIN(  count,   (  fs_info->vol.bps - ofs ) );
          
           if (  c == fs_info->vol.bps )
           rc = fat_buf_access(  fs_info,   blk,   FAT_OP_TYPE_GET,   &block );
           else
           rc = fat_buf_access(  fs_info,   blk,   FAT_OP_TYPE_READ,   &block );
           if (  rc != RC_OK )
           return -1;
          
           memcpy(  (  block->buffer + ofs ),   (  buff + cmpltd ),   c );
          
           fat_buf_mark_modified(  fs_info );
          
           count -= c;
           cmpltd +=c;
           blk++;
           ofs = 0;
           }
           return cmpltd;
          }
          
          /* _fat_block_release --
           * This function works around the hack that hold a bdbuf and does
           * not release it.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           *
           * RETURNS:
           * 0 on success,   or -1 if error occured and errno set appropriately
           */
          int
     277  _fat_block_release(  
           rtems_filesystem_mount_table_entry_t *mt_entry )
          {
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           return fat_buf_release(  fs_info );
          }
          
          /* fat_cluster_read --
           * wrapper for reading a whole cluster at once
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * cln - number of cluster to read
           * buff - buffer provided by user
           *
           * RETURNS:
           * bytes read on success,   or -1 if error occured
           * and errno set appropriately
           */
          ssize_t
     297  fat_cluster_read(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t cln,  
           void *buff
            )
          {
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t fsec = 0;
          
           fsec = fat_cluster_num_to_sector_num(  mt_entry,   cln );
          
           return _fat_block_read(  mt_entry,   fsec,   0,  
           fs_info->vol.spc << fs_info->vol.sec_log2,   buff );
          }
          
          /* fat_cluster_write --
           * wrapper for writting a whole cluster at once
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * cln - number of cluster to write
           * buff - buffer provided by user
           *
           * RETURNS:
           * bytes written on success,   or -1 if error occured
           * and errno set appropriately
           */
          ssize_t
     325  fat_cluster_write(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t cln,  
           const void *buff
            )
          {
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t fsec = 0;
          
           fsec = fat_cluster_num_to_sector_num(  mt_entry,   cln );
          
           return _fat_block_write(  mt_entry,   fsec,   0,  
           fs_info->vol.spc << fs_info->vol.sec_log2,   buff );
          }
          
          /* fat_init_volume_info --
           * Get inforamtion about volume on which filesystem is mounted on
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured
           * and errno set appropriately
           */
          int
     351  fat_init_volume_info(  rtems_filesystem_mount_table_entry_t *mt_entry )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           int rc = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           register fat_vol_t *vol = &fs_info->vol;
           uint32_t data_secs = 0;
           char boot_rec[FAT_MAX_BPB_SIZE];
           char fs_info_sector[FAT_USEFUL_INFO_SIZE];
           ssize_t ret = 0;
           struct stat stat_buf;
           int i = 0;
           rtems_bdbuf_buffer *block = NULL;
          
           rc = stat(  mt_entry->dev,   &stat_buf );
           if (  rc == -1 )
           return rc;
          
           /* Must be a block device. */
           if (  !S_ISBLK(  stat_buf.st_mode ) )
           rtems_set_errno_and_return_minus_one(  ENOTTY );
          
           /* check that device is registred as block device and lock it */
           vol->dd = rtems_disk_obtain(  stat_buf.st_rdev );
           if (  vol->dd == NULL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           vol->dev = stat_buf.st_rdev;
          
           /* Read boot record */
           /* FIXME: Asserts FAT_MAX_BPB_SIZE < bdbuf block size */
           sc = rtems_bdbuf_read(   vol->dev,   0,   &block );
           if (  sc != RTEMS_SUCCESSFUL )
           {
           rtems_disk_release(  vol->dd );
           rtems_set_errno_and_return_minus_one(   EIO );
           }
          
           memcpy(   boot_rec,   block->buffer,   FAT_MAX_BPB_SIZE );
          
           sc = rtems_bdbuf_release(   block );
           if (  sc != RTEMS_SUCCESSFUL )
           {
           rtems_disk_release(  vol->dd );
           rtems_set_errno_and_return_minus_one(   EIO  );
           }
          
           /* Evaluate boot record */
           vol->bps = FAT_GET_BR_BYTES_PER_SECTOR(  boot_rec );
          
           if (   (  vol->bps != 512 ) &&
           (  vol->bps != 1024 ) &&
           (  vol->bps != 2048 ) &&
           (  vol->bps != 4096 ) )
           {
           rtems_disk_release(  vol->dd );
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           for (  vol->sec_mul = 0,   i = (  vol->bps >> FAT_SECTOR512_BITS ); (  i & 1 ) == 0;
           i >>= 1,   vol->sec_mul++ );
           for (  vol->sec_log2 = 0,   i = vol->bps; (  i & 1 ) == 0;
           i >>= 1,   vol->sec_log2++ );
          
           vol->spc = FAT_GET_BR_SECTORS_PER_CLUSTER(  boot_rec );
           /*
           * "sectors per cluster" of zero is invalid
           * (  and would hang the following loop )
           */
           if (  vol->spc == 0 )
           {
           rtems_disk_release(  vol->dd );
           rtems_set_errno_and_return_minus_one(  EINVAL );
           }
          
           for (  vol->spc_log2 = 0,   i = vol->spc; (  i & 1 ) == 0;
           i >>= 1,   vol->spc_log2++ );
          
           /*
           * "bytes per cluster" value greater than 32K is invalid
           */
           if (  (  vol->bpc = vol->bps << vol->spc_log2 ) > MS_BYTES_PER_CLUSTER_LIMIT )
           {
           rtems_disk_release(  vol->dd );
           rtems_set_errno_and_return_minus_one(  EINVAL );
           }
          
           for (  vol->bpc_log2 = 0,   i = vol->bpc; (  i & 1 ) == 0;
           i >>= 1,   vol->bpc_log2++ );
          
           vol->fats = FAT_GET_BR_FAT_NUM(  boot_rec );
           vol->fat_loc = FAT_GET_BR_RESERVED_SECTORS_NUM(  boot_rec );
          
           vol->rdir_entrs = FAT_GET_BR_FILES_PER_ROOT_DIR(  boot_rec );
          
           /* calculate the count of sectors occupied by the root directory */
           vol->rdir_secs = (  (  vol->rdir_entrs * FAT_DIRENTRY_SIZE ) + (  vol->bps - 1 ) ) /
           vol->bps;
          
           vol->rdir_size = vol->rdir_secs << vol->sec_log2;
          
           if (   (  FAT_GET_BR_SECTORS_PER_FAT(  boot_rec ) ) != 0 )
           vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT(  boot_rec );
           else
           vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT32(  boot_rec );
          
           vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length +
           vol->rdir_secs;
          
           /* for FAT12/16 root dir starts at(  sector ) */
           vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length;
          
           if (   (  FAT_GET_BR_TOTAL_SECTORS_NUM16(  boot_rec ) ) != 0 )
           vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM16(  boot_rec );
           else
           vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM32(  boot_rec );
          
           data_secs = vol->tot_secs - vol->data_fsec;
          
           vol->data_cls = data_secs / vol->spc;
          
           /* determine FAT type at least */
           if (   vol->data_cls < FAT_FAT12_MAX_CLN )
           {
           vol->type = FAT_FAT12;
           vol->mask = FAT_FAT12_MASK;
           vol->eoc_val = FAT_FAT12_EOC;
           }
           else
           {
           if (   vol->data_cls < FAT_FAT16_MAX_CLN )
           {
           vol->type = FAT_FAT16;
           vol->mask = FAT_FAT16_MASK;
           vol->eoc_val = FAT_FAT16_EOC;
           }
           else
           {
           vol->type = FAT_FAT32;
           vol->mask = FAT_FAT32_MASK;
           vol->eoc_val = FAT_FAT32_EOC;
           }
           }
          
           if (  vol->type == FAT_FAT32 )
           {
           vol->rdir_cl = FAT_GET_BR_FAT32_ROOT_CLUSTER(  boot_rec );
          
           vol->mirror = FAT_GET_BR_EXT_FLAGS(  boot_rec ) & FAT_BR_EXT_FLAGS_MIRROR;
           if (  vol->mirror )
           vol->afat = FAT_GET_BR_EXT_FLAGS(  boot_rec ) & FAT_BR_EXT_FLAGS_FAT_NUM;
           else
           vol->afat = 0;
          
           vol->info_sec = FAT_GET_BR_FAT32_FS_INFO_SECTOR(  boot_rec );
           if(   vol->info_sec == 0  )
           {
           rtems_disk_release(  vol->dd );
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
           else
           {
           ret = _fat_block_read(  mt_entry,   vol->info_sec ,   0,  
           FAT_FSI_LEADSIG_SIZE,   fs_info_sector );
           if (   ret < 0  )
           {
           rtems_disk_release(  vol->dd );
           return -1;
           }
          
           if (  FAT_GET_FSINFO_LEAD_SIGNATURE(  fs_info_sector ) !=
           FAT_FSINFO_LEAD_SIGNATURE_VALUE )
           {
           _fat_block_release(  mt_entry );
           rtems_disk_release(  vol->dd );
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
           else
           {
           ret = _fat_block_read(  mt_entry,   vol->info_sec ,   FAT_FSI_INFO,  
           FAT_USEFUL_INFO_SIZE,   fs_info_sector );
           if (   ret < 0  )
           {
           _fat_block_release(  mt_entry );
           rtems_disk_release(  vol->dd );
           return -1;
           }
          
           vol->free_cls = FAT_GET_FSINFO_FREE_CLUSTER_COUNT(  fs_info_sector );
           vol->next_cl = FAT_GET_FSINFO_NEXT_FREE_CLUSTER(  fs_info_sector );
           rc = fat_fat32_update_fsinfo_sector(  mt_entry,   0xFFFFFFFF,  
           0xFFFFFFFF );
           if (   rc != RC_OK  )
           {
           _fat_block_release(  mt_entry );
           rtems_disk_release(  vol->dd );
           return rc;
           }
           }
           }
           }
           else
           {
           vol->rdir_cl = 0;
           vol->mirror = 0;
           vol->afat = 0;
           vol->free_cls = 0xFFFFFFFF;
           vol->next_cl = 0xFFFFFFFF;
           }
          
           _fat_block_release(  mt_entry );
          
           vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat;
          
           /* set up collection of fat-files fd */
           fs_info->vhash = calloc(  FAT_HASH_SIZE,   sizeof(  rtems_chain_control ) );
           if (   fs_info->vhash == NULL  )
           {
           rtems_disk_release(  vol->dd );
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
           }
          
           for (  i = 0; i < FAT_HASH_SIZE; i++ )
           rtems_chain_initialize_empty(  fs_info->vhash + i );
          
           fs_info->rhash = calloc(  FAT_HASH_SIZE,   sizeof(  rtems_chain_control ) );
           if (   fs_info->rhash == NULL  )
           {
           rtems_disk_release(  vol->dd );
           free(  fs_info->vhash );
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
           }
           for (  i = 0; i < FAT_HASH_SIZE; i++ )
           rtems_chain_initialize_empty(  fs_info->rhash + i );
          
           fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE;
           fs_info->uino_base = (  vol->tot_secs << vol->sec_mul ) << 4;
           fs_info->index = 0;
           fs_info->uino = (  char * )calloc(  fs_info->uino_pool_size,   sizeof(  char ) );
           if (   fs_info->uino == NULL  )
           {
           rtems_disk_release(  vol->dd );
           free(  fs_info->vhash );
           free(  fs_info->rhash );
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
           }
           fs_info->sec_buf = (  uint8_t * )calloc(  vol->bps,   sizeof(  uint8_t ) );
           if (  fs_info->sec_buf == NULL )
           {
           rtems_disk_release(  vol->dd );
           free(  fs_info->vhash );
           free(  fs_info->rhash );
           free(  fs_info->uino );
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
           }
          
           return RC_OK;
          }
          
          /* fat_shutdown_drive --
           * Free all allocated resources and synchronize all necessary data
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured
           * and errno set appropriately
           */
          int
     621  fat_shutdown_drive(  rtems_filesystem_mount_table_entry_t *mt_entry )
          {
           int rc = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           int i = 0;
          
           if (  fs_info->vol.type & FAT_FAT32 )
           {
           rc = fat_fat32_update_fsinfo_sector(  mt_entry,   fs_info->vol.free_cls,  
           fs_info->vol.next_cl );
           if (   rc != RC_OK  )
           rc = -1;
           }
          
           fat_buf_release(  fs_info );
          
           if (  rtems_bdbuf_syncdev(  fs_info->vol.dev ) != RTEMS_SUCCESSFUL )
           rc = -1;
          
           for (  i = 0; i < FAT_HASH_SIZE; i++ )
           {
           rtems_chain_node *node = NULL;
           rtems_chain_control *the_chain = fs_info->vhash + i;
          
           while (   (  node = rtems_chain_get(  the_chain ) ) != NULL  )
           free(  node );
           }
          
           for (  i = 0; i < FAT_HASH_SIZE; i++ )
           {
           rtems_chain_node *node = NULL;
           rtems_chain_control *the_chain = fs_info->rhash + i;
          
           while (   (  node = rtems_chain_get(  the_chain ) ) != NULL  )
           free(  node );
           }
          
           free(  fs_info->vhash );
           free(  fs_info->rhash );
          
           free(  fs_info->uino );
           free(  fs_info->sec_buf );
           rtems_disk_release(  fs_info->vol.dd );
          
           if (  rc )
           errno = EIO;
           return rc;
          }
          
          /* fat_init_clusters_chain --
           * Zeroing contents of all clusters in the chain
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * start_cluster_num - num of first cluster in the chain
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured
           * and errno set appropriately
           */
          int
     682  fat_init_clusters_chain(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t start_cln
            )
          {
           int rc = RC_OK;
           ssize_t ret = 0;
           register fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t cur_cln = start_cln;
           char *buf;
          
           buf = calloc(  fs_info->vol.bpc,   sizeof(  char ) );
           if (   buf == NULL  )
           rtems_set_errno_and_return_minus_one(   EIO  );
          
           while (  (  cur_cln & fs_info->vol.mask ) < fs_info->vol.eoc_val )
           {
           ret = fat_cluster_write(  mt_entry,   cur_cln,   buf );
           if (   ret == -1  )
           {
           free(  buf );
           return -1;
           }
          
           rc = fat_get_fat_cluster(  mt_entry,   cur_cln,   &cur_cln );
           if (   rc != RC_OK  )
           {
           free(  buf );
           return rc;
           }
          
           }
           free(  buf );
           return rc;
          }
          
          #define FAT_UNIQ_INO_BASE 0x0FFFFF00
          
          #define FAT_UNIQ_INO_IS_BUSY(  index,   arr ) \
           (  (  (  arr )[(  (  index )>>3 )]>>(  (  index ) & (  8-1 ) ) ) & 0x01 )
          
          #define FAT_SET_UNIQ_INO_BUSY(  index,   arr ) \
           (  (  arr )[(  (  index )>>3 )] |= (  0x01<<(  (  index ) & (  8-1 ) ) ) )
          
          #define FAT_SET_UNIQ_INO_FREE(  index,   arr ) \
           (  (  arr )[(  (  index )>>3 )] &= (  ~(  0x01<<(  (  index ) & (  8-1 ) ) ) ) )
          
          /* fat_get_unique_ino --
           * Allocate unique ino from unique ino pool
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           *
           * RETURNS:
           * unique inode number on success,   or 0 if there is no free unique inode
           * number in the pool
           *
           * ATTENTION:
           * 0 means FAILED !!!
     741   *
           */
          uint32_t
          fat_get_unique_ino(  rtems_filesystem_mount_table_entry_t *mt_entry )
          {
           register fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t j = 0;
           bool resrc_unsuff = false;
          
           while (  !resrc_unsuff )
           {
           for (  j = 0; j < fs_info->uino_pool_size; j++ )
           {
           if (  !FAT_UNIQ_INO_IS_BUSY(  fs_info->index,   fs_info->uino ) )
           {
           FAT_SET_UNIQ_INO_BUSY(  fs_info->index,   fs_info->uino );
           return (  fs_info->uino_base + fs_info->index );
           }
           fs_info->index++;
           if (  fs_info->index >= fs_info->uino_pool_size )
           fs_info->index = 0;
           }
          
           if (  (  fs_info->uino_pool_size << 1 ) < (  0x0FFFFFFF - fs_info->uino_base ) )
           {
           fs_info->uino_pool_size <<= 1;
           fs_info->uino = realloc(  fs_info->uino,   fs_info->uino_pool_size );
           if (  fs_info->uino != NULL )
           fs_info->index = fs_info->uino_pool_size;
           else
           resrc_unsuff = true;
           }
           else
           resrc_unsuff = true;
           }
           return 0;
          }
          
          /* fat_free_unique_ino --
           * Return unique ino to unique ino pool
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * ino - inode number to free
           *
           * RETURNS:
     787   * None
           */
          void
          fat_free_unique_ino(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t ino
            )
          {
           fat_fs_info_t *fs_info = mt_entry->fs_info;
          
           FAT_SET_UNIQ_INO_FREE(  (  ino - fs_info->uino_base ),   fs_info->uino );
          }
          
          /* fat_ino_is_unique --
           * Test whether ino is from unique ino pool
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * ino - ino to be tested
           *
           * RETURNS:
     808   * true if ino is allocated from unique ino pool,   false otherwise
           */
          inline bool
          fat_ino_is_unique(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t ino
            )
          {
           fat_fs_info_t *fs_info = mt_entry->fs_info;
          
           return (  ino >= fs_info->uino_base );
          }
          
          /* fat_fat32_update_fsinfo_sector --
           * Synchronize fsinfo sector for FAT32 volumes
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * free_count - count of free clusters
           * next_free - the next free cluster num
           *
           * RETURNS:
     830   * RC_OK on success,   or -1 if error occured (  errno set appropriately )
           */
          int
          fat_fat32_update_fsinfo_sector(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t free_count,  
           uint32_t next_free
            )
          {
           ssize_t ret1 = 0,   ret2 = 0;
           register fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t le_free_count = 0;
           uint32_t le_next_free = 0;
          
           le_free_count = CT_LE_L(  free_count );
           le_next_free = CT_LE_L(  next_free );
          
           ret1 = _fat_block_write(  mt_entry,  
           fs_info->vol.info_sec,  
           FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET,  
           4,  
           (  char * )(  &le_free_count ) );
          
           ret2 = _fat_block_write(  mt_entry,  
           fs_info->vol.info_sec,  
           FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET,  
           4,  
           (  char * )(  &le_next_free ) );
          
           if (   (  ret1 < 0 ) || (  ret2 < 0 )  )
           return -1;
          
           return RC_OK;
          }

libfs/src/dosfs/fat_fat_operations.c

       1  /*
           * fat_fat_operations.c
           *
           * General operations on File Allocation Table
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * @(  # ) $Id: fat_fat_operations.c,  v 1.10 2010/07/04 14:53:45 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          
          #include <rtems/libio_.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          
          /* fat_scan_fat_for_free_clusters --
           * Allocate chain of free clusters from Files Allocation Table
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * chain - the number of the first allocated cluster (  first cluster
           * in the chain )
           * count - count of clusters to allocate (  chain length )
           *
           * RETURNS:
           * RC_OK on success,   or error code if error occured (  errno set
           * appropriately )
           *
           *
           */
          int
      44  fat_scan_fat_for_free_clusters(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t *chain,  
           uint32_t count,  
           uint32_t *cls_added,  
           uint32_t *last_cl
            )
          {
           int rc = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t cl4find = 2;
           uint32_t next_cln = 0;
           uint32_t save_cln = 0;
           uint32_t data_cls_val = fs_info->vol.data_cls + 2;
           uint32_t i = 2;
          
           *cls_added = 0;
          
           if (  count == 0 )
           return rc;
          
           if (  fs_info->vol.next_cl != FAT_UNDEFINED_VALUE )
           cl4find = fs_info->vol.next_cl;
          
           /*
           * fs_info->vol.data_cls is exactly the count of data clusters
           * starting at cluster 2,   so the maximum valid cluster number is
           * (  fs_info->vol.data_cls + 1 )
           */
           while (  i < data_cls_val )
           {
           rc = fat_get_fat_cluster(  mt_entry,   cl4find,   &next_cln );
           if (   rc != RC_OK  )
           {
           if (  *cls_added != 0 )
           fat_free_fat_clusters_chain(  mt_entry,   (  *chain ) );
           return rc;
           }
          
           if (  next_cln == FAT_GENFAT_FREE )
           {
           /*
           * We are enforced to process allocation of the first free cluster
           * by separate 'if' statement because otherwise undo function
           * wouldn't work properly
           */
           if (  *cls_added == 0 )
           {
           *chain = cl4find;
           rc = fat_set_fat_cluster(  mt_entry,   cl4find,   FAT_GENFAT_EOC );
           if (   rc != RC_OK  )
           {
           /*
           * this is the first cluster we tried to allocate so no
           * cleanup activity needed
           */
           return rc;
           }
           }
           else
           {
           /* set EOC value to new allocated cluster */
           rc = fat_set_fat_cluster(  mt_entry,   cl4find,   FAT_GENFAT_EOC );
           if (   rc != RC_OK  )
           {
           /* cleanup activity */
           fat_free_fat_clusters_chain(  mt_entry,   (  *chain ) );
           return rc;
           }
          
           rc = fat_set_fat_cluster(  mt_entry,   save_cln,   cl4find );
           if (   rc != RC_OK  )
           {
           /* cleanup activity */
           fat_free_fat_clusters_chain(  mt_entry,   (  *chain ) );
           /* trying to save last allocated cluster for future use */
           fat_set_fat_cluster(  mt_entry,   cl4find,   FAT_GENFAT_FREE );
           fat_buf_release(  fs_info );
           return rc;
           }
           }
          
           save_cln = cl4find;
           (  *cls_added )++;
          
           /* have we satisfied request ? */
           if (  *cls_added == count )
           {
           fs_info->vol.next_cl = save_cln;
           if (  fs_info->vol.free_cls != 0xFFFFFFFF )
           fs_info->vol.free_cls -= (  *cls_added );
           *last_cl = save_cln;
           fat_buf_release(  fs_info );
           return rc;
           }
           }
           i++;
           cl4find++;
           if (  cl4find >= data_cls_val )
           cl4find = 2;
           }
          
           fs_info->vol.next_cl = save_cln;
           if (  fs_info->vol.free_cls != 0xFFFFFFFF )
           fs_info->vol.free_cls -= (  *cls_added );
          
           *last_cl = save_cln;
           fat_buf_release(  fs_info );
           return RC_OK;
          }
          
          /* fat_free_fat_clusters_chain --
           * Free chain of clusters in Files Allocation Table.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * chain - number of the first cluster in the chain
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set appropriately )
           */
          int
     166  fat_free_fat_clusters_chain(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t chain
            )
          {
           int rc = RC_OK,   rc1 = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t cur_cln = chain;
           uint32_t next_cln = 0;
           uint32_t freed_cls_cnt = 0;
          
           while (  (  cur_cln & fs_info->vol.mask ) < fs_info->vol.eoc_val )
           {
           rc = fat_get_fat_cluster(  mt_entry,   cur_cln,   &next_cln );
           if (   rc != RC_OK  )
           {
           if(  fs_info->vol.free_cls != FAT_UNDEFINED_VALUE )
           fs_info->vol.free_cls += freed_cls_cnt;
          
           fat_buf_release(  fs_info );
           return rc;
           }
          
           rc = fat_set_fat_cluster(  mt_entry,   cur_cln,   FAT_GENFAT_FREE );
           if (   rc != RC_OK  )
           rc1 = rc;
          
           freed_cls_cnt++;
           cur_cln = next_cln;
           }
          
           fs_info->vol.next_cl = chain;
           if (  fs_info->vol.free_cls != FAT_UNDEFINED_VALUE )
           fs_info->vol.free_cls += freed_cls_cnt;
          
           fat_buf_release(  fs_info );
           if (  rc1 != RC_OK )
           return rc1;
          
           return RC_OK;
          }
          
          /* fat_get_fat_cluster --
           * Fetches the contents of the cluster (  link to next cluster in the chain )
           * from Files Allocation Table.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * cln - number of cluster to fetch the contents from
           * ret_val - contents of the cluster 'cln' (  link to next cluster in
           * the chain )
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured
           * and errno set appropriately
           */
          int
     223  fat_get_fat_cluster(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t cln,  
           uint32_t *ret_val
            )
          {
           int rc = RC_OK;
           register fat_fs_info_t *fs_info = mt_entry->fs_info;
           rtems_bdbuf_buffer *block0 = NULL;
           uint32_t sec = 0;
           uint32_t ofs = 0;
          
           /* sanity check */
           if (   (  cln < 2 ) || (  cln > (  fs_info->vol.data_cls + 1 ) )  )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           sec = (  FAT_FAT_OFFSET(  fs_info->vol.type,   cln ) >> fs_info->vol.sec_log2 ) +
           fs_info->vol.afat_loc;
           ofs = FAT_FAT_OFFSET(  fs_info->vol.type,   cln ) & (  fs_info->vol.bps - 1 );
          
           rc = fat_buf_access(  fs_info,   sec,   FAT_OP_TYPE_READ,   &block0 );
           if (  rc != RC_OK )
           return rc;
          
           switch (   fs_info->vol.type  )
           {
           case FAT_FAT12:
           /*
           * we are enforced in complex computations for FAT12 to escape CPU
           * align problems for some architectures
           */
           *ret_val = (  *(  (  uint8_t * )(  block0->buffer + ofs ) ) );
           if (   ofs == (  fs_info->vol.bps - 1 )  )
           {
           rc = fat_buf_access(  fs_info,   sec + 1,   FAT_OP_TYPE_READ,  
           &block0 );
           if (  rc != RC_OK )
           return rc;
          
           *ret_val |= (  *(  (  uint8_t * )(  block0->buffer ) ) )<<8;
           }
           else
           {
           *ret_val |= (  *(  (  uint8_t * )(  block0->buffer + ofs + 1 ) ) )<<8;
           }
          
           if (   FAT_CLUSTER_IS_ODD(  cln )  )
           *ret_val = (  *ret_val ) >> FAT12_SHIFT;
           else
           *ret_val = (  *ret_val ) & FAT_FAT12_MASK;
           break;
          
           case FAT_FAT16:
           *ret_val = *(  (  uint16_t * )(  block0->buffer + ofs ) );
           *ret_val = CF_LE_W(  *ret_val );
           break;
          
           case FAT_FAT32:
           *ret_val = *(  (  uint32_t * )(  block0->buffer + ofs ) );
           *ret_val = CF_LE_L(  *ret_val );
           break;
          
           default:
           rtems_set_errno_and_return_minus_one(  EIO );
           break;
           }
          
           return RC_OK;
          }
          
          /* fat_set_fat_cluster --
           * Set the contents of the cluster (  link to next cluster in the chain )
           * from Files Allocation Table.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * cln - number of cluster to set contents to
           * in_val - value to set
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured
           * and errno set appropriately
           */
          int
     307  fat_set_fat_cluster(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t cln,  
           uint32_t in_val
            )
          {
           int rc = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t sec = 0;
           uint32_t ofs = 0;
           uint16_t fat16_clv = 0;
           uint32_t fat32_clv = 0;
           rtems_bdbuf_buffer *block0 = NULL;
          
           /* sanity check */
           if (   (  cln < 2 ) || (  cln > (  fs_info->vol.data_cls + 1 ) )  )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           sec = (  FAT_FAT_OFFSET(  fs_info->vol.type,   cln ) >> fs_info->vol.sec_log2 ) +
           fs_info->vol.afat_loc;
           ofs = FAT_FAT_OFFSET(  fs_info->vol.type,   cln ) & (  fs_info->vol.bps - 1 );
          
           rc = fat_buf_access(  fs_info,   sec,   FAT_OP_TYPE_READ,   &block0 );
           if (  rc != RC_OK )
           return rc;
          
           switch (   fs_info->vol.type  )
           {
           case FAT_FAT12:
           if (   FAT_CLUSTER_IS_ODD(  cln )  )
           {
           fat16_clv = (  (  uint16_t  )in_val ) << FAT_FAT12_SHIFT;
           *(  (  uint8_t * )(  block0->buffer + ofs ) ) =
           (  *(  (  uint8_t * )(  block0->buffer + ofs ) ) ) & 0x0F;
          
           *(  (  uint8_t * )(  block0->buffer + ofs ) ) =
           (  *(  (  uint8_t * )(  block0->buffer + ofs ) ) ) |
           (  uint8_t  )(  fat16_clv & 0x00FF );
          
           fat_buf_mark_modified(  fs_info );
          
           if (   ofs == (  fs_info->vol.bps - 1 )  )
           {
           rc = fat_buf_access(  fs_info,   sec + 1,   FAT_OP_TYPE_READ,  
           &block0 );
           if (  rc != RC_OK )
           return rc;
          
           *(  (  uint8_t * )(  block0->buffer ) ) &= 0x00;
          
           *(  (  uint8_t * )(  block0->buffer ) ) =
           (  *(  (  uint8_t * )(  block0->buffer ) ) ) |
           (  uint8_t  )(  (  fat16_clv & 0xFF00 )>>8 );
          
           fat_buf_mark_modified(  fs_info );
           }
           else
           {
           *(  (  uint8_t * )(  block0->buffer + ofs + 1 ) ) &= 0x00;
          
           *(  (  uint8_t * )(  block0->buffer + ofs + 1 ) ) =
           (  *(  (  uint8_t * )(  block0->buffer + ofs + 1 ) ) ) |
           (  uint8_t  )(  (  fat16_clv & 0xFF00 )>>8 );
           }
           }
           else
           {
           fat16_clv = (  (  uint16_t  )in_val ) & FAT_FAT12_MASK;
           *(  (  uint8_t * )(  block0->buffer + ofs ) ) &= 0x00;
          
           *(  (  uint8_t * )(  block0->buffer + ofs ) ) =
           (  *(  (  uint8_t * )(  block0->buffer + ofs ) ) ) |
           (  uint8_t  )(  fat16_clv & 0x00FF );
          
           fat_buf_mark_modified(  fs_info );
          
           if (   ofs == (  fs_info->vol.bps - 1 )  )
           {
           rc = fat_buf_access(  fs_info,   sec + 1,   FAT_OP_TYPE_READ,  
           &block0 );
           if (  rc != RC_OK )
           return rc;
          
           *(  (  uint8_t * )(  block0->buffer ) ) =
           (  *(  (  uint8_t * )(  block0->buffer ) ) ) & 0xF0;
          
           *(  (  uint8_t * )(  block0->buffer ) ) =
           (  *(  (  uint8_t * )(  block0->buffer ) ) ) |
           (  uint8_t  )(  (  fat16_clv & 0xFF00 )>>8 );
          
           fat_buf_mark_modified(  fs_info );
           }
           else
           {
           *(  (  uint8_t * )(  block0->buffer + ofs + 1 ) ) =
           (  *(  (  uint8_t * )(  block0->buffer + ofs + 1 ) ) ) & 0xF0;
          
           *(  (  uint8_t * )(  block0->buffer + ofs+1 ) ) =
           (  *(  (  uint8_t * )(  block0->buffer + ofs+1 ) ) ) |
           (  uint8_t  )(  (  fat16_clv & 0xFF00 )>>8 );
           }
           }
           break;
          
           case FAT_FAT16:
           *(  (  uint16_t * )(  block0->buffer + ofs ) ) =
           (  uint16_t  )(  CT_LE_W(  in_val ) );
           fat_buf_mark_modified(  fs_info );
           break;
          
           case FAT_FAT32:
           fat32_clv = CT_LE_L(  (  in_val & FAT_FAT32_MASK ) );
          
           *(  (  uint32_t * )(  block0->buffer + ofs ) ) =
           (  *(  (  uint32_t * )(  block0->buffer + ofs ) ) ) & (  CT_LE_L(  0xF0000000 ) );
          
           *(  (  uint32_t * )(  block0->buffer + ofs ) ) =
           fat32_clv | (  *(  (  uint32_t * )(  block0->buffer + ofs ) ) );
          
           fat_buf_mark_modified(  fs_info );
           break;
          
           default:
           rtems_set_errno_and_return_minus_one(  EIO );
           break;
          
           }
          
           return RC_OK;
          }

libfs/src/dosfs/fat_file.c

       1  /*
           * fat_file.c
           *
           * General operations on "fat-file"
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * @(  # ) $Id: fat_file.c,  v 1.17 2010/08/23 23:17:42 joel Exp $
           *
           */
          
          #define MSDOS_TRACE 1
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <stdarg.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <assert.h>
          #include <time.h>
          
          #include <rtems/libio_.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          static inline void
      36  _hash_insert(  rtems_chain_control *hash,   uint32_t key1,   uint32_t key2,  
           fat_file_fd_t *el );
          
          static inline void
      40  _hash_delete(  rtems_chain_control *hash,   uint32_t key1,   uint32_t key2,  
           fat_file_fd_t *el );
          
          static inline int
      44  _hash_search(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           rtems_chain_control *hash,  
           uint32_t key1,  
           uint32_t key2,  
           fat_file_fd_t **ret
           );
          
          static off_t
      53  fat_file_lseek(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd,  
           uint32_t file_cln,  
           uint32_t *disk_cln
           );
          
          /* fat_file_open --
           * Open fat-file. Two hash tables are accessed by key
           * constructed from cluster num and offset of the node (  i.e.
           * files/directories are distinguished by location on the disk ).
           * First,   hash table(  "vhash" ) consists of fat-file descriptors corresponded
           * to "valid" files is accessed. Search is made by 2 fields equal to key
           * constructed. If descriptor is found in the "vhash" - return it.
           * Otherwise search is made in hash table(  "rhash" ) consits of fat-file
           * descriptors corresponded to "removed-but-still-open" files with the
           * same keys.
           * If search failed,   new fat-file descriptor is added to "vhash"
           * with both key fields equal to constructed key. Otherwise new fat-file
           * descriptor is added to "vhash" with first key field equal to key
           * constructed and the second equal to an unique (  unique among all values
           * of second key fields ) value.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * pos - cluster and offset of the node
           * fat_fd - placeholder for returned fat-file descriptor
           *
           * RETURNS:
           * RC_OK and pointer to opened descriptor on success,   or -1 if error
           * occured (  errno set appropriately )
           */
          int
      86  fat_file_open(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_dir_pos_t *dir_pos,  
           fat_file_fd_t **fat_fd
            )
          {
           int rc = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           fat_file_fd_t *lfat_fd = NULL;
           uint32_t key = 0;
          
           /* construct key */
           key = fat_construct_key(  mt_entry,   &dir_pos->sname );
          
           /* access "valid" hash table */
           rc = _hash_search(  mt_entry,   fs_info->vhash,   key,   0,   &lfat_fd );
           if (   rc == RC_OK  )
           {
           /* return pointer to fat_file_descriptor allocated before */
           (  *fat_fd ) = lfat_fd;
           lfat_fd->links_num++;
           return rc;
           }
          
           /* access "removed-but-still-open" hash table */
           rc = _hash_search(  mt_entry,   fs_info->rhash,   key,   key,   &lfat_fd );
          
           lfat_fd = (  *fat_fd ) = (  fat_file_fd_t* )malloc(  sizeof(  fat_file_fd_t ) );
           if (   lfat_fd == NULL  )
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
          
           memset(  lfat_fd,   0,   sizeof(  fat_file_fd_t ) );
          
           lfat_fd->links_num = 1;
           lfat_fd->flags &= ~FAT_FILE_REMOVED;
           lfat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
          
           lfat_fd->dir_pos = *dir_pos;
          
           if (   rc != RC_OK  )
           lfat_fd->ino = key;
           else
           {
           lfat_fd->ino = fat_get_unique_ino(  mt_entry );
          
           if (   lfat_fd->ino == 0  )
           {
           free(  (  *fat_fd ) );
           /*
           * XXX: kernel resource is unsufficient,   but not the memory,  
           * but there is no suitable errno :(  
           */
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
           }
           }
           _hash_insert(  fs_info->vhash,   key,   lfat_fd->ino,   lfat_fd );
          
           /*
           * other fields of fat-file descriptor will be initialized on upper
           * level
           */
          
           return RC_OK;
          }
          
          
          /* fat_file_reopen --
           * Increment by 1 number of links
           *
           * PARAMETERS:
           * fat_fd - fat-file descriptor
           *
           * RETURNS:
           * RC_OK
           */
          int
     162  fat_file_reopen(  fat_file_fd_t *fat_fd )
          {
           fat_fd->links_num++;
           return RC_OK;
          }
          
          /* fat_file_close --
           * Close fat-file. If count of links to fat-file
           * descriptor is greater than 1 (  i.e. somebody esle holds pointer
           * to this descriptor ) just decrement it. Otherwise
           * do the following. If this descriptor corresponded to removed fat-file
           * then free clusters contained fat-file data,   delete descriptor from
           * "rhash" table and free memory allocated by descriptor. If descriptor
           * correspondes to non-removed fat-file and 'ino' field has value from
           * unique inode numbers pool then set count of links to descriptor to zero
           * and leave it in hash,   otherwise delete descriptor from "vhash" and free
           * memory allocated by the descriptor
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           *
           * RETURNS:
           * RC_OK,   or -1 if error occured (  errno set appropriately )
           */
          int
     188  fat_file_close(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd
            )
          {
           int rc = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t key = 0;
          
           /*
           * if links_num field of fat-file descriptor is greater than 1
           * decrement the count of links and return
           */
           if (  fat_fd->links_num > 1 )
           {
           fat_fd->links_num--;
           return rc;
           }
          
           key = fat_construct_key(  mt_entry,   &fat_fd->dir_pos.sname );
          
           if (  fat_fd->flags & FAT_FILE_REMOVED )
           {
           rc = fat_file_truncate(  mt_entry,   fat_fd,   0 );
           if (   rc != RC_OK  )
           return rc;
          
           _hash_delete(  fs_info->rhash,   key,   fat_fd->ino,   fat_fd );
          
           if (   fat_ino_is_unique(  mt_entry,   fat_fd->ino )  )
           fat_free_unique_ino(  mt_entry,   fat_fd->ino );
          
           free(  fat_fd );
           }
           else
           {
           if (  fat_ino_is_unique(  mt_entry,   fat_fd->ino ) )
           {
           fat_fd->links_num = 0;
           }
           else
           {
           _hash_delete(  fs_info->vhash,   key,   fat_fd->ino,   fat_fd );
           free(  fat_fd );
           }
           }
           /*
           * flush any modified "cached" buffer back to disk
           */
           rc = fat_buf_release(  fs_info );
          
           return rc;
          }
          
          /* fat_file_read --
           * Read 'count' bytes from 'start' position from fat-file. This
           * interface hides the architecture of fat-file,   represents it as
           * linear file
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           * start - offset in fat-file (  in bytes ) to read from
           * count - count of bytes to read
           * buf - buffer provided by user
           *
           * RETURNS:
           * the number of bytes read on success,   or -1 if error occured (  errno
           * set appropriately )
           */
          ssize_t
     259  fat_file_read(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd,  
           uint32_t start,  
           uint32_t count,  
           uint8_t *buf
           )
          {
           int rc = RC_OK;
           ssize_t ret = 0;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t cmpltd = 0;
           uint32_t cur_cln = 0;
           uint32_t cl_start = 0;
           uint32_t save_cln = 0;
           uint32_t ofs = 0;
           uint32_t save_ofs;
           uint32_t sec = 0;
           uint32_t byte = 0;
           uint32_t c = 0;
          
           /* it couldn't be removed - otherwise cache update will be broken */
           if (  count == 0 )
           return cmpltd;
          
           /*
           * >= because start is offset and computed from 0 and file_size
           * computed from 1
           */
           if (   start >= fat_fd->fat_file_size  )
           return FAT_EOF;
          
           if (  (  count > fat_fd->fat_file_size ) ||
           (  start > fat_fd->fat_file_size - count ) )
           count = fat_fd->fat_file_size - start;
          
           if (  (  FAT_FD_OF_ROOT_DIR(  fat_fd ) ) &&
           (  fs_info->vol.type & (  FAT_FAT12 | FAT_FAT16 ) ) )
           {
           sec = fat_cluster_num_to_sector_num(  mt_entry,   fat_fd->cln );
           sec += (  start >> fs_info->vol.sec_log2 );
           byte = start & (  fs_info->vol.bps - 1 );
          
           ret = _fat_block_read(  mt_entry,   sec,   byte,   count,   buf );
           if (   ret < 0  )
           return -1;
          
           return ret;
           }
          
           cl_start = start >> fs_info->vol.bpc_log2;
           save_ofs = ofs = start & (  fs_info->vol.bpc - 1 );
          
           rc = fat_file_lseek(  mt_entry,   fat_fd,   cl_start,   &cur_cln );
           if (  rc != RC_OK )
           return rc;
          
           while (  count > 0 )
           {
           c = MIN(  count,   (  fs_info->vol.bpc - ofs ) );
          
           sec = fat_cluster_num_to_sector_num(  mt_entry,   cur_cln );
           sec += (  ofs >> fs_info->vol.sec_log2 );
           byte = ofs & (  fs_info->vol.bps - 1 );
          
           ret = _fat_block_read(  mt_entry,   sec,   byte,   c,   buf + cmpltd );
           if (   ret < 0  )
           return -1;
          
           count -= c;
           cmpltd += c;
           save_cln = cur_cln;
           rc = fat_get_fat_cluster(  mt_entry,   cur_cln,   &cur_cln );
           if (   rc != RC_OK  )
           return rc;
          
           ofs = 0;
           }
          
           /* update cache */
           /* XXX: check this - I'm not sure :(   */
           fat_fd->map.file_cln = cl_start +
           (  (  save_ofs + cmpltd - 1 ) >> fs_info->vol.bpc_log2 );
           fat_fd->map.disk_cln = save_cln;
          
           return cmpltd;
          }
          
          /* fat_file_write --
           * Write 'count' bytes of data from user supplied buffer to fat-file
           * starting at offset 'start'. This interface hides the architecture
           * of fat-file,   represents it as linear file
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           * start - offset(  in bytes ) to write from
           * count - count
           * buf - buffer provided by user
           *
           * RETURNS:
           * number of bytes actually written to the file on success,   or -1 if
           * error occured (  errno set appropriately )
           */
          ssize_t
     364  fat_file_write(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd,  
           uint32_t start,  
           uint32_t count,  
           const uint8_t *buf
            )
          {
           int rc = 0;
           ssize_t ret = 0;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t cmpltd = 0;
           uint32_t cur_cln = 0;
           uint32_t save_cln = 0; /* FIXME: This might be incorrect,   cf. below */
           uint32_t cl_start = 0;
           uint32_t ofs = 0;
           uint32_t save_ofs;
           uint32_t sec = 0;
           uint32_t byte = 0;
           uint32_t c = 0;
          
           if (   count == 0  )
           return cmpltd;
          
           if (   start > fat_fd->fat_file_size  )
           rtems_set_errno_and_return_minus_one(   EIO  );
          
           if (  (  count > fat_fd->size_limit ) ||
           (  start > fat_fd->size_limit - count ) )
           rtems_set_errno_and_return_minus_one(   EIO  );
          
           rc = fat_file_extend(  mt_entry,   fat_fd,   start + count,   &c );
           if (  rc != RC_OK )
           return rc;
          
           /*
           * check whether there was enough room on device to locate
           * file of 'start + count' bytes
           */
           if (  c != (  start + count ) )
           count = c - start;
          
           if (  (  FAT_FD_OF_ROOT_DIR(  fat_fd ) ) &&
           (  fs_info->vol.type & (  FAT_FAT12 | FAT_FAT16 ) ) )
           {
           sec = fat_cluster_num_to_sector_num(  mt_entry,   fat_fd->cln );
           sec += (  start >> fs_info->vol.sec_log2 );
           byte = start & (  fs_info->vol.bps - 1 );
          
           ret = _fat_block_write(  mt_entry,   sec,   byte,   count,   buf );
           if (   ret < 0  )
           return -1;
          
           return ret;
           }
          
           cl_start = start >> fs_info->vol.bpc_log2;
           save_ofs = ofs = start & (  fs_info->vol.bpc - 1 );
          
           rc = fat_file_lseek(  mt_entry,   fat_fd,   cl_start,   &cur_cln );
           if (  rc != RC_OK )
           return rc;
          
           while (  count > 0 )
           {
           c = MIN(  count,   (  fs_info->vol.bpc - ofs ) );
          
           sec = fat_cluster_num_to_sector_num(  mt_entry,   cur_cln );
           sec += (  ofs >> fs_info->vol.sec_log2 );
           byte = ofs & (  fs_info->vol.bps - 1 );
          
           ret = _fat_block_write(  mt_entry,   sec,   byte,   c,   buf + cmpltd );
           if (   ret < 0  )
           return -1;
          
           count -= c;
           cmpltd += c;
           save_cln = cur_cln;
           rc = fat_get_fat_cluster(  mt_entry,   cur_cln,   &cur_cln );
           if (   rc != RC_OK  )
           return rc;
          
           ofs = 0;
           }
          
           /* update cache */
           /* XXX: check this - I'm not sure :(   */
           fat_fd->map.file_cln = cl_start +
           (  (  save_ofs + cmpltd - 1 ) >> fs_info->vol.bpc_log2 );
           fat_fd->map.disk_cln = save_cln;
          
           return cmpltd;
          }
          
          /* fat_file_extend --
           * Extend fat-file. If new length less than current fat-file size -
           * do nothing. Otherwise calculate necessary count of clusters to add,  
           * allocate it and add new clusters chain to the end of
           * existing clusters chain.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           * new_length - new length
           * a_length - placeholder for result - actual new length of file
           *
           * RETURNS:
           * RC_OK and new length of file on success,   or -1 if error occured (  errno
           * set appropriately )
           */
          int
     475  fat_file_extend(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd,  
           uint32_t new_length,  
           uint32_t *a_length
            )
          {
           int rc = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t chain = 0;
           uint32_t bytes2add = 0;
           uint32_t cls2add = 0;
           uint32_t old_last_cl;
           uint32_t last_cl = 0;
           uint32_t bytes_remain = 0;
           uint32_t cls_added;
          
           *a_length = new_length;
          
           if (  new_length <= fat_fd->fat_file_size )
           return RC_OK;
          
           if (  (  FAT_FD_OF_ROOT_DIR(  fat_fd ) ) &&
           (  fs_info->vol.type & (  FAT_FAT12 | FAT_FAT16 ) ) )
           rtems_set_errno_and_return_minus_one(   ENOSPC  );
          
           bytes_remain = (  fs_info->vol.bpc -
           (  fat_fd->fat_file_size & (  fs_info->vol.bpc - 1 ) ) ) &
           (  fs_info->vol.bpc - 1 );
          
           bytes2add = new_length - fat_fd->fat_file_size;
          
           if (  bytes2add > bytes_remain )
           bytes2add -= bytes_remain;
           else
           bytes2add = 0;
          
           /*
           * if in last cluster allocated for the file there is enough room to
           * handle extention (  hence we don't need to add even one cluster to the
           * file  ) - return
           */
           if (  bytes2add == 0 )
           return RC_OK;
          
           cls2add = (  (  bytes2add - 1 ) >> fs_info->vol.bpc_log2 ) + 1;
          
           rc = fat_scan_fat_for_free_clusters(  mt_entry,   &chain,   cls2add,  
           &cls_added,   &last_cl );
          
           /* this means that low level I/O error occured */
           if (  rc != RC_OK )
           return rc;
          
           /* this means that no space left on device */
           if (  (  cls_added == 0 ) && (  bytes_remain == 0 ) )
           rtems_set_errno_and_return_minus_one(  ENOSPC );
          
           /* check wether we satisfied request for 'cls2add' clusters */
           if (  cls2add != cls_added )
           *a_length = new_length -
           (  (  cls2add - cls_added - 1 ) << fs_info->vol.bpc_log2 ) -
           (  bytes2add & (  fs_info->vol.bpc - 1 ) );
          
           /* add new chain to the end of existed */
           if (   fat_fd->fat_file_size == 0  )
           {
           fat_fd->map.disk_cln = fat_fd->cln = chain;
           fat_fd->map.file_cln = 0;
           }
           else
           {
           if (  fat_fd->map.last_cln != FAT_UNDEFINED_VALUE )
           {
           old_last_cl = fat_fd->map.last_cln;
           }
           else
           {
           rc = fat_file_ioctl(  mt_entry,   fat_fd,   F_CLU_NUM,  
           (  fat_fd->fat_file_size - 1 ),   &old_last_cl );
           if (   rc != RC_OK  )
           {
           fat_free_fat_clusters_chain(  mt_entry,   chain );
           return rc;
           }
           }
          
           rc = fat_set_fat_cluster(  mt_entry,   old_last_cl,   chain );
           if (   rc != RC_OK  )
           {
           fat_free_fat_clusters_chain(  mt_entry,   chain );
           return rc;
           }
           fat_buf_release(  fs_info );
           }
          
           /* update number of the last cluster of the file if it changed */
           if (  cls_added != 0 )
           {
           fat_fd->map.last_cln = last_cl;
           if (  fat_fd->fat_file_type == FAT_DIRECTORY )
           {
           rc = fat_init_clusters_chain(  mt_entry,   chain );
           if (   rc != RC_OK  )
           {
           fat_free_fat_clusters_chain(  mt_entry,   chain );
           return rc;
           }
           }
           }
          
           fat_fd->fat_file_size = new_length;
          
           return RC_OK;
          }
          
          /* fat_file_truncate --
           * Truncate fat-file. If new length greater than current fat-file size -
           * do nothing. Otherwise find first cluster to free and free all clusters
           * in the chain starting from this cluster.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           * new_length - new length
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set appropriately )
           */
          int
     605  fat_file_truncate(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd,  
           uint32_t new_length
            )
          {
           int rc = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t cur_cln = 0;
           uint32_t cl_start = 0;
           uint32_t new_last_cln = FAT_UNDEFINED_VALUE;
          
          
           if (   new_length >= fat_fd->fat_file_size  )
           return rc;
          
           assert(  fat_fd->fat_file_size );
          
           cl_start = (  new_length + fs_info->vol.bpc - 1 ) >> fs_info->vol.bpc_log2;
          
           if (  (  cl_start << fs_info->vol.bpc_log2 ) >= fat_fd->fat_file_size )
           return RC_OK;
          
           if (  cl_start != 0 )
           {
           rc = fat_file_lseek(  mt_entry,   fat_fd,   cl_start - 1,   &new_last_cln );
           if (  rc != RC_OK )
           return rc;
          
           }
          
           rc = fat_file_lseek(  mt_entry,   fat_fd,   cl_start,   &cur_cln );
           if (  rc != RC_OK )
           return rc;
          
           rc = fat_free_fat_clusters_chain(  mt_entry,   cur_cln );
           if (  rc != RC_OK )
           return rc;
          
           if (  cl_start != 0 )
           {
           rc = fat_set_fat_cluster(  mt_entry,   new_last_cln,   FAT_GENFAT_EOC );
           if (   rc != RC_OK  )
           return rc;
           fat_fd->map.file_cln = cl_start - 1;
           fat_fd->map.disk_cln = new_last_cln;
           fat_fd->map.last_cln = new_last_cln;
           }
           return RC_OK;
          }
          
          /* fat_file_ioctl --
           * F_CLU_NUM:
           * make mapping between serial number of the cluster in fat-file and
           * its real number on the volume
           *
           * PARAMETERS:
           * fat_fd - fat-file descriptor
           * mt_entry - mount table entry
           * cmd - command
           * ...
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured and errno set appropriately
           */
          int
     671  fat_file_ioctl(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd,  
           int cmd,  
           ... )
          {
           int rc = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t cur_cln = 0;
           uint32_t cl_start = 0;
           uint32_t pos = 0;
           uint32_t *ret;
           va_list ap;
          
           va_start(  ap,   cmd );
          
           switch (  cmd )
           {
           case F_CLU_NUM:
           pos = va_arg(  ap,   uint32_t  );
           ret = va_arg(  ap,   uint32_t * );
          
           /* sanity check */
           if (   pos >= fat_fd->fat_file_size  ) {
           va_end(  ap );
           rtems_set_errno_and_return_minus_one(   EIO  );
           }
          
           if (  (  FAT_FD_OF_ROOT_DIR(  fat_fd ) ) &&
           (  fs_info->vol.type & (  FAT_FAT12 | FAT_FAT16 ) ) )
           {
           /* cluster 0 (  zero ) reserved for root dir */
           *ret = 0;
           rc = RC_OK;
           break;
           }
          
           cl_start = pos >> fs_info->vol.bpc_log2;
          
           rc = fat_file_lseek(  mt_entry,   fat_fd,   cl_start,   &cur_cln );
           if (   rc != RC_OK  )
           break;
          
           *ret = cur_cln;
           break;
          
           default:
           errno = EINVAL;
           rc = -1;
           break;
           }
           va_end(  ap );
           return rc;
          }
          
          /* fat_file_mark_removed --
           * Remove the fat-file descriptor from "valid" hash table,   insert it
           * into "removed-but-still-open" hash table and set up "removed" bit.
           *
           * PARAMETERS:
           * fat_fd - fat-file descriptor
           * mt_entry - mount table entry
           *
           * RETURNS:
           * None
           */
          void
     738  fat_file_mark_removed(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd
            )
          {
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t key = 0;
          
           key = fat_construct_key(  mt_entry,   &fat_fd->dir_pos.sname );
          
           _hash_delete(  fs_info->vhash,   key,   fat_fd->ino,   fat_fd );
          
           _hash_insert(  fs_info->rhash,   key,   fat_fd->ino,   fat_fd );
          
           fat_fd->flags |= FAT_FILE_REMOVED;
          }
          
          /* fat_file_datasync --
           * Synchronize fat-file - flush all buffered data to the media.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured and errno set appropriately
           */
          int
     766  fat_file_datasync(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd
            )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t cur_cln = fat_fd->cln;
           rtems_bdbuf_buffer *block = NULL;
           uint32_t sec = 0;
           uint32_t i = 0;
          
           if (  fat_fd->fat_file_size == 0 )
           return RC_OK;
          
           /*
           * we can use only one bdbuf :(   and we also know that cache is useless
           * for sync operation,   so don't use it
           */
           rc = fat_buf_release(  fs_info );
           if (  rc != RC_OK )
           return rc;
          
           /* for each cluster of the file ... */
           while (  (  cur_cln & fs_info->vol.mask ) < fs_info->vol.eoc_val )
           {
           sec = fat_cluster_num_to_sector_num(  mt_entry,   cur_cln );
           /* for each sector in cluster ... */
           for (   i = 0; i < fs_info->vol.spc; i++  )
           {
           /* ... sync it */
           sc = rtems_bdbuf_read(  fs_info->vol.dev,   (  sec + i ),   &block );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(   EIO  );
          
           sc = rtems_bdbuf_sync(  block );
           if (   sc != RTEMS_SUCCESSFUL  )
           rtems_set_errno_and_return_minus_one(   EIO  );
           }
          
           rc = fat_get_fat_cluster(  mt_entry,   cur_cln,   &cur_cln );
           if (   rc != RC_OK  )
           return rc;
           }
           return rc;
          }
          
          /* fat_file_size --
           * Calculate fat-file size - fat-file is nothing that clusters chain,   so
           * go through all clusters in the chain and count it. Only
           * special case is root directory for FAT12/16 volumes.
           * This function is used only for directories which are fat-files with
           * non-zero length,   hence 'fat_fd->cln' always contains valid data.
           * Calculated size is stored in 'fat_file_size' field of fat-file
           * descriptor.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set appropriately )
           */
          int
     831  fat_file_size(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd
            )
          {
           int rc = RC_OK;
           fat_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t cur_cln = fat_fd->cln;
           uint32_t save_cln = 0;
          
           /* Have we requested root dir size for FAT12/16? */
           if (  (  FAT_FD_OF_ROOT_DIR(  fat_fd ) ) &&
           (  fs_info->vol.type & (  FAT_FAT12 | FAT_FAT16 ) ) )
           {
           fat_fd->fat_file_size = fs_info->vol.rdir_size;
           return rc;
           }
          
           fat_fd->fat_file_size = 0;
          
           while (  (  cur_cln & fs_info->vol.mask ) < fs_info->vol.eoc_val )
           {
           save_cln = cur_cln;
           rc = fat_get_fat_cluster(  mt_entry,   cur_cln,   &cur_cln );
           if (   rc != RC_OK  )
           return rc;
          
           fat_fd->fat_file_size += fs_info->vol.bpc;
           }
           fat_fd->map.last_cln = save_cln;
           return rc;
          }
          
          /* hash support routines */
          
          /* _hash_insert --
           * Insert elemnt into hash based on key 'key1'
           *
           * PARAMETERS:
           * hash - hash element will be inserted into
           * key1 - key on which insertion is based on
           * key2 - not used during insertion
           * el - element to insert
           *
           * RETURNS:
           * None
           */
          static inline void
     879  _hash_insert(  rtems_chain_control *hash,   uint32_t key1,   uint32_t key2,  
           fat_file_fd_t *el )
          {
           rtems_chain_append(  (  hash ) + (  (  key1 ) % FAT_HASH_MODULE ),   &(  el )->link );
          }
          
          
          /* _hash_delete --
           * Remove element from hash
           *
           * PARAMETERS:
           * hash - hash element will be removed from
           * key1 - not used
           * key2 - not used
           * el - element to delete
           *
           * RETURNS:
           * None
           */
          static inline void
     899  _hash_delete(  rtems_chain_control *hash,   uint32_t key1,   uint32_t key2,  
           fat_file_fd_t *el )
          {
           rtems_chain_extract(  &(  el )->link );
          }
          
          /* _hash_search --
           * Search element in hash. If both keys match pointer to found element
           * is returned
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * hash - hash element will be removed from
           * key1 - search key
           * key2 - search key
           * ret - placeholder for result
           *
           * RETURNS:
           * 0 and pointer to found element on success,   -1 otherwise
           */
          static inline int
     920  _hash_search(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           rtems_chain_control *hash,  
           uint32_t key1,  
           uint32_t key2,  
           fat_file_fd_t **ret
            )
          {
           uint32_t mod = (  key1 ) % FAT_HASH_MODULE;
           rtems_chain_node *the_node = (  (  rtems_chain_control * )(  (  hash ) + mod ) )->first;
          
           for (   ; !rtems_chain_is_tail(  (  hash ) + mod,   the_node ) ;  )
           {
           fat_file_fd_t *ffd = (  fat_file_fd_t * )the_node;
           uint32_t ck = fat_construct_key(  mt_entry,   &ffd->dir_pos.sname );
          
           if (   (  key1 ) == ck )
           {
           if (   (  (  key2 ) == 0 ) || (  (  key2 ) == ffd->ino )  )
           {
           *ret = (  void * )the_node;
           return 0;
           }
           }
           the_node = the_node->next;
           }
           return -1;
          }
          
          static off_t
     950  fat_file_lseek(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd,  
           uint32_t file_cln,  
           uint32_t *disk_cln
            )
          {
           int rc = RC_OK;
          
           if (  file_cln == fat_fd->map.file_cln )
           *disk_cln = fat_fd->map.disk_cln;
           else
           {
           uint32_t cur_cln;
           uint32_t count;
           uint32_t i;
          
           if (  file_cln > fat_fd->map.file_cln )
           {
           cur_cln = fat_fd->map.disk_cln;
           count = file_cln - fat_fd->map.file_cln;
           }
           else
           {
           cur_cln = fat_fd->cln;
           count = file_cln;
           }
          
           /* skip over the clusters */
           for (  i = 0; i < count; i++ )
           {
           rc = fat_get_fat_cluster(  mt_entry,   cur_cln,   &cur_cln );
           if (   rc != RC_OK  )
           return rc;
           }
          
           /* update cache */
           fat_fd->map.file_cln = file_cln;
           fat_fd->map.disk_cln = cur_cln;
          
           *disk_cln = cur_cln;
           }
           return RC_OK;
          }

libfs/src/dosfs/msdos_conv.c

       1  /*
           * Adaptation of NetBSD code for RTEMS by Victor V. Vengerov <vvv@oktet.ru>
           */
          /* $NetBSD: msdosfs_conv.c,  v 1.10 1994/12/27 18:36:24 mycroft Exp $ */
          /*
           * Written by Paul Popelka (  paulp@uts.amdahl.com )
           *
           * You can do anything you want with this software,   just don't say you wrote
           * it,   and don't remove this notice.
           *
           * This software is provided "as is".
           *
           * The author supplies this software to be publicly redistributed on the
           * understanding that the author is not responsible for the correct
           * functioning of this software in any circumstances and is not liable for
           * any damages caused by this software.
           *
           * October 1992
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include "msdos.h"
          
          /* #define SECONDSPERDAY (  24 * 60 * 60 ) */
          #define SECONDSPERDAY (  (  uint32_t ) 86400 )
          
          /*
           * Days in each month in a regular year.
           */
          static uint16_t regyear[] = {
           31,   28,   31,   30,   31,   30,  
           31,   31,   30,   31,   30,   31
          };
          
          /*
           * Days in each month in a leap year.
           */
          static uint16_t leapyear[] = {
           31,   29,   31,   30,   31,   30,  
           31,   31,   30,   31,   30,   31
          };
          
          /*
           * Variables used to remember parts of the last time conversion. Maybe we
           * can avoid a full conversion.
           */
          static uint32_t lasttime;
          static uint32_t lastday;
          static uint16_t lastddate;
          static uint16_t lastdtime;
          
          /*
           * Convert the unix version of time to dos's idea of time to be used in
           * file timestamps. The passed in unix time is assumed to be in GMT.
           */
          void
      61  msdos_date_unix2dos(  unsigned int t,   uint16_t *ddp,  
           uint16_t *dtp )
          {
           uint32_t days;
           uint32_t inc;
           uint32_t year;
           uint32_t month;
           uint16_t *months;
          
           /*
           * If the time from the last conversion is the same as now,   then
           * skip the computations and use the saved result.
           */
           if (  lasttime != t ) {
           lasttime = t;
           lastdtime = (  (  (  t % 60 ) >> 1 ) << MSDOS_DT_2SECONDS_SHIFT )
           + (  (  (  t / 60 ) % 60 ) << MSDOS_DT_MINUTES_SHIFT )
           + (  (  (  t / 3600 ) % 24 ) << MSDOS_DT_HOURS_SHIFT );
          
           /*
           * If the number of days since 1970 is the same as the last
           * time we did the computation then skip all this leap year
           * and month stuff.
           */
           days = t / (  SECONDSPERDAY );
           if (  days != lastday ) {
           lastday = days;
           for (  year = 1970;; year++ ) {
           inc = year & 0x03 ? 365 : 366;
           if (  days < inc )
           break;
           days -= inc;
           }
           months = year & 0x03 ? regyear : leapyear;
           for (  month = 0; month < 12; month++ ) {
           if (  days < months[month] )
           break;
           days -= months[month];
           }
           lastddate = (  (  days + 1 ) << MSDOS_DD_DAY_SHIFT )
           + (  (  month + 1 ) << MSDOS_DD_MONTH_SHIFT );
           /*
           * Remember dos's idea of time is relative to 1980.
           * unix's is relative to 1970. If somehow we get a
           * time before 1980 then don't give totally crazy
           * results.
           */
           if (  year > 1980 )
           lastddate += (  year - 1980 ) <<
           MSDOS_DD_YEAR_SHIFT;
           }
           }
           *dtp = lastdtime;
           *ddp = lastddate;
          }
          
          /*
           * The number of days between Jan 1,   1970 and Jan 1,   1980. In that
           * interval there were 8 regular years and 2 leap years.
           */
          /* #define DAYSTO1980 (  (  8 * 365 ) + (  2 * 366 ) ) */
          #define DAYSTO1980 (  (  uint32_t ) 3652 )
          
          static uint16_t lastdosdate;
          static uint32_t lastseconds;
          
          /*
           * Convert from dos' idea of time to unix'. This will probably only be
           * called from the stat(   ),   and fstat(   ) system calls and so probably need
           * not be too efficient.
           */
          unsigned int
     133  msdos_date_dos2unix(  unsigned int dd,   unsigned int dt )
          {
           uint32_t seconds;
           uint32_t m,   month;
           uint32_t y,   year;
           uint32_t days;
           uint16_t *months;
          
           seconds = (  (  dt & MSDOS_DT_2SECONDS_MASK ) >> MSDOS_DT_2SECONDS_SHIFT )
           + (  (  dt & MSDOS_DT_MINUTES_MASK ) >> MSDOS_DT_MINUTES_SHIFT ) * 60
           + (  (  dt & MSDOS_DT_HOURS_MASK ) >> MSDOS_DT_HOURS_SHIFT ) * 3600;
           /*
           * If the year,   month,   and day from the last conversion are the
           * same then use the saved value.
           */
           if (  lastdosdate != dd ) {
           lastdosdate = dd;
           days = 0;
           year = (  dd & MSDOS_DD_YEAR_MASK ) >> MSDOS_DD_YEAR_SHIFT;
           for (  y = 0; y < year; y++ )
           days += y & 0x03 ? 365 : 366;
           months = year & 0x03 ? regyear : leapyear;
           /*
           * Prevent going from 0 to 0xffffffff in the following
           * loop.
           */
           month = (  dd & MSDOS_DD_MONTH_MASK ) >> MSDOS_DD_MONTH_SHIFT;
           if (  month == 0 ) {
           month = 1;
           }
           for (  m = 0; m < month - 1; m++ )
           days += months[m];
           days += (  (  dd & MSDOS_DD_DAY_MASK ) >> MSDOS_DD_DAY_SHIFT ) - 1;
           lastseconds = (  days + DAYSTO1980 ) * SECONDSPERDAY;
           }
           return seconds + lastseconds;
          }
          
          static const uint8_t msdos_map[] = {
           0,   0,   0,   0,   0,   0,   0,   0,   /* 00-07 */
           0,   0,   0,   0,   0,   0,   0,   0,   /* 08-0f */
           0,   0,   0,   0,   0,   0,   0,   0,   /* 10-17 */
           0,   0,   0,   0,   0,   0,   0,   0,   /* 18-1f */
           0,   '!',   0,   '#',   '$',   '%',   '&',   '\'',   /* 20-27 */
           '(  ',   ' )',   0,   '+',   0,   '-',   0,   0,   /* 28-2f */
           '0',   '1',   '2',   '3',   '4',   '5',   '6',   '7',   /* 30-37 */
           '8',   '9',   0,   0,   0,   0,   0,   0,   /* 38-3f */
           '@',   'A',   'B',   'C',   'D',   'E',   'F',   'G',   /* 40-47 */
           'H',   'I',   'J',   'K',   'L',   'M',   'N',   'O',   /* 48-4f */
           'P',   'Q',   'R',   'S',   'T',   'U',   'V',   'W',   /* 50-57 */
           'X',   'Y',   'Z',   0,   0,   0,   '^',   '_',   /* 58-5f */
           '`',   'A',   'B',   'C',   'D',   'E',   'F',   'G',   /* 60-67 */
           'H',   'I',   'J',   'K',   'L',   'M',   'N',   'O',   /* 68-6f */
           'P',   'Q',   'R',   'S',   'T',   'U',   'V',   'W',   /* 70-77 */
           'X',   'Y',   'Z',   '{',   0,   '}',   '~',   0,   /* 78-7f */
           0,   0,   0,   0,   0,   0,   0,   0,   /* 80-87 */
           0,   0,   0,   0,   0,   0,   0,   0,   /* 88-8f */
           0,   0,   0,   0,   0,   0,   0,   0,   /* 90-97 */
           0,   0,   0,   0,   0,   0,   0,   0,   /* 98-9f */
           0,   0xad,   0xbd,   0x9c,   0xcf,   0xbe,   0xdd,   0xf5,   /* a0-a7 */
           0xf9,   0xb8,   0xa6,   0xae,   0xaa,   0xf0,   0xa9,   0xee,   /* a8-af */
           0xf8,   0xf1,   0xfd,   0xfc,   0xef,   0xe6,   0xf4,   0xfa,   /* b0-b7 */
           0xf7,   0xfb,   0xa7,   0xaf,   0xac,   0xab,   0xf3,   0xa8,   /* b8-bf */
           0xb7,   0xb5,   0xb6,   0xc7,   0x8e,   0x8f,   0x92,   0x80,   /* c0-c7 */
           0xd4,   0x90,   0xd2,   0xd3,   0xde,   0xd6,   0xd7,   0xd8,   /* c8-cf */
           0xd1,   0xa5,   0xe3,   0xe0,   0xe2,   0xe5,   0x99,   0x9e,   /* d0-d7 */
           0x9d,   0xeb,   0xe9,   0xea,   0x9a,   0xed,   0xe8,   0xe1,   /* d8-df */
           0xb7,   0xb5,   0xb6,   0xc7,   0x8e,   0x8f,   0x92,   0x80,   /* e0-e7 */
           0xd4,   0x90,   0xd2,   0xd3,   0xde,   0xd6,   0xd7,   0xd8,   /* e8-ef */
           0xd1,   0xa5,   0xe3,   0xe0,   0xe2,   0xe5,   0x99,   0xf6,   /* f0-f7 */
           0x9d,   0xeb,   0xe9,   0xea,   0x9a,   0xed,   0xe8,   0x98,   /* f8-ff */
          #if OLD_TABLE
          /* 00 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* 08 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* 10 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* 18 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* 20 */ 0x00,   0x21,   0x00,   0x23,   0x24,   0x25,   0x26,   0x27,   /* !"#$%&' */
          /* 28 */ 0x28,   0x29,   0x00,   0x00,   0x00,   0x2D,   0x2E,   0x00,   /* (   )*+,  -./ */
     211  /* 30 */ 0x30,   0x31,   0x32,   0x33,   0x34,   0x35,   0x36,   0x37,   /* 01234567 */
          /* 38 */ 0x38,   0x39,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   /* 89:;<=>? */
          /* 40 */ 0x40,   0x41,   0x42,   0x43,   0x44,   0x45,   0x46,   0x47,   /* @ABCDEFG */
          /* 48 */ 0x48,   0x49,   0x4A,   0x4B,   0x4C,   0x4D,   0x4E,   0x4F,   /* HIJKLMNO */
          /* 50 */ 0x50,   0x51,   0x52,   0x53,   0x54,   0x55,   0x56,   0x57,   /* PQRSTUVW */
          /* 58 */ 0x58,   0x59,   0x5A,   0x5B,   0x5C,   0x00,   0x5E,   0x5F,   /* XYZ[\]^_ */
          /* 60 */ 0x60,   0x41,   0x42,   0x43,   0x44,   0x45,   0x46,   0x47,   /* `abcdefg */
          /* 68 */ 0x48,   0x49,   0x4A,   0x4B,   0x4C,   0x4D,   0x4E,   0x4F,   /* hijklmno */
          /* 70 */ 0x50,   0x51,   0x52,   0x53,   0x54,   0x55,   0x56,   0x57,   /* pqrstuvw */
          /* 78 */ 0x58,   0x59,   0x5A,   0x5B,   0x7C,   0x00,   0x7E,   0x00,   /* xyz{|}~ */
          /* 80 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* 88 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* 90 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* 98 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* A0 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* A8 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* B0 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* B8 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* C0 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* C8 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* D0 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* D8 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* E0 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* E8 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* F0 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          /* F8 */ 0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
          #endif
          };
          /*
           * Convert a unix filename to a DOS filename. Return -1 if wrong name is
           * supplied.
           */
          int
          msdos_filename_unix2dos(  const char *un,   int unlen,   char *dn )
          {
           int i;
           uint8_t c;
          
           /*
           * Fill the dos filename string with blanks. These are DOS's pad
           * characters.
           */
           for (  i = 0; i <= 10; i++ )
           dn[i] = ' ';
          
           /*
           * The filenames "." and ".." are handled specially,   since they
           * don't follow dos filename rules.
           */
           if (  un[0] == '.' && unlen == 1 ) {
           dn[0] = '.';
           return 0;
           }
           if (  un[0] == '.' && un[1] == '.' && unlen == 2 ) {
           dn[0] = '.';
           dn[1] = '.';
           return 0;
           }
          
           /*
           * Remove any dots from the start of a file name.
           */
           while (  unlen && (  *un == '.' ) ) {
           un++;
           unlen--;
           }
          
           /*
           * Copy the unix filename into the dos filename string upto the end
           * of string,   a '.',   or 8 characters. Whichever happens first stops
           * us. This forms the name portion of the dos filename. Fold to
           * upper case.
           */
           for (  i = 0; i <= 7 && unlen && (  c = *un ) && c != '.'; i++ ) {
           if (  msdos_map[c] == 0 )
           break;
           dn[i] = msdos_map[c];
           un++;
           unlen--;
           }
          
           /*
           * Strip any further characters up to a '.' or the end of the
           * string.
           */
           while (  unlen && (  c = *un ) ) {
           un++;
           unlen--;
           /* Make sure we've skipped over the dot before stopping. */
           if (  c == '.' )
           break;
           }
          
           /*
           * Copy in the extension part of the name,   if any. Force to upper
           * case. Note that the extension is allowed to contain '.'s.
           * Filenames in this form are probably inaccessable under dos.
           */
           for (  i = 8; i <= 10 && unlen && (  c = *un ); i++ ) {
           if (  msdos_map[c] == 0 )
           break;
           dn[i] = msdos_map[c];
           un++;
           unlen--;
           }
           return 0;
          }

libfs/src/dosfs/msdos_create.c

       1  /*
           * Routine to create a new MSDOS filesystem node
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_create.c,  v 1.18 2010/07/04 14:53:46 joel Exp $
           *
           */
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <rtems/libio_.h>
          #include <time.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          #include "msdos.h"
          
          /* msdos_creat_node --
           * Create a new node. Determine if the name is a long name. If long we to
           * scan the directory to create a short entry.
           *
           *
          
          
          
           * If a new node is file,   FAT 32 Bytes Directory
           * Entry Structure is initialized,   free space is found in parent
           * directory and structure is written to the disk. In case of directory,  
           * all above steps present and also new cluster is allocated for a
           * new directory and dot and dotdot nodes are created in alloceted cluster.
           *
           * PARAMETERS:
           * parent_loc - parent (  directory we are going to create node in )
           * type - new node type (  file or directory )
           * name - new node name
           * mode - mode
           * link_info - fs_info of existing node for a pseudo "hard-link"
           * (  see msdos_file.c,   msdos_link for documentation )
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set appropriately ).
           *
           */
          int
      58  msdos_creat_node(  rtems_filesystem_location_info_t *parent_loc,  
           msdos_node_type_t type,  
           const char *name,  
           int name_len,  
           mode_t mode,  
           const fat_file_fd_t *link_fd )
          {
           int rc = RC_OK;
           ssize_t ret = 0;
           msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
           fat_file_fd_t *parent_fat_fd = parent_loc->node_access;
           fat_file_fd_t *fat_fd = NULL;
           time_t time_ret = 0;
           uint16_t time_val = 0;
           uint16_t date = 0;
           fat_dir_pos_t dir_pos;
           msdos_name_type_t name_type;
           char short_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
           char dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
           char link_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
           uint32_t sec = 0;
           uint32_t byte = 0;
          
           fat_dir_pos_init(  &dir_pos );
          
           memset(  short_node,   0,   MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE );
           memset(  dot_dotdot,   0,   MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2 );
          
           name_type = msdos_long_to_short (  name,   name_len,  
           MSDOS_DIR_NAME(  short_node ),  
           MSDOS_NAME_MAX );
          
           /* fill reserved field */
           *MSDOS_DIR_NT_RES(  short_node ) = MSDOS_RES_NT_VALUE;
          
           /* set up last write date and time */
           time_ret = time(  NULL );
           if (   time_ret == -1  )
           return -1;
          
           msdos_date_unix2dos(  time_ret,   &date,   &time_val );
           *MSDOS_DIR_WRITE_TIME(  short_node ) = CT_LE_W(  time_val );
           *MSDOS_DIR_WRITE_DATE(  short_node ) = CT_LE_W(  date );
          
           /* initialize directory/file size */
           *MSDOS_DIR_FILE_SIZE(  short_node ) = MSDOS_INIT_DIR_SIZE;
          
           if (  type == MSDOS_DIRECTORY ) {
           *MSDOS_DIR_ATTR(  short_node ) |= MSDOS_ATTR_DIRECTORY;
           }
           else if (  type == MSDOS_HARD_LINK ) {
           /*
           * when we establish a (  temporary ) hard link,  
           * we must copy some information from the original
           * node to the newly created
           */
           /*
           * read the original directory entry
           */
           sec = fat_cluster_num_to_sector_num(  parent_loc->mt_entry,  
           link_fd->dir_pos.sname.cln );
           sec += (  link_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2 );
           byte = (  link_fd->dir_pos.sname.ofs & (  fs_info->fat.vol.bps - 1 ) );
          
           ret = _fat_block_read(  parent_loc->mt_entry,  
           sec,   byte,   MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,  
           link_node );
           if (  ret < 0 ) {
           return -1;
           }
           /*
           * copy various attributes
           */
           *MSDOS_DIR_ATTR(  short_node ) =*MSDOS_DIR_ATTR(  link_node );
           *MSDOS_DIR_CRT_TIME_TENTH(  short_node )=*MSDOS_DIR_CRT_TIME_TENTH(  link_node );
           *MSDOS_DIR_CRT_TIME(  short_node ) =*MSDOS_DIR_CRT_TIME(  link_node );
           *MSDOS_DIR_CRT_DATE(  short_node ) =*MSDOS_DIR_CRT_DATE(  link_node );
          
           /*
           * copy/set "file size",   "first cluster"
           */
           *MSDOS_DIR_FILE_SIZE(  short_node ) =*MSDOS_DIR_FILE_SIZE(  link_node );
          
           *MSDOS_DIR_FIRST_CLUSTER_LOW(  short_node ) =
           *MSDOS_DIR_FIRST_CLUSTER_LOW(  link_node );
           *MSDOS_DIR_FIRST_CLUSTER_HI(  short_node ) =
           *MSDOS_DIR_FIRST_CLUSTER_HI(  link_node );
           /*
           * set "archive bit" due to changes
           */
           *MSDOS_DIR_ATTR(  short_node ) |= MSDOS_ATTR_ARCHIVE;
           /*
           * set "last access" date to today
           */
           *MSDOS_DIR_LAST_ACCESS_DATE(  short_node ) = CT_LE_W(  date );
           }
           else { /* regular file... */
           *MSDOS_DIR_ATTR(  short_node ) |= MSDOS_ATTR_ARCHIVE;
           }
          
           /*
           * find free space in the parent directory and write new initialized
           * FAT 32 Bytes Directory Entry Structure to the disk
           */
           rc = msdos_get_name_node(  parent_loc,   true,   name,   name_len,  
           name_type,   &dir_pos,   short_node );
           if (   rc != RC_OK  )
           return rc;
          
           /*
           * if we create a new file we are done,   if directory there are more steps
           * to do
           */
           if (  type == MSDOS_DIRECTORY )
           {
           /* open new directory as fat-file */
           rc = fat_file_open(  parent_loc->mt_entry,   &dir_pos,   &fat_fd );
           if (  rc != RC_OK )
           goto err;
          
           /*
           * we opened fat-file for node we just created,   so initialize fat-file
           * descritor
           */
           fat_fd->fat_file_size = 0;
           fat_fd->fat_file_type = FAT_DIRECTORY;
           fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
          
           /*
           * dot and dotdot entries are identical to new node except the
           * names
           */
           memcpy(  DOT_NODE_P(  dot_dotdot ),   short_node,  
           MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE );
           memcpy(  DOTDOT_NODE_P(  dot_dotdot ),   short_node,  
           MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE );
           memcpy(  MSDOS_DIR_NAME(  DOT_NODE_P(  dot_dotdot ) ),   MSDOS_DOT_NAME,  
           MSDOS_NAME_MAX );
           memcpy(  MSDOS_DIR_NAME(  DOTDOT_NODE_P(  dot_dotdot ) ),   MSDOS_DOTDOT_NAME,  
           MSDOS_NAME_MAX );
          
           /* set up cluster num for dotdot entry */
           /*
           * here we can ommit FAT32 condition because for all FAT types dirs
           * right under root dir should contain 0 in dotdot entry but for
           * FAT12/16 parent_fat_fd->cluster_num always contains such value
           */
           if (  (  FAT_FD_OF_ROOT_DIR(  parent_fat_fd ) ) &&
           (  fs_info->fat.vol.type & FAT_FAT32 ) )
           {
           *MSDOS_DIR_FIRST_CLUSTER_LOW(  DOTDOT_NODE_P(  dot_dotdot ) ) = 0x0000;
           *MSDOS_DIR_FIRST_CLUSTER_HI(  DOTDOT_NODE_P(  dot_dotdot ) ) = 0x0000;
           }
           else
           {
           *MSDOS_DIR_FIRST_CLUSTER_LOW(  DOTDOT_NODE_P(  dot_dotdot ) ) =
           CT_LE_W(  (  uint16_t  )(  (  parent_fat_fd->cln ) & 0x0000FFFF ) );
           *MSDOS_DIR_FIRST_CLUSTER_HI(  DOTDOT_NODE_P(  dot_dotdot ) ) =
           CT_LE_W(  (  uint16_t  )(  (  (  parent_fat_fd->cln ) & 0xFFFF0000 )>>16 ) );
           }
          
           /*
           * write dot and dotdot entries to new fat-file: currently fat-file
           * correspondes to a new node is zero length,   so it will be extended
           * by one cluster and entries will be written
           */
           ret = fat_file_write(  parent_loc->mt_entry,   fat_fd,   0,  
           MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2,  
           (  uint8_t * )dot_dotdot );
           if (  ret < 0 )
           {
           rc = -1;
           goto error;
           }
          
           /* increment fat-file size by cluster size */
           fat_fd->fat_file_size += fs_info->fat.vol.bpc;
          
           /* set up cluster num for dot entry */
           *MSDOS_DIR_FIRST_CLUSTER_LOW(  DOT_NODE_P(  dot_dotdot ) ) =
           CT_LE_W(  (  uint16_t  )(  (  fat_fd->cln ) & 0x0000FFFF ) );
           *MSDOS_DIR_FIRST_CLUSTER_HI(  DOT_NODE_P(  dot_dotdot ) ) =
           CT_LE_W(  (  uint16_t  )(  (  (  fat_fd->cln ) & 0xFFFF0000 ) >> 16 ) );
          
           /* rewrite dot entry */
           ret = fat_file_write(  parent_loc->mt_entry,   fat_fd,   0,  
           MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,  
           (  uint8_t * )DOT_NODE_P(  dot_dotdot ) );
           if (  ret < 0 )
           {
           rc = -1;
           goto error;
           }
          
           /* write first cluster num of a new directory to disk */
           rc = msdos_set_first_cluster_num(  parent_loc->mt_entry,   fat_fd );
           if (  rc != RC_OK )
           goto error;
          
           fat_file_close(  parent_loc->mt_entry,   fat_fd );
           }
           return RC_OK;
          
          error:
           fat_file_close(  parent_loc->mt_entry,   fat_fd );
          
          err:
           /* mark the used 32bytes structure on the disk as free */
           msdos_set_first_char4file_name(  parent_loc->mt_entry,   &dir_pos,   0xE5 );
           return rc;
          }

libfs/src/dosfs/msdos_dir.c

       1  /*
           * MSDOS directory handlers implementation
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_dir.c,  v 1.20 2010/07/15 08:10:47 sh Exp $
           */
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <ctype.h>
          #include <stdlib.h>
          #include <unistd.h>
          #include <errno.h>
          #include <rtems/libio_.h>
          #include <sys/types.h>
          #include <sys/stat.h>
          
          #include <dirent.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          #include "msdos.h"
          
          /* msdos_dir_open --
           * Open fat-file which correspondes to the directory being opened and
           * set offset field of file control block to zero.
           *
           * PARAMETERS:
           * iop - file control block
           * pathname - name
           * flag - flags
           * mode - mode
           *
           * RETURNS:
           * RC_OK,   if directory opened successfully,   or -1 if error occured (  errno
           * set apropriately )
           */
          int
      48  msdos_dir_open(  rtems_libio_t *iop,   const char *pathname,   uint32_t flag,  
           uint32_t mode )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(   EIO  );
          
           rc = fat_file_reopen(  fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           iop->offset = 0;
           rtems_semaphore_release(  fs_info->vol_sema );
           return RC_OK;
          }
          
          /* msdos_dir_close --
           * Close fat-file which correspondes to the directory being closed
           *
           * PARAMETERS:
           * iop - file control block
           *
           * RETURNS:
           * RC_OK,   if directory closed successfully,   or -1 if error occured (  errno
           * set apropriately.
           */
          int
      84  msdos_dir_close(  rtems_libio_t *iop )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(   EIO  );
          
           rc = fat_file_close(  iop->pathinfo.mt_entry,   fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return RC_OK;
          }
          
          /* msdos_format_dirent_with_dot --
           * This routine convert a (  short ) MSDOS filename as present on disk
           * (  fixed 8+3 characters,   filled with blanks,   without separator dot )
           * to a "normal" format,   with between 0 and 8 name chars,  
           * a separating dot and up to 3 extension characters
           * Rules to work:
           * - copy any (  0-8 ) "name" part characters that are non-blank
           * - if an extension exists,   append a dot
           * - copy any (  0-3 ) non-blank extension characters
           * - append a '\0' (  dont count it for the rturn code
           *
           * PARAMETERS:
           * dst: pointer to destination char array (  must be big enough )
           * src: pointer to source characters
           *
           *
           * RETURNS:
           * the number of bytes (  without trailing '\0'(  written to destination
           */
          static ssize_t
     127  msdos_format_dirent_with_dot(  char *dst,  const char *src )
          {
           ssize_t len;
           int i;
           const char *src_tmp;
          
           /*
           * find last non-blank character of base name
           */
           for (  (  i = MSDOS_SHORT_BASE_LEN ,  
           src_tmp = src + MSDOS_SHORT_BASE_LEN-1 );
           (  (  i > 0 ) &&
           (  *src_tmp == ' ' ) );
           i--,  src_tmp-- )
           {};
           /*
           * copy base name to destination
           */
           src_tmp = src;
           len = i;
           while (  i-- > 0 ) {
           *dst++ = tolower(  (  unsigned char )(  *src_tmp++ ) );
           }
           /*
           * find last non-blank character of extension
           */
           for (  (  i = MSDOS_SHORT_EXT_LEN ,  
           src_tmp = src + MSDOS_SHORT_BASE_LEN+MSDOS_SHORT_EXT_LEN-1 );
           (  (  i > 0 ) &&
           (  *src_tmp == ' ' ) );
           i--,  src_tmp-- )
           {};
           /*
           * extension is not empty
           */
           if (  i > 0 ) {
           *dst++ = '.'; /* append dot */
           len += i + 1; /* extension + dot */
           src_tmp = src + MSDOS_SHORT_BASE_LEN;
           while (  i-- > 0 ) {
           *dst++ = tolower(  (  unsigned char )(  *src_tmp++ ) );
           len++;
           }
           }
           *dst = '\0'; /* terminate string */
          
           return len;
          }
          
          /* msdos_dir_read --
           * This routine will read the next directory entry based on the directory
           * offset. The offset should be equal to -n- time the size of an
           * individual dirent structure. If n is not an integer multiple of the
           * sizeof a dirent structure,   an integer division will be performed to
           * determine directory entry that will be returned in the buffer. Count
           * should reflect -m- times the sizeof dirent bytes to be placed in the
           * buffer.
           * If there are not -m- dirent elements from the current directory
           * position to the end of the exisiting file,   the remaining entries will
           * be placed in the buffer and the returned value will be equal to
           * -m actual- times the size of a directory entry.
           *
           * PARAMETERS:
           * iop - file control block
           * buffer - buffer provided by user
           * count - count of bytes to read
           *
           * RETURNS:
           * the number of bytes read on success,   or -1 if error occured (  errno
           * set apropriately ).
           */
          ssize_t
     199  msdos_dir_read(  rtems_libio_t *iop,   void *buffer,   size_t count )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
           fat_file_fd_t *tmp_fat_fd = NULL;
           struct dirent tmp_dirent;
           uint32_t start = 0;
           ssize_t ret = 0;
           uint32_t cmpltd = 0;
           uint32_t j = 0,   i = 0;
           uint32_t bts2rd = 0;
           uint32_t cur_cln = 0;
           uint32_t lfn_start = FAT_FILE_SHORT_NAME;
           uint8_t lfn_checksum = 0;
           int lfn_entries = 0;
          
           /*
           * cast start and count - protect against using sizes that are not exact
           * multiples of the -dirent- size. These could result in unexpected
           * results
           */
           start = iop->offset / sizeof(  struct dirent );
           count = (  count / sizeof(  struct dirent ) ) * sizeof(  struct dirent );
          
           /*
           * optimization: we know that root directory for FAT12/16 volumes is
           * sequential set of sectors and any cluster is sequential set of sectors
           * too,   so read such set of sectors is quick operation for low-level IO
           * layer.
           */
           bts2rd = (  FAT_FD_OF_ROOT_DIR(  fat_fd ) &&
           (  fs_info->fat.vol.type & (  FAT_FAT12 | FAT_FAT16 ) ) ) ?
           fat_fd->fat_file_size :
           fs_info->fat.vol.bpc;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           while (  count > 0 )
           {
           /*
           * fat-file is already opened by open call,   so read it
           * Always read directory fat-file from the beggining because of MSDOS
           * directories feature :(   - we should count elements currently
           * present in the directory because there may be holes : )
           */
           ret = fat_file_read(  iop->pathinfo.mt_entry,   fat_fd,   (  j * bts2rd ),  
           bts2rd,   fs_info->cl_buf );
           if (  ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           rtems_set_errno_and_return_minus_one(  EIO );
           }
          
           for (  i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE )
           {
           char* entry = (  char* ) fs_info->cl_buf + i;
          
           /*
           * Is this directory from here on empty ?
           */
           if (  (  *MSDOS_DIR_ENTRY_TYPE(  entry ) ) ==
           MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return cmpltd;
           }
          
           /* Is the directory entry empty */
           if (  (  *MSDOS_DIR_ENTRY_TYPE(  entry ) ) == MSDOS_THIS_DIR_ENTRY_EMPTY )
           continue;
          
           /* Is the directory entry empty a volume label */
           if (  (  (  *MSDOS_DIR_ATTR(  entry ) ) & MSDOS_ATTR_VOLUME_ID ) &&
           (  (  *MSDOS_DIR_ATTR(  entry ) & MSDOS_ATTR_LFN_MASK ) != MSDOS_ATTR_LFN ) )
           continue;
          
           /*
           * Check the attribute to see if the entry is for a long file
           * name.
           */
           if (  (  *MSDOS_DIR_ATTR(  entry ) & MSDOS_ATTR_LFN_MASK ) ==
           MSDOS_ATTR_LFN )
           {
           int o;
           char* p;
           int q;
          
           /*
           * Is this is the first entry of a LFN ?
           */
           if (  lfn_start == FAT_FILE_SHORT_NAME )
           {
           /*
           * The first entry must have the last long entry flag set.
           */
           if (  (  *MSDOS_DIR_ENTRY_TYPE(  entry ) &
           MSDOS_LAST_LONG_ENTRY ) == 0 )
           continue;
          
           /*
           * Remember the start location of the long file name.
           */
           lfn_start =
           (  (  j * bts2rd ) + i ) / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
          
           /*
           * Get the number of entries so we can count down and
           * also the checksum of the short entry.
           */
           lfn_entries = (  *MSDOS_DIR_ENTRY_TYPE(  entry ) &
           MSDOS_LAST_LONG_ENTRY_MASK );
           lfn_checksum = *MSDOS_DIR_LFN_CHECKSUM(  entry );
           memset (  tmp_dirent.d_name,   0,   sizeof(  tmp_dirent.d_name ) );
           }
          
           /*
           * If the entry number or the check sum do not match
           * forget this series of long directory entries. These could
           * be orphaned entries depending on the history of the
           * disk.
           */
           if (  (  lfn_entries != (  *MSDOS_DIR_ENTRY_TYPE(  entry ) &
           MSDOS_LAST_LONG_ENTRY_MASK ) ) ||
           (  lfn_checksum != *MSDOS_DIR_LFN_CHECKSUM(  entry ) ) )
           {
           lfn_start = FAT_FILE_SHORT_NAME;
           continue;
           }
          
           /*
           * Extract the file name into the directory entry. The data is
           * stored in UNICODE characters (  16bit ). No translation is
           * currently supported.
           *
           * The DOS maximum length is 255 characters without the
           * trailing nul character. We need to range check the length to
           * fit in the directory entry name field.
           */
          
           lfn_entries--;
           p = entry + 1;
           o = lfn_entries * MSDOS_LFN_LEN_PER_ENTRY;
          
           for (  q = 0; q < MSDOS_LFN_LEN_PER_ENTRY; q++ )
           {
           if (  o >= (  sizeof(  tmp_dirent.d_name ) - 1 ) )
           break;
          
           tmp_dirent.d_name[o++] = *p;
          
           if (  *p == '\0' )
           break;
          
           switch (  q )
           {
           case 4:
           p += 5;
           break;
           case 10:
           p += 4;
           break;
           default:
           p += 2;
           break;
           }
           }
           }
           else
           {
           fat_dir_pos_t dir_pos;
          
           /*
           * Skip active entries until get the entry to start from.
           */
           if (  start )
           {
           lfn_start = FAT_FILE_SHORT_NAME;
           start--;
           continue;
           }
          
           /*
           * Move the entry to the return buffer
           *
           * unfortunately there is no method to extract ino except to
           * open fat-file descriptor :(   ... so,   open it
           */
          
           /* get number of cluster we are working with */
           rc = fat_file_ioctl(  iop->pathinfo.mt_entry,   fat_fd,   F_CLU_NUM,  
           j * bts2rd,   &cur_cln );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           fat_dir_pos_init(  &dir_pos );
           dir_pos.sname.cln = cur_cln;
           dir_pos.sname.ofs = i;
           rc = fat_file_open(  iop->pathinfo.mt_entry,   &dir_pos,   &tmp_fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           /* fill in dirent structure */
           /* XXX: from what and in what d_off should be computed ?! */
           tmp_dirent.d_off = start + cmpltd;
           tmp_dirent.d_reclen = sizeof(  struct dirent );
           tmp_dirent.d_ino = tmp_fat_fd->ino;
          
           /*
           * If a long file name check if the correct number of
           * entries have been found and if the checksum is correct.
           * If not return the short file name.
           */
           if (  lfn_start != FAT_FILE_SHORT_NAME )
           {
           uint8_t cs = 0;
           uint8_t* p = (  uint8_t* ) entry;
           int i;
          
           for (  i = 0; i < 11; i++,   p++ )
           cs = (  (  cs & 1 ) ? 0x80 : 0 ) + (  cs >> 1 ) + *p;
          
           if (  lfn_entries || (  lfn_checksum != cs ) )
           lfn_start = FAT_FILE_SHORT_NAME;
           }
          
           if (  lfn_start == FAT_FILE_SHORT_NAME )
           {
           /*
           * convert dir entry from fixed 8+3 format (  without dot )
           * to 0..8 + 1dot + 0..3 format
           */
           tmp_dirent.d_namlen = msdos_format_dirent_with_dot(  
           tmp_dirent.d_name,   entry ); /* src text */
           }
           else
           {
           tmp_dirent.d_namlen = strlen(  tmp_dirent.d_name );
           }
          
           memcpy(  buffer + cmpltd,   &tmp_dirent,   sizeof(  struct dirent ) );
          
           iop->offset = iop->offset + sizeof(  struct dirent );
           cmpltd += (  sizeof(  struct dirent ) );
           count -= (  sizeof(  struct dirent ) );
          
           /* inode number extracted,   close fat-file */
           rc = fat_file_close(  iop->pathinfo.mt_entry,   tmp_fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
           }
          
           if (  count <= 0 )
           break;
           }
           j++;
           }
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return cmpltd;
          }
          
          /* msdos_dir_write --
           * no write for directory
           */
          
          /* msdos_dir_lseek --
           *
           * This routine will behave in one of three ways based on the state of
           * argument whence. Based on the state of its value the offset argument will
           * be interpreted using one of the following methods:
           *
           * SEEK_SET - offset is the absolute byte offset from the start of the
           * logical start of the dirent sequence that represents the
           * directory
           * SEEK_CUR - offset is used as the relative byte offset from the current
           * directory position index held in the iop structure
           * SEEK_END - N/A --> This will cause an assert.
           *
           * PARAMETERS:
           * iop - file control block
           * offset - offset
           * whence - predefine directive
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno
           * set apropriately ).
           */
          rtems_off64_t
     501  msdos_dir_lseek(  rtems_libio_t *iop,   rtems_off64_t offset,   int whence )
          {
           switch (  whence )
           {
           case SEEK_SET:
           case SEEK_CUR:
           break;
           /*
           * Movement past the end of the directory via lseek is not a
           * permitted operation
           */
           case SEEK_END:
           default:
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           break;
           }
           return RC_OK;
          }
          
          /* msdos_dir_stat --
           *
           * This routine will obtain the following information concerning the current
           * directory:
           * st_dev device id
           * st_ino node serial number : )
           * st_mode mode extracted from the node
           * st_size total size in bytes
           * st_blksize blocksize for filesystem I/O
           * st_blocks number of blocks allocated
           * stat_mtime time of last modification
           *
           * PARAMETERS:
           * loc - this directory
           * buf - stat buffer provided by user
           *
           * RETURNS:
           * RC_OK and filled stat buffer on success,   or -1 if error occured (  errno
           * set apropriately ).
           */
          int
     541  msdos_dir_stat(  
           rtems_filesystem_location_info_t *loc,  
           struct stat *buf
            )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
           fat_file_fd_t *fat_fd = loc->node_access;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           buf->st_dev = fs_info->fat.vol.dev;
           buf->st_ino = fat_fd->ino;
           buf->st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
           buf->st_rdev = 0ll;
           buf->st_size = fat_fd->fat_file_size;
           buf->st_blocks = fat_fd->fat_file_size >> FAT_SECTOR512_BITS;
           buf->st_blksize = fs_info->fat.vol.bps;
           buf->st_mtime = fat_fd->mtime;
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return RC_OK;
          }
          
          /* msdos_dir_truncate --
           * No truncate for directory.
           *
           * PARAMETERS:
           *
           * RETURNS:
           *
           */
          
          /* msdos_dir_sync --
           * The following routine does a syncronization on a MSDOS directory node.
           * DIR_WrtTime,   DIR_WrtDate and DIR_fileSize fields of 32 Bytes Directory
           * Entry Structure should not be updated for directories,   so only call
           * to corresponding fat-file routine.
           *
           * PARAMETERS:
           * iop - file control block
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set apropriately ).
           */
          int
     590  msdos_dir_sync(  rtems_libio_t *iop )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           rc = fat_file_datasync(  iop->pathinfo.mt_entry,   fat_fd );
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
          }
          
          /* msdos_dir_chmod --
           * Change the attributes of the directory. This currently does
           * nothing and returns no error.
           *
           * PARAMETERS:
           * pathloc - node description
           * mode - the new mode
           *
           * RETURNS:
           * RC_OK always
           */
          int
     620  msdos_dir_chmod(  rtems_filesystem_location_info_t *pathloc,  
           mode_t mode )
          {
           return RC_OK;
          }
          
          /* msdos_dir_rmnod --
           * Remove directory node.
           *
           * Check that this directory node is not opened as fat-file,   is empty and
           * not filesystem root node. If all this conditions met then delete.
           *
           * PARAMETERS:
           * pathloc - node description
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set apropriately ).
           */
          int
     639  msdos_dir_rmnod(  rtems_filesystem_location_info_t *parent_pathloc,  
           rtems_filesystem_location_info_t *pathloc )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
           fat_file_fd_t *fat_fd = pathloc->node_access;
           bool is_empty = false;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           /*
           * We deny attempts to delete open directory (  if directory is current
           * directory we assume it is open one )
           */
           if (  fat_fd->links_num > 1 )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           rtems_set_errno_and_return_minus_one(  EBUSY );
           }
          
           /*
           * You cannot remove a node that still has children
           */
           rc = msdos_dir_is_empty(  pathloc->mt_entry,   fat_fd,   &is_empty );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           if (  !is_empty )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           rtems_set_errno_and_return_minus_one(  ENOTEMPTY );
           }
          
           /*
           * You cannot remove the file system root node.
           */
           if (  pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           rtems_set_errno_and_return_minus_one(  EBUSY );
           }
          
           /*
           * You cannot remove a mountpoint.
           * not used - mount(   ) not implemenetd yet.
           */
          
           /* mark file removed */
           rc = msdos_set_first_char4file_name(  pathloc->mt_entry,   &fat_fd->dir_pos,  
           MSDOS_THIS_DIR_ENTRY_EMPTY );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           fat_file_mark_removed(  pathloc->mt_entry,   fat_fd );
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
          }

libfs/src/dosfs/msdos_eval.c

       1  /*
           * MSDOS evaluation routines
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_eval.c,  v 1.13 2010/07/04 14:53:46 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          
          #include <rtems/libio_.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          #include "msdos.h"
          
          /* msdos_set_handlers --
           * Set handlers for the node with specified type(  i.e. handlers for file
           * or directory ).
           *
           * PARAMETERS:
           * loc - node description
           *
           * RETURNS:
           * None
           */
          static void
      44  msdos_set_handlers(  rtems_filesystem_location_info_t *loc )
          {
           msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
           fat_file_fd_t *fat_fd = loc->node_access;
          
           if (  fat_fd->fat_file_type == FAT_DIRECTORY )
           loc->handlers = fs_info->directory_handlers;
           else
           loc->handlers = fs_info->file_handlers;
          }
          
          /* msdos_eval_path --
           *
           * The following routine evaluate path for a node that wishes to be
           * accessed. Structure 'pathloc' is returned with a pointer to the
           * node to be accessed.
           *
           * PARAMETERS:
           * pathname - path for evaluation
           * flags - flags
           * pathloc - node description (  IN/OUT )
           *
           * RETURNS:
           * RC_OK and filled pathloc on success,   or -1 if error occured
           * (  errno set appropriately )
           *
           */
          int
      72  msdos_eval_path(  
           const char *pathname,  
           size_t pathnamelen,  
           int flags,  
           rtems_filesystem_location_info_t *pathloc
            )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
           fat_file_fd_t *fat_fd = NULL;
           rtems_filesystem_location_info_t newloc;
           int i = 0;
           int token_len = 0;
           msdos_token_types_t type = MSDOS_CURRENT_DIR;
           const char *token;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           if (  !pathloc->node_access )
           {
           errno = ENOENT;
           rc = -1;
           goto err;
           }
          
           fat_fd = pathloc->node_access;
          
           rc = fat_file_reopen(  fat_fd );
           if (  rc != RC_OK )
           goto err;
          
           while (  (  type != MSDOS_NO_MORE_PATH ) && (  type != MSDOS_INVALID_TOKEN ) )
           {
           type = msdos_get_token(  &pathname[i],   pathnamelen,   &token,   &token_len );
           pathnamelen -= token_len;
           i += token_len;
          
           fat_fd = pathloc->node_access;
          
           switch (  type )
           {
           case MSDOS_UP_DIR:
           /*
           * Only a directory can be decended into.
           */
           if (  fat_fd->fat_file_type != FAT_DIRECTORY )
           {
           errno = ENOTSUP;
           rc = -1;
           goto error;
           }
          
           /*
           * Am I at the root of this mounted filesystem?
           */
           if (  pathloc->node_access ==
           pathloc->mt_entry->mt_fs_root.node_access )
           {
           /*
           * Am I at the root of all filesystems?
           * XXX: MSDOS is not supposed to be base fs.
           */
           if (  pathloc->node_access ==
           rtems_filesystem_root.node_access )
           {
           break; /* Throw out the .. in this case */
           }
           else
           {
           newloc = pathloc->mt_entry->mt_point_node;
           *pathloc = newloc;
          
           rc = fat_file_close(  pathloc->mt_entry,   fat_fd );
           if (  rc != RC_OK )
           goto err;
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return (  *pathloc->ops->evalpath_h )(  &(  pathname[i-token_len] ),  
           pathnamelen + token_len,  
           flags,   pathloc );
           }
           }
           else
           {
           rc = msdos_find_name(  pathloc,   token,   token_len );
           if (  rc != RC_OK )
           {
           if (  rc == MSDOS_NAME_NOT_FOUND_ERR )
           {
           errno = ENOENT;
           rc = -1;
           }
           goto error;
           }
           }
           break;
          
           case MSDOS_NAME:
           /*
           * Only a directory can be decended into.
           */
           if (  fat_fd->fat_file_type != FAT_DIRECTORY )
           {
           errno = ENOTSUP;
           rc = -1;
           goto error;
           }
          
           /*
           * Otherwise find the token name in the present location and
           * set the node access to the point we have found.
           */
           rc = msdos_find_name(  pathloc,   token,   token_len );
           if (  rc != RC_OK )
           {
           if (  rc == MSDOS_NAME_NOT_FOUND_ERR )
           {
           errno = ENOENT;
           rc = -1;
           }
           goto error;
           }
           break;
          
           case MSDOS_NO_MORE_PATH:
           case MSDOS_CURRENT_DIR:
           break;
          
           case MSDOS_INVALID_TOKEN:
           errno = ENAMETOOLONG;
           rc = -1;
           goto error;
           break;
          
           }
           }
          
           /*
           * Always return the root node.
           *
           * If we are at a node that is a mount point. Set loc to the
           * new fs root node and let let the mounted filesystem set the handlers.
           *
           * NOTE: The behavior of stat(   ) on a mount point appears to be
           * questionable.
           * NOTE: MSDOS filesystem currently doesn't support mount functionality ->
           * action not implemented
           */
           fat_fd = pathloc->node_access;
          
           msdos_set_handlers(  pathloc );
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return RC_OK;
          
          error:
           fat_file_close(  pathloc->mt_entry,   fat_fd );
          
          err:
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
          }
          
          /* msdos_eval4make --
           * The following routine evaluate path for a new node to be created.
           * 'pathloc' is returned with a pointer to the parent of the new node.
           * 'name' is returned with a pointer to the first character in the
           * new node name. The parent node is verified to be a directory.
           *
           * PARAMETERS:
           * path - path for evaluation
           * pathloc - IN/OUT (  start point for evaluation/parent directory for
           * creation )
           * name - new node name
           *
           * RETURNS:
           * RC_OK,   filled pathloc for parent directory and name of new node on
           * success,   or -1 if error occured (  errno set appropriately )
           */
          int
     256  msdos_eval4make(  
           const char *path,  
           rtems_filesystem_location_info_t *pathloc,  
           const char **name
            )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
           fat_file_fd_t *fat_fd = NULL;
           rtems_filesystem_location_info_t newloc;
           msdos_token_types_t type;
           int i = 0;
           int token_len;
           const char *token;
           bool done = false;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           if (  !pathloc->node_access )
           {
           errno = ENOENT;
           rc = -1;
           goto err;
           }
          
           fat_fd = pathloc->node_access;
          
           rc = fat_file_reopen(  fat_fd );
           if (  rc != RC_OK )
           goto err;
          
           while (  !done )
           {
           type = msdos_get_token(  &path[i],   strlen(  &path[i] ),   &token,   &token_len );
           i += token_len;
           fat_fd = pathloc->node_access;
          
           switch (  type )
           {
           case MSDOS_UP_DIR:
           /*
           * Only a directory can be decended into.
           */
           if (  fat_fd->fat_file_type != FAT_DIRECTORY )
           {
           errno = ENOTDIR;
           rc = -1;
           goto error;
           }
          
           /*
           * Am I at the root of this mounted filesystem?
           */
           if (  pathloc->node_access ==
           pathloc->mt_entry->mt_fs_root.node_access )
           {
           /*
           * Am I at the root of all filesystems?
           * XXX: MSDOS is not supposed to be base fs.
           */
           if (  pathloc->node_access ==
           rtems_filesystem_root.node_access )
           {
           break; /* Throw out the .. in this case */
           }
           else
           {
           newloc = pathloc->mt_entry->mt_point_node;
           *pathloc = newloc;
          
           rc = fat_file_close(  pathloc->mt_entry,   fat_fd );
           if (  rc != RC_OK )
           goto err;
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return (  *pathloc->ops->evalformake_h )(  &path[i-token_len],  
           pathloc,   name );
           }
           }
           else
           {
           rc = msdos_find_name(  pathloc,   token,   token_len );
           if (  rc != RC_OK )
           {
           if (  rc == MSDOS_NAME_NOT_FOUND_ERR )
           {
           errno = ENOENT;
           rc = -1;
           }
           goto error;
           }
           }
           break;
          
           case MSDOS_NAME:
           /*
           * Only a directory can be decended into.
           */
           if (  fat_fd->fat_file_type != FAT_DIRECTORY )
           {
           errno = ENOTDIR;
           rc = -1;
           goto error;
           }
          
           /*
           * Otherwise find the token name in the present location and
           * set the node access to the point we have found.
           */
           rc = msdos_find_name(  pathloc,   token,   token_len );
           if (  rc )
           {
           if (  rc != MSDOS_NAME_NOT_FOUND_ERR )
           {
           errno = ENOENT;
           rc = -1;
           goto error;
           }
           else
           done = true;
           }
           break;
          
           case MSDOS_NO_MORE_PATH:
           errno = EEXIST;
           rc = -1;
           goto error;
           break;
          
           case MSDOS_CURRENT_DIR:
           break;
          
           case MSDOS_INVALID_TOKEN:
           errno = ENAMETOOLONG;
           rc = -1;
           goto error;
           break;
          
           }
           }
          
           *name = &path[i - token_len];
          
           /*
           * We have evaluated the path as far as we can.
           * Verify there is not any invalid stuff at the end of the name.
           */
           for(   ; path[i] != '\0'; i++ )
           {
           if (  !msdos_is_separator(  path[i] ) )
           {
           errno = ENOENT;
           rc = -1;
           goto error;
           }
           }
          
           fat_fd = pathloc->node_access;
          
           if (  fat_fd->fat_file_type != FAT_DIRECTORY )
           {
           errno = ENOTDIR;
           rc = -1;
           goto error;
           }
          
           msdos_set_handlers(  pathloc );
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return RC_OK;
          
          error:
           fat_file_close(  pathloc->mt_entry,   fat_fd );
          
          err:
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
          }

libfs/src/dosfs/msdos_file.c

       1  /*
           * MSDOS file handlers implementation
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_file.c,  v 1.15 2010/07/15 08:10:47 sh Exp $
           */
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          #include "msdos.h"
          
          /* msdos_file_open --
           * Open fat-file which correspondes to the file
           *
           * PARAMETERS:
           * iop - file control block
           * pathname - name
           * flag - flags
           * mode - mode
           *
           * RETURNS:
           * RC_OK,   if file opened successfully,   or -1 if error occured
           * and errno set appropriately
           */
          int
      44  msdos_file_open(  rtems_libio_t *iop,   const char *pathname,   uint32_t flag,  
           uint32_t mode )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           rc = fat_file_reopen(  fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           if (  iop->flags & LIBIO_FLAGS_APPEND )
           iop->offset = fat_fd->fat_file_size;
          
           iop->size = fat_fd->fat_file_size;
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return RC_OK;
          }
          
          /* msdos_file_close --
           * Close fat-file which correspondes to the file. If fat-file descriptor
           * which correspondes to the file is not marked "removed",   synchronize
           * size,   first cluster number,   write time and date fields of the file.
           *
           * PARAMETERS:
           * iop - file control block
           *
           * RETURNS:
           * RC_OK,   if file closed successfully,   or -1 if error occured (  errno set
           * appropriately )
           */
          int
      86  msdos_file_close(  rtems_libio_t *iop )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           /*
           * if fat-file descriptor is not marked as "removed",   synchronize
           * size,   first cluster number,   write time and date fields of the file
           */
           if (  !FAT_FILE_IS_REMOVED(  fat_fd ) )
           {
           rc = msdos_set_first_cluster_num(  iop->pathinfo.mt_entry,   fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           rc = msdos_set_file_size(  iop->pathinfo.mt_entry,   fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           rc = msdos_set_dir_wrt_time_and_date(  iop->pathinfo.mt_entry,   fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
           }
          
           rc = fat_file_close(  iop->pathinfo.mt_entry,   fat_fd );
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
          }
          
          /* msdos_file_read --
           * This routine read from file pointed to by file control block into
           * the specified data buffer provided by user
           *
           * PARAMETERS:
           * iop - file control block
           * buffer - buffer provided by user
           * count - the number of bytes to read
           *
           * RETURNS:
           * the number of bytes read on success,   or -1 if error occured (  errno set
           * appropriately )
           */
          ssize_t
     146  msdos_file_read(  rtems_libio_t *iop,   void *buffer,   size_t count )
          {
           ssize_t ret = 0;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           ret = fat_file_read(  iop->pathinfo.mt_entry,   fat_fd,   iop->offset,   count,  
           buffer );
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return ret;
          }
          
          /* msdos_file_write --
           * This routine writes the specified data buffer into the file pointed to
           * by file control block.
           *
           * PARAMETERS:
           * iop - file control block
           * buffer - data to write
           * count - count of bytes to write
           *
           * RETURNS:
           * the number of bytes written on success,   or -1 if error occured
           * and errno set appropriately
           */
          ssize_t
     179  msdos_file_write(  rtems_libio_t *iop,  const void *buffer,   size_t count )
          {
           ssize_t ret = 0;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           ret = fat_file_write(  iop->pathinfo.mt_entry,   fat_fd,   iop->offset,   count,  
           buffer );
           if (  ret < 0 )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return -1;
           }
          
           /*
           * update file size in both fat-file descriptor and file control block if
           * file was extended
           */
           if (  iop->offset + ret > fat_fd->fat_file_size )
           fat_fd->fat_file_size = iop->offset + ret;
          
           iop->size = fat_fd->fat_file_size;
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return ret;
          }
          
          /* msdos_file_lseek --
           * Process lseek call to the file: extend file if lseek is up to the end
           * of the file.
           *
           * PARAMETERS:
           * iop - file control block
           * offset - new offset
           * whence - predefine directive
           *
           * RETURNS:
           * new offset on success,   or -1 if error occured (  errno set
           * appropriately ).
           */
          rtems_off64_t
     226  msdos_file_lseek(  rtems_libio_t *iop,   rtems_off64_t offset,   int whence )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
           uint32_t real_size = 0;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           rc = fat_file_extend(  iop->pathinfo.mt_entry,   fat_fd,   iop->offset,  
           &real_size );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           if (  real_size > fat_fd->fat_file_size )
           fat_fd->fat_file_size = iop->offset = real_size;
          
           iop->size = fat_fd->fat_file_size;
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return iop->offset;
          }
          
          /* msdos_file_stat --
           *
           * PARAMETERS:
           * loc - node description
           * buf - stat buffer provided by user
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set appropriately )
           */
          int
     266  msdos_file_stat(  
           rtems_filesystem_location_info_t *loc,  
           struct stat *buf
            )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
           fat_file_fd_t *fat_fd = loc->node_access;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           buf->st_dev = fs_info->fat.vol.dev;
           buf->st_ino = fat_fd->ino;
           buf->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO;
           buf->st_rdev = 0ll;
           buf->st_size = fat_fd->fat_file_size;
           buf->st_blocks = fat_fd->fat_file_size >> FAT_SECTOR512_BITS;
           buf->st_blksize = fs_info->fat.vol.bps;
           buf->st_mtime = fat_fd->mtime;
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return RC_OK;
          }
          
          /* msdos_file_ftruncate --
           * Truncate the file (  if new length is greater then current do nothing ).
           *
           * PARAMETERS:
           * iop - file control block
           * length - new length
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set appropriately ).
           */
          int
     304  msdos_file_ftruncate(  rtems_libio_t *iop,   rtems_off64_t length )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
          
           if (  length >= fat_fd->fat_file_size )
           return RC_OK;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           rc = fat_file_truncate(  iop->pathinfo.mt_entry,   fat_fd,   length );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           /*
           * fat_file_truncate do nothing if new length >= fat-file size,   so update
           * file size only if length < fat-file size
           */
           if (  length < fat_fd->fat_file_size )
           iop->size = fat_fd->fat_file_size = length;
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return RC_OK;
          }
          
          /* msdos_file_sync --
           * Synchronize file - synchronize file data and if file is not removed
           * synchronize file metadata.
           *
           * PARAMETERS:
           * iop - file control block
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set appropriately )
           */
          int
     348  msdos_file_sync(  rtems_libio_t *iop )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           /* synchronize file data */
           rc = fat_file_datasync(  iop->pathinfo.mt_entry,   fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           /*
           * if fat-file descriptor is not marked "removed" - synchronize file
           * metadata
           */
           if (  !FAT_FILE_IS_REMOVED(  fat_fd ) )
           {
           rc = msdos_set_first_cluster_num(  iop->pathinfo.mt_entry,   fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
           rc = msdos_set_file_size(  iop->pathinfo.mt_entry,   fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
           rc = msdos_set_dir_wrt_time_and_date(  iop->pathinfo.mt_entry,   fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
           }
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return RC_OK;
          }
          
          /* msdos_file_datasync --
           * Synchronize file - synchronize only file data (  metadata is letf intact ).
           *
           * PARAMETERS:
           * iop - file control block
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set appropriately )
           */
          int
     408  msdos_file_datasync(  rtems_libio_t *iop )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
           msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           /* synchronize file data */
           rc = fat_file_datasync(  iop->pathinfo.mt_entry,   fat_fd );
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return RC_OK;
          }
          
          
          /* msdos_file_ioctl --
           *
           *
           * PARAMETERS:
           * iop - file control block
           * ...
           *
           * RETURNS:
           *
           */
          int
     439  msdos_file_ioctl(  rtems_libio_t *iop,  uint32_t command,   void *buffer )
          {
           int rc = RC_OK;
          
           return rc;
          }
          
          /* msdos_file_chmod --
           * Change the attributes of the file. This currently does
           * nothing and returns no error.
           *
           * PARAMETERS:
           * pathloc - node description
           * mode - the new mode
           *
           * RETURNS:
           * RC_OK always
           */
          int
     458  msdos_file_chmod(  rtems_filesystem_location_info_t *pathloc,  
           mode_t mode )
          {
           return RC_OK;
          }
          
          /* msdos_file_rmnod --
           * Remove node associated with a file - set up first name character to
           * predefined value(  and write it to the disk ),   and mark fat-file which
           * correspondes to the file as "removed"
           *
           * PARAMETERS:
           * pathloc - node description
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set appropriately )
           */
          int
     476  msdos_file_rmnod(  rtems_filesystem_location_info_t *parent_pathloc,  
           rtems_filesystem_location_info_t *pathloc )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
           fat_file_fd_t *fat_fd = pathloc->node_access;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           /* mark file removed */
           rc = msdos_set_first_char4file_name(  pathloc->mt_entry,  
           &fat_fd->dir_pos,  
           MSDOS_THIS_DIR_ENTRY_EMPTY );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           fat_file_mark_removed(  pathloc->mt_entry,   fat_fd );
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return RC_OK;
          }

libfs/src/dosfs/msdos_format.c

       1  /*===============================================================*\
          | Project: RTEMS msdos format functionality |
          +-----------------------------------------------------------------+
          | File: msdos_format.c |
          +-----------------------------------------------------------------+
          | Copyright (  c ) 2004 IMD |
          | Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
          | <Thomas.Doerfler@imd-systems.de> |
          | all rights reserved |
          +-----------------------------------------------------------------+
          | this file contains msdos_format function. This function |
          | formats a disk partition conforming to MS-DOS conventions |
          | |
          | The license and distribution terms for this file may be |
          | found in the file LICENSE in this distribution or at |
          | http://www.rtems.com/license/LICENSE. |
          | |
          +-----------------------------------------------------------------+
          | date history ID |
          | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
          | 29.10.04 creation doe |
          \*===============================================================*/
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <stdio.h>
          #include <ctype.h>
          
          #include <rtems/libio_.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "msdos.h"
          #include "dosfs.h"
          
          typedef struct {
           uint32_t bytes_per_sector;
           uint32_t totl_sector_cnt;
           uint32_t rsvd_sector_cnt;
          
           uint32_t sectors_per_cluster;
           uint32_t sectors_per_fat;
          
           uint32_t fat_start_sec;
           uint32_t files_per_root_dir;
           uint32_t root_dir_sectors;
           uint32_t root_dir_start_sec;
           uint32_t root_dir_fmt_sec_cnt;
           uint32_t mbr_copy_sec; /* location of copy of mbr or 0 */
           uint32_t fsinfo_sec; /* location of fsinfo sector or 0 */
           uint8_t fat_num;
           uint8_t media_code;
           uint8_t fattype;
           char OEMName[FAT_BR_OEMNAME_SIZE+1];
           char VolLabel[FAT_BR_VOLLAB_SIZE+1];
           bool VolLabel_present;
           uint32_t vol_id;
          } msdos_format_param_t;
          
          /*
           * Formatted output.
           */
          static void
      72  msdos_format_printf (  const msdos_format_request_param_t *rqdata,  
           int info_level,  
           const char *format,   ... )
          {
           va_list args;
           va_start (  args,   format );
           if (  rqdata != NULL && rqdata->info_level >= info_level )
           {
           vfprintf (  stdout,   format,   args );
           fflush (  stdout );
           }
           va_end (  args );
          }
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
      89  static int msdos_format_read_sec
          (  
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | function to read a sector |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
           int fd,   /* file descriptor index */
           uint32_t start_sector,   /* sector number to write to */
           uint32_t sector_size,   /* size of sector */
           char *buffer /* buffer with read data into */
            )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | 0,   if success,   -1 and errno if failed |
          \*=========================================================================*/
          {
           int ret_val = 0;
          
           if (  0 > lseek(  fd,  (  (  off_t )start_sector )*sector_size,  SEEK_SET ) ) {
           ret_val = -1;
           }
           if (  ret_val == 0 ) {
           if (  0 > read(  fd,  buffer,  sector_size ) ) {
           ret_val = -1;
           }
           }
          
           return ret_val;
          }
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
     124  static int msdos_format_write_sec
          (  
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | function to write to a sector |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
           int fd,   /* file descriptor index */
           uint32_t start_sector,   /* sector number to write to */
           uint32_t sector_size,   /* size of sector */
           const char *buffer /* buffer with write data */
            )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | 0,   if success,   -1 and errno if failed |
          \*=========================================================================*/
          {
           int ret_val = 0;
          
           if (  0 > lseek(  fd,  (  (  off_t )start_sector )*sector_size,  SEEK_SET ) ) {
           ret_val = -1;
           }
           if (  ret_val == 0 ) {
           if (  0 > write(  fd,  buffer,  sector_size ) ) {
           ret_val = -1;
           }
           }
          
           return ret_val;
          }
          
          /*=========================================================================* \
          | Function: |
          \*-------------------------------------------------------------------------*/
     159  static int msdos_format_fill_sectors
          (  
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | function to fill sectors with byte |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
           const msdos_format_request_param_t *rqdata,  
           int fd,   /* file descriptor index */
           uint32_t start_sector,   /* sector number to fill to */
           uint32_t sector_cnt,   /* number of sectors to fill to */
           uint32_t sector_size,   /* size of sector */
           const char fill_byte /* byte to fill into sectors */
            )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | 0,   if success,   -1 and errno if failed |
          \*=========================================================================*/
          {
           int ret_val = 0;
           char *fill_buffer = NULL;
           uint32_t total_sectors = sector_cnt;
           int last_percent = -1;
          
           /*
           * allocate and fill buffer
           */
           if (  ret_val == 0 ) {
           fill_buffer = malloc(  sector_size );
           if (  fill_buffer == NULL ) {
           errno = ENOMEM;
           ret_val = -1;
           }
           else {
           memset(  fill_buffer,  fill_byte,  sector_size );
           }
           }
          
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,  
           "Filling : " );
           /*
           * write to consecutive sectors
           */
           while (  (  ret_val == 0 ) &&
           (  sector_cnt > 0 ) ) {
           int percent = (  sector_cnt * 100 ) / total_sectors;
           if (  percent != last_percent ) {
           if (  (  percent & 1 ) == 0 )
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,   "." );
           last_percent = percent;
           }
           ret_val = msdos_format_write_sec(  fd,  start_sector,  sector_size,  fill_buffer );
           start_sector++;
           sector_cnt--;
           }
          
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,   "\n" );
          
           if (  ret_val )
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_INFO,  
           "filling error on sector: %d\n",   start_sector );
          
           /*
           * cleanup
           */
           if (  fill_buffer != NULL ) {
           free(  fill_buffer );
           fill_buffer = NULL;
           }
           return ret_val;
          }
          
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
     236  static int msdos_format_gen_volid
          (  
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | function to generate a pseudo-random volume id |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
           uint32_t *volid_ptr /* volume ID return pointer */
            )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | 0,   if success,   -1 and errno if failed |
          \*=========================================================================*/
          {
           int ret_val = 0;
           int rc;
           struct timeval time_value;
          
           rc = rtems_clock_get_tod_timeval(  &time_value );
           if (  rc == RTEMS_SUCCESSFUL ) {
           *volid_ptr = time_value.tv_sec + time_value.tv_sec;
           }
           else {
           *volid_ptr = rand(   );
           }
          
           return ret_val;
          }
          
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
     270  static int msdos_format_eval_sectors_per_cluster
          (  
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | function to check/adjust sectors_per_cluster to legal values |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
           int fattype,   /* type code of FAT (  FAT_FAT12 ... ) */
           uint32_t bytes_per_sector,   /* byte count per sector (  512 ) */
           uint32_t fatdata_sec_cnt,   /* sectors available for FAT and data */
           uint8_t fat_num,   /* number of fat copies */
           uint32_t sectors_per_cluster,   /* sectors per cluster (  requested ) */
           uint32_t *sectors_per_cluster_adj,   /* ret: sec per cluster (  granted ) */
           uint32_t *sectors_per_fat_ptr /* ret: sectors needed for one FAT */
            )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | 0,   if success,   -1 and errno if failed |
          \*=========================================================================*/
          {
          
           bool finished = false;
           int ret_val = 0;
           uint32_t fatdata_cluster_cnt;
           uint32_t fat_capacity;
           uint32_t sectors_per_fat;
           uint32_t data_cluster_cnt;
           /*
           * ensure,   that maximum cluster size (  32KByte ) is not exceeded
           */
           while (  MS_BYTES_PER_CLUSTER_LIMIT / bytes_per_sector < sectors_per_cluster ) {
           sectors_per_cluster /= 2;
           }
          
           do {
           /*
           * compute number of data clusters for current data:
           * - compute cluster count for data AND fat
           * - compute storage size for FAT
           * - subtract from total cluster count
           */
           fatdata_cluster_cnt = fatdata_sec_cnt/sectors_per_cluster;
           if (  fattype == FAT_FAT12 ) {
           fat_capacity = fatdata_cluster_cnt * 3 / 2;
           }
           else if (  fattype == FAT_FAT16 ) {
           fat_capacity = fatdata_cluster_cnt * 2;
           }
           else { /* FAT32 */
           fat_capacity = fatdata_cluster_cnt * 4;
           }
          
           sectors_per_fat = (  (  fat_capacity
           + (  bytes_per_sector - 1 ) )
           / bytes_per_sector );
          
           data_cluster_cnt = (  fatdata_cluster_cnt -
           (  (  (  sectors_per_fat * fat_num )
           + (  sectors_per_cluster - 1 ) )
           / sectors_per_cluster ) );
           /*
           * data cluster count too big? then make sectors bigger
           */
           if (  (  (  fattype == FAT_FAT12 ) && (  data_cluster_cnt > FAT_FAT12_MAX_CLN ) ) ||
           (  (  fattype == FAT_FAT16 ) && (  data_cluster_cnt > FAT_FAT16_MAX_CLN ) ) ) {
           sectors_per_cluster *= 2;
           }
           else {
           finished = true;
           }
           /*
           * when maximum cluster size is exceeded,   we have invalid data,   abort...
           */
           if (  (  sectors_per_cluster * bytes_per_sector )
           > MS_BYTES_PER_CLUSTER_LIMIT ) {
           ret_val = EINVAL;
           finished = true;
           }
           } while (  !finished );
          
           if (  ret_val != 0 ) {
           rtems_set_errno_and_return_minus_one(  ret_val );
           }
           else {
           *sectors_per_cluster_adj = sectors_per_cluster;
           *sectors_per_fat_ptr = sectors_per_fat;
           return 0;
           }
          }
          
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
     365  static int msdos_format_determine_fmt_params
          (  
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | determine parameters for formatting |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
           const rtems_disk_device *dd,   /* disk device structure */
           const msdos_format_request_param_t *rqdata,   /* requested fmt parameters */
           msdos_format_param_t *fmt_params/* computed fmt parameters */
            )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | 0,   if success,   -1 and errno if failed |
          \*=========================================================================*/
          {
           int ret_val = 0;
           uint32_t fatdata_sect_cnt;
           uint32_t onebit;
           uint32_t sectors_per_cluster_adj = 0;
           uint64_t total_size = 0;
          
           memset(  fmt_params,  0,  sizeof(  *fmt_params ) );
           /*
           * this one is fixed in this implementation.
           * At least one thing we don't have to magically guess...
           */
           if (  ret_val == 0 ) {
           fmt_params->bytes_per_sector = dd->block_size;
           fmt_params->totl_sector_cnt = dd->size;
           total_size = dd->block_size * dd->size;
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,  
           "bytes per sector: %d\ntotal sectors: %d\ntotal size: %lu\n",  
           dd->block_size,   dd->size,   total_size );
           }
           /*
           * determine number of FATs
           */
           if (  ret_val == 0 ) {
           if (  (  rqdata == NULL ) ||
           (  rqdata->fat_num == 0 ) ) {
           fmt_params->fat_num = 2;
           }
           else if (  rqdata->fat_num <= 6 ) {
           fmt_params->fat_num = rqdata->fat_num;
           }
           else {
           ret_val = EINVAL;
           }
           }
          
           if (  ret_val == 0 )
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,  
           "number of fats: %d\n",   fmt_params->fat_num );
          
           /*
           * Now we get sort of a loop when determining things:
           * The FAT type (  FAT12/16/32 ) is determined ONLY from the
           * data cluster count:
           * Disks with data cluster count < 4085 are FAT12.
           * Disks with data cluster count < 65525 are FAT16.
           * The rest is FAT32 (  no FAT128 available yet :- )
           *
           * The number of data clusters is the
           * total capacity
           * minus reserved sectors
           * minus root directory ares
           * minus storage needed for the FAT (  and its copy/copies ).
           *
           * The last item once again depends on the FAT type and the cluster count.
           *
           * So here is what we do in this formatter:
           * - If a FAT type is requested from the caller,   we try to modify
           * the cluster size,   until the data cluster count is in range
           * - If no FAT type is given,   we estimate a useful FAT type from
           * the disk capacity and then adapt the cluster size
           */
          
           /*
           * determine characteristic values:
           * - number of sectors
           * - number of reserved sectors
           * - number of used sectors
           * - sectors per cluster
           */
           /*
           * determine FAT type and sectors per cluster
           * depends on
           */
           if (  ret_val == 0 ) {
           fmt_params->sectors_per_cluster = 1;
           if (  (  rqdata != NULL ) &&
           (  rqdata->fattype == MSDOS_FMT_FAT12 ) ) {
           fmt_params->fattype = FAT_FAT12;
           }
           else if (  (  rqdata != NULL ) &&
           (  rqdata->fattype == MSDOS_FMT_FAT16 ) ) {
           fmt_params->fattype = FAT_FAT16;
           }
           else if (  (  rqdata != NULL ) &&
           (  rqdata->fattype == MSDOS_FMT_FAT32 ) ) {
           fmt_params->fattype = FAT_FAT32;
           }
           else if (  (  rqdata != NULL ) &&
           (  rqdata->fattype != MSDOS_FMT_FATANY ) ) {
           ret_val = -1;
           errno = EINVAL;
           }
           else {
           /*
           * limiting values for disk size,   fat type,   sectors per cluster
           * NOTE: maximum sect_per_clust is arbitrarily choosen with values that
           * are a compromise concerning capacity and efficency
           */
           if (  fmt_params->totl_sector_cnt
           < (  (  uint32_t )FAT_FAT12_MAX_CLN )*8 ) {
           fmt_params->fattype = FAT_FAT12;
           /* start trying with small clusters */
           fmt_params->sectors_per_cluster = 2;
           }
           else if (  fmt_params->totl_sector_cnt
           < (  (  uint32_t )FAT_FAT16_MAX_CLN )*32 ) {
           fmt_params->fattype = FAT_FAT16;
           /* start trying with small clusters */
           fmt_params->sectors_per_cluster = 2;
           }
           else {
           #define ONE_GB (  1024L * 1024L * 1024L )
           uint32_t gigs = (  total_size + ONE_GB ) / ONE_GB;
           int b;
           fmt_params->fattype = FAT_FAT32;
           /* scale with the size of disk... */
           for (  b = 31; b > 0; b-- )
           if (  (  gigs & (  1 << b ) ) != 0 )
           break;
           fmt_params->sectors_per_cluster = 1 << b;
           }
           }
           /*
           * try to use user requested cluster size
           */
           if (  (  rqdata != NULL ) &&
           (  rqdata->sectors_per_cluster > 0 ) ) {
           fmt_params->sectors_per_cluster =
           rqdata->sectors_per_cluster;
           }
           /*
           * check sectors per cluster.
           * must be power of 2
           * must be smaller than or equal to 128
           * sectors_per_cluster*bytes_per_sector must not be bigger than 32K
           */
           for (  onebit = 128;onebit >= 1;onebit = onebit>>1 ) {
           if (  fmt_params->sectors_per_cluster >= onebit ) {
           fmt_params->sectors_per_cluster = onebit;
           if (  fmt_params->sectors_per_cluster
           <= 32768L/fmt_params->bytes_per_sector ) {
           /* value is small enough so this value is ok */
           onebit = 1;
           }
           }
           }
           }
          
           if (  ret_val == 0 ) {
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,  
           "sectors per cluster: %d\n",   fmt_params->sectors_per_cluster );
          
           if (  fmt_params->fattype == FAT_FAT32 ) {
           /* recommended: for FAT32,   always set reserved sector count to 32 */
           fmt_params->rsvd_sector_cnt = 32;
           /* for FAT32,   always set files per root directory 0 */
           fmt_params->files_per_root_dir = 0;
           /* location of copy of MBR */
           fmt_params->mbr_copy_sec = 6;
           /* location of fsinfo sector */
           fmt_params->fsinfo_sec = 1;
          
           }
           else {
           /* recommended: for FAT12/FAT16,   always set reserved sector count to 1 */
           fmt_params->rsvd_sector_cnt = 1;
           /* recommended: for FAT16,   set files per root directory to 512 */
           /* for FAT12/FAT16,   set files per root directory */
           /* must fill up an even count of sectors */
           if (  (  rqdata != NULL ) &&
           (  rqdata->files_per_root_dir > 0 ) ) {
           fmt_params->files_per_root_dir = rqdata->files_per_root_dir;
           }
           else {
           if (  fmt_params->fattype == FAT_FAT16 ) {
           fmt_params->files_per_root_dir = 512;
           }
           else {
           fmt_params->files_per_root_dir = 64;
           }
           }
           fmt_params->files_per_root_dir = (  fmt_params->files_per_root_dir +
           (  2*fmt_params->bytes_per_sector/
           FAT_DIRENTRY_SIZE-1 ) );
           fmt_params->files_per_root_dir -= (  fmt_params->files_per_root_dir %
           (  2*fmt_params->bytes_per_sector
           /FAT_DIRENTRY_SIZE ) );
           }
           fmt_params->root_dir_sectors =
           (  (  (  fmt_params->files_per_root_dir * FAT_DIRENTRY_SIZE )
           + fmt_params->bytes_per_sector - 1 )
           / fmt_params->bytes_per_sector );
           }
           if (  ret_val == 0 ) {
           fatdata_sect_cnt = (  fmt_params->totl_sector_cnt -
           fmt_params->rsvd_sector_cnt -
           fmt_params->root_dir_sectors );
          
           /*
           * check values to get legal arrangement of FAT type and cluster count
           */
          
           ret_val = msdos_format_eval_sectors_per_cluster
           (  fmt_params->fattype,  
           fmt_params->bytes_per_sector,  
           fatdata_sect_cnt,  
           fmt_params->fat_num,  
           fmt_params->sectors_per_cluster,  
           &sectors_per_cluster_adj,  
           &(  fmt_params->sectors_per_fat ) );
           fmt_params->sectors_per_cluster = sectors_per_cluster_adj;
           }
          
           /*
           * determine media code
           */
           if (  ret_val == 0 ) {
           if (  (  rqdata != NULL ) &&
           (  rqdata->media != 0 ) ) {
           const char valid_media_codes[] =
           {0xF0,  0xF8,  0xF9,  0xFA,  0xFB,  0xFC,  0xFD,  0xFE,  0xFF};
           if (  NULL==memchr(  valid_media_codes,  
           rqdata->media,  
           sizeof(  valid_media_codes ) ) ) {
           ret_val = -1;
           errno = EINVAL;
           }
           else {
           fmt_params->media_code = rqdata->media;
           }
           }
           else {
           fmt_params->media_code = FAT_BR_MEDIA_FIXED;
           }
           }
           /*
           * determine location and size of root directory
           * for formatting
           */
           if (  fmt_params->root_dir_sectors > 0 ) {
           fmt_params->root_dir_start_sec =
           fmt_params->rsvd_sector_cnt
           + (  fmt_params-> fat_num*fmt_params->sectors_per_fat );
           fmt_params->root_dir_fmt_sec_cnt = fmt_params->root_dir_sectors;
           }
           else {
           /*
           * for FAT32: root directory is in cluster 2
           */
           fmt_params->root_dir_start_sec =
           fmt_params->rsvd_sector_cnt
           + (  fmt_params-> fat_num*fmt_params->sectors_per_fat );
           fmt_params->root_dir_fmt_sec_cnt = fmt_params->sectors_per_cluster;
           }
           /*
           * determine usable OEMName
           */
           if (  ret_val == 0 ) {
           const char *from;
           char *to = fmt_params->OEMName;
           int cnt;
           from = "RTEMS"; /* default: make "from" point to OS Name */
           if (  (  rqdata != NULL ) &&
           (  rqdata->OEMName != NULL ) ) {
           from = rqdata->OEMName;
           }
           for (  cnt = 0;
           cnt < (  sizeof(  fmt_params->OEMName )-1 );
           cnt++ ) {
           if (  isprint(  (  unsigned char )*from ) ) {
           *to++ = *from++;
           }
           else {
           /*
           * non-printable character in given name,   so keep stuck
           * at that character and replace all following characters
           * with a ' '
           */
           *to++=' ';
           }
           *to = '\0';
           }
           }
          
           /*
           * determine usable Volume Label
           */
           if (  ret_val == 0 ) {
           const char *from;
           char *to = fmt_params->VolLabel;
           int cnt;
           from = ""; /* default: make "from" point to empty string */
           if (  (  rqdata != NULL ) &&
           (  rqdata->VolLabel != NULL ) ) {
           from = rqdata->VolLabel;
           fmt_params->VolLabel_present = true;
           }
           for (  cnt = 0;
           cnt < (  sizeof(  fmt_params->VolLabel )-1 );
           cnt++ ) {
           if (  isprint(  (  unsigned char )*from ) ) {
           *to++ = *from++;
           }
           else {
           /*
           * non-printable character in given name,   so keep stuck
           * at that character and replace all following characters
           * with a ' '
           */
           *to++=' ';
           }
           *to = '\0';
           }
           }
          
           /*
           * determine usable Volume ID
           */
           if (  ret_val == 0 ) {
           msdos_format_gen_volid(  &(  fmt_params->vol_id ) );
           }
           /*
           * Phuuu.... That's it.
           */
           if (  ret_val != 0 ) {
           rtems_set_errno_and_return_minus_one(  ret_val );
           }
           else {
           return 0;
           }
          }
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
     716  static int msdos_format_gen_mbr
          (  
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | create master boot record content from parameter set |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
           char mbr[],   /* sector buffer */
           const msdos_format_param_t *fmt_params/* computed fmt parameters */
            )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | 0,   if success,   -1 and errno if failed |
          \*=========================================================================*/
          {
           uint32_t total_sectors_num16 = 0;
           uint32_t total_sectors_num32 = 0;
          
           /* store total sector count in either 16 or 32 bit field in mbr */
           if (  fmt_params->totl_sector_cnt < 0x10000 ) {
           total_sectors_num16 = fmt_params->totl_sector_cnt;
           }
           else {
           total_sectors_num32 = fmt_params->totl_sector_cnt;
           }
           /*
           * finally we are there: let's fill in the values into the MBR
           * but first clear the MRB leaving the partition table.
           */
          #define RTEMS_IDE_PARTITION_TABLE_OFFSET 0x1be
          #define RTEMS_IDE_PARTITION_TABLE_SIZE (  4 * 16 )
           memset(  mbr,  0,  RTEMS_IDE_PARTITION_TABLE_OFFSET );
           memset(  mbr + RTEMS_IDE_PARTITION_TABLE_OFFSET + RTEMS_IDE_PARTITION_TABLE_SIZE,  
           0,  
           FAT_TOTAL_MBR_SIZE - (  RTEMS_IDE_PARTITION_TABLE_OFFSET + RTEMS_IDE_PARTITION_TABLE_SIZE ) );
           /*
           * FIXME: fill jmpBoot and Boot code...
           * with 0xEB,  ....
           */
           /*
           * fill OEMName
           */
           memcpy(  FAT_GET_ADDR_BR_OEMNAME(  mbr ),  
           fmt_params->OEMName,  
           FAT_BR_OEMNAME_SIZE );
           FAT_SET_BR_BYTES_PER_SECTOR(  mbr ,   fmt_params->bytes_per_sector );
           FAT_SET_BR_SECTORS_PER_CLUSTER(  mbr ,   fmt_params->sectors_per_cluster );
           FAT_SET_BR_RESERVED_SECTORS_NUM(  mbr,   fmt_params->rsvd_sector_cnt );
          
           /* number of FATs on medium */
           FAT_SET_BR_FAT_NUM(  mbr ,   2 ); /* standard/recommended value */
           FAT_SET_BR_FILES_PER_ROOT_DIR(  mbr ,   fmt_params->files_per_root_dir );
           FAT_SET_BR_TOTAL_SECTORS_NUM16(  mbr ,   total_sectors_num16 );
           FAT_SET_BR_MEDIA(  mbr ,   fmt_params->media_code );
          
           FAT_SET_BR_SECTORS_PER_TRACK(  mbr ,   255 ); /* only needed for INT13... */
           FAT_SET_BR_NUMBER_OF_HEADS(  mbr ,   6 ); /* only needed for INT13... */
           FAT_SET_BR_HIDDEN_SECTORS(  mbr ,   1 ); /* only needed for INT13... */
          
           FAT_SET_BR_TOTAL_SECTORS_NUM32(  mbr ,   total_sectors_num32 );
           if (  fmt_params->fattype != FAT_FAT32 ) {
           FAT_SET_BR_SECTORS_PER_FAT(  mbr ,  fmt_params->sectors_per_fat );
           FAT_SET_BR_DRVNUM(  mbr ,   0 ); /* only needed for INT13... */
           FAT_SET_BR_RSVD1(  mbr ,   0 ); /* fill with zero */
           FAT_SET_BR_BOOTSIG(  mbr ,   FAT_BR_BOOTSIG_VAL );
           FAT_SET_BR_VOLID(  mbr ,   fmt_params->vol_id ); /* volume id */
           memcpy(  FAT_GET_ADDR_BR_VOLLAB(  mbr ),  
           fmt_params->VolLabel,  
           FAT_BR_VOLLAB_SIZE );
           memcpy(  FAT_GET_ADDR_BR_FILSYSTYPE(  mbr ),  
           (  fmt_params->fattype == FAT_FAT12 )
           ? "FAT12 "
           : "FAT16 ",  
           FAT_BR_FILSYSTYPE_SIZE );
           }
           else {
           FAT_SET_BR_SECTORS_PER_FAT32(  mbr ,  fmt_params->sectors_per_fat );
           FAT_SET_BR_EXT_FLAGS(  mbr ,   0 );
           FAT_SET_BR_FSVER(  mbr ,   0 ); /* FAT32 Version:0.0 */
           FAT_SET_BR_FAT32_ROOT_CLUSTER(  mbr ,   2 ); /* put root dir to cluster 2 */
           FAT_SET_BR_FAT32_FS_INFO_SECTOR(  mbr,   1 ); /* Put fsinfo to rsrvd sec 1*/
           FAT_SET_BR_FAT32_BK_BOOT_SECTOR(  mbr,   fmt_params->mbr_copy_sec  ); /* Put MBR copy to rsrvd sec */
           memset(  FAT_GET_ADDR_BR_FAT32_RESERVED(  mbr ),  0,  FAT_BR_FAT32_RESERVED_SIZE );
          
           FAT_SET_BR_FAT32_DRVNUM(  mbr ,   0 ); /* only needed for INT13... */
           FAT_SET_BR_FAT32_RSVD1(  mbr ,   0 ); /* fill with zero */
           FAT_SET_BR_FAT32_BOOTSIG(  mbr ,  FAT_BR_FAT32_BOOTSIG_VAL );
           FAT_SET_BR_FAT32_VOLID(  mbr ,   0 ); /* not set */
           memset(  FAT_GET_ADDR_BR_FAT32_VOLLAB(  mbr ) ,  0,  FAT_BR_VOLLAB_SIZE );
           memcpy(  FAT_GET_ADDR_BR_FAT32_FILSYSTYPE(  mbr ),  
           "FAT32 ",  
           FAT_BR_FILSYSTYPE_SIZE );
           }
           /*
           * add boot record signature
           */
           FAT_SET_BR_SIGNATURE(  mbr,   FAT_BR_SIGNATURE_VAL );
          
           /*
           * add jump to boot loader at start of sector
           */
           FAT_SET_VAL8(  mbr,  0,  0xeb );
           FAT_SET_VAL8(  mbr,  1,  0x3c );
           FAT_SET_VAL8(  mbr,  2,  0x90 );
           /*
           * FIXME: a nice little PC boot loader would be nice here.
           * but where can I get one for free?
           */
           /*
           * Phuuu.... That's it.
           */
           return 0;
          }
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
     834  static int msdos_format_gen_fsinfo
          (  
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | create FAT32 fsinfo sector |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
           char fsinfo[] /* sector buffer */
            )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | 0,   if success,   -1 and errno if failed |
          \*=========================================================================*/
          {
           /*
           * clear fsinfo sector data
           */
           memset(  fsinfo,  0,  FAT_TOTAL_FSINFO_SIZE );
           /*
           * write LEADSIG,   STRUCTSIG,   TRAILSIG
           */
           FAT_SET_FSINFO_LEAD_SIGNATURE (  fsinfo,  FAT_FSINFO_LEAD_SIGNATURE_VALUE  );
           FAT_SET_FSINFO_STRUC_SIGNATURE(  fsinfo,  FAT_FSINFO_STRUC_SIGNATURE_VALUE );
           FAT_SET_FSINFO_TRAIL_SIGNATURE(  fsinfo,  FAT_FSINFO_TRAIL_SIGNATURE_VALUE );
           /*
           * write "empty" values for free cluster count and next cluster number
           */
           FAT_SET_FSINFO_FREE_CLUSTER_COUNT(  fsinfo+FAT_FSI_INFO,  
           0xffffffff );
           FAT_SET_FSINFO_NEXT_FREE_CLUSTER (  fsinfo+FAT_FSI_INFO,  
           0xffffffff );
           return 0;
          }
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
     872  int msdos_format
          (  
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | format device with msdos filesystem |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
           const char *devname,   /* device name */
           const msdos_format_request_param_t *rqdata /* requested fmt parameters */
           /* set to NULL for automatic */
           /* determination */
            )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | 0,   if success,   -1 and errno if failed |
          \*=========================================================================*/
          {
           char tmp_sec[FAT_TOTAL_MBR_SIZE];
           int rc;
           rtems_disk_device *dd = NULL;
           struct stat stat_buf;
           int ret_val = 0;
           int fd = -1;
           int i;
           msdos_format_param_t fmt_params;
          
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_INFO,  
           "formating: %s\n",   devname );
           /*
           * sanity check on device
           */
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,  
           "stat check: %s\n",   devname );
           if (  ret_val == 0 ) {
           rc = stat(  devname,   &stat_buf );
           ret_val = rc;
           }
          
           /* rtems feature: no block devices,   all are character devices */
           if (  (  ret_val == 0 ) &&
           (  !S_ISBLK(  stat_buf.st_mode ) ) ) {
           errno = ENOTTY;
           ret_val = -1;
           }
          
           /* check that device is registered as block device and lock it */
           if (  ret_val == 0 ) {
           dd = rtems_disk_obtain(  stat_buf.st_rdev );
           if (  dd == NULL ) {
           errno = ENOTTY;
           ret_val = -1;
           }
           }
          
           /*
           * open device for writing
           */
           if (  ret_val == 0 ) {
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,  
           "open device\n" );
           fd = open(  devname,   O_RDWR );
           if (  fd == -1 )
           {
           ret_val= -1;
           }
           }
          
           /*
           * compute formatting parameters
           */
           if (  ret_val == 0 ) {
           ret_val = msdos_format_determine_fmt_params(  dd,  rqdata,  &fmt_params );
           }
           /*
           * if requested,   write whole disk/partition with 0xe5
           */
           if (  (  ret_val == 0 ) &&
           (  rqdata != NULL ) &&
           !(  rqdata->quick_format ) ) {
           ret_val = msdos_format_fill_sectors
           (  rqdata,  
           fd,  
           0,   /* start sector */
           fmt_params.totl_sector_cnt,   /* sector count */
           fmt_params.bytes_per_sector,  
           0xe5 );
           }
           /*
           * create master boot record
           */
           if (  ret_val == 0 ) {
           /*
           * Read the current MBR to obtain the partition table.
           */
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,  
           "read MRB sector\n" );
           ret_val = msdos_format_read_sec(  fd,  
           0,  
           fmt_params.bytes_per_sector,  
           tmp_sec );
           if (  ret_val == 0 ) {
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,  
           "generate MRB sector\n" );
           ret_val = msdos_format_gen_mbr(  tmp_sec,  &fmt_params );
           }
          
           /*
           * write master boot record to disk
           * also write copy of MBR to disk
           */
           if (  ret_val == 0 ) {
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,  
           "write MRB sector\n" );
           ret_val = msdos_format_write_sec(  fd,  
           0,  
           fmt_params.bytes_per_sector,  
           tmp_sec );
           }
           if (  (  ret_val == 0 ) &&
           (  fmt_params.mbr_copy_sec != 0 ) ) {
           /*
           * write copy of MBR
           */
           msdos_format_printf (  rqdata,   MSDOS_FMT_INFO_LEVEL_DETAIL,  
           "write back up MRB sector\n" );
           ret_val = msdos_format_write_sec(  fd,  
           fmt_params.mbr_copy_sec ,  
           fmt_params.bytes_per_sector,  
           tmp_sec );
           }
           }
           /*
           * for FAT32: initialize info sector on disk
           */
           if (  (  ret_val == 0 ) &&
           (  fmt_params.fsinfo_sec != 0 ) ) {
           ret_val = msdos_format_gen_fsinfo(  tmp_sec );
           }
           /*
           * write fsinfo sector
           */
           if (  (  ret_val == 0 ) &&
           (  fmt_params.fsinfo_sec != 0 ) ) {
           ret_val = msdos_format_write_sec(  fd,  
           fmt_params.fsinfo_sec,  
           fmt_params.bytes_per_sector,  
           tmp_sec );
           }
           /*
           * write FAT as all empty
           * -> write all FAT sectors as zero
           */
           if (  ret_val == 0 ) {
           ret_val = msdos_format_fill_sectors
           (  rqdata,  
           fd,  
           fmt_params.rsvd_sector_cnt,   /* start sector */
           fmt_params.fat_num*fmt_params.sectors_per_fat,  /* sector count */
           fmt_params.bytes_per_sector,  
           0x00 );
           }
           /*
           * clear/init root directory
           * -> write all directory sectors as 0x00
           */
           if (  ret_val == 0 ) {
           ret_val = msdos_format_fill_sectors
           (  rqdata,  
           fd,  
           fmt_params.root_dir_start_sec,   /* start sector */
           fmt_params.root_dir_fmt_sec_cnt,   /* sector count */
           fmt_params.bytes_per_sector,  
           0x00 );
           }
           /*
           * write volume label to first entry of directory
           */
           if (  (  ret_val == 0 ) && fmt_params.VolLabel_present ) {
           memset(  tmp_sec,  0,  sizeof(  tmp_sec ) );
           memcpy(  MSDOS_DIR_NAME(  tmp_sec ),  fmt_params.VolLabel,  MSDOS_SHORT_NAME_LEN );
           *MSDOS_DIR_ATTR(  tmp_sec ) = MSDOS_ATTR_VOLUME_ID;
           ret_val = msdos_format_write_sec
           (  fd,  
           fmt_params.root_dir_start_sec,  
           fmt_params.bytes_per_sector,  
           tmp_sec );
           }
           /*
           * write FAT entry 0 as (  0xffffff00|Media_type )EOC,  
           * write FAT entry 1 as EOC
           * allocate directory in a FAT32 FS
           */
           if (  (  ret_val == 0 ) && fmt_params.VolLabel_present ){
           /*
           * empty sector: all clusters are free/do not link further on
           */
           memset(  tmp_sec,  0,  sizeof(  tmp_sec ) );
          
           switch(  fmt_params.fattype ) {
           case FAT_FAT12:
           /* LSBits of FAT entry 0: media_type */
           FAT_SET_VAL8(  tmp_sec,  0,  (  fmt_params.media_code ) );
           /* MSBits of FAT entry 0:0xf,   LSBits of FAT entry 1: LSB of EOC */
           FAT_SET_VAL8(  tmp_sec,  1,  (  0x0f | (  FAT_FAT12_EOC << 4 ) ) );
           /* MSBits of FAT entry 1: MSBits of EOC */
           FAT_SET_VAL8(  tmp_sec,  2,  (  FAT_FAT12_EOC >> 4 ) );
           break;
          
           case FAT_FAT16:
           /* FAT entry 0: 0xff00|media_type */
           FAT_SET_VAL16(  tmp_sec,  0,  0xff00|fmt_params.media_code );
           /* FAT entry 1: EOC */
           FAT_SET_VAL16(  tmp_sec,  2,  FAT_FAT16_EOC );
           break;
          
           case FAT_FAT32:
           /* FAT entry 0: 0xffffff00|media_type */
           FAT_SET_VAL32(  tmp_sec,  0,  0xffffff00|fmt_params.media_code );
           /* FAT entry 1: EOC */
           FAT_SET_VAL32(  tmp_sec,  4,  FAT_FAT32_EOC );
           break;
          
           default:
           ret_val = -1;
           errno = EINVAL;
           }
           if (  fmt_params.fattype == FAT_FAT32 ) {
           /*
           * only first valid cluster (  cluster number 2 ) belongs
           * to root directory,   and is end of chain
           * mark this in every copy of the FAT
           */
           FAT_SET_VAL32(  tmp_sec,  8,  FAT_FAT32_EOC );
           }
           for (  i = 0;
           (  i < fmt_params.fat_num ) && (  ret_val == 0 );
           i++ ) {
           ret_val = msdos_format_write_sec
           (  fd,  
           fmt_params.rsvd_sector_cnt
           + (  i * fmt_params.sectors_per_fat ),  
           fmt_params.bytes_per_sector,  
           tmp_sec );
           }
           }
           /*
           * cleanup:
           * sync and unlock disk
           * free any data structures (  not needed now )
           */
           if (  fd != -1 ) {
           close(  fd );
           }
           if (  dd != NULL ) {
           rtems_disk_release(  dd );
           }
           return ret_val;
          }

libfs/src/dosfs/msdos_free.c

       1  /*
           * Free node handler implementation for the filesystem
           * operations table.
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_free.c,  v 1.6 2008/07/29 02:21:14 ccj Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          
          #include <errno.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          #include "msdos.h"
          
          /* msdos_free_node_info --
           * Call fat-file close routine.
           *
           * PARAMETERS:
           * pathloc - node description
           *
           * RETURNS:
           * RC_OK on success,   or -1 code if error occured
           *
           */
          int
      41  msdos_free_node_info(  rtems_filesystem_location_info_t *pathloc )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           rc = fat_file_close(  pathloc->mt_entry,   pathloc->node_access );
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
          }

libfs/src/dosfs/msdos_fsunmount.c

       1  /*
           * MSDOS shut down handler implementation
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_fsunmount.c,  v 1.6 2010/07/04 14:53:46 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <stdlib.h>
          #include <stdio.h>
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          #include "msdos.h"
          
          /* msdos_shut_down --
           * Shut down MSDOS filesystem - free all allocated resources (  don't
           * return if deallocation of some resource failed - free as much as
           * possible ).
           *
           * PARAMETERS:
           * temp_mt_entry - mount table entry
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set apropriately ).
           *
           */
          int
      46  msdos_shut_down(  rtems_filesystem_mount_table_entry_t *temp_mt_entry )
          {
           int rc = RC_OK;
           msdos_fs_info_t *fs_info = temp_mt_entry->fs_info;
           fat_file_fd_t *fat_fd = temp_mt_entry->mt_fs_root.node_access;
          
           /* close fat-file which correspondes to root directory */
           if (  fat_file_close(  temp_mt_entry,   fat_fd ) != RC_OK )
           {
           /* no return - try to free as much as possible */
           rc = -1;
           }
          
           if (  fat_shutdown_drive(  temp_mt_entry ) != RC_OK )
           {
           /* no return - try to free as much as possible */
           rc = -1;
           }
          
           rtems_semaphore_delete(  fs_info->vol_sema );
           free(  fs_info->cl_buf );
           free(  temp_mt_entry->fs_info );
          
           return rc;
          }

libfs/src/dosfs/msdos_handlers_dir.c

       1  /*
           * Directory Handlers Table for MSDOS filesystem
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_handlers_dir.c,  v 1.6 2010/07/01 20:18:40 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio.h>
          #include "msdos.h"
          
          const rtems_filesystem_file_handlers_r msdos_dir_handlers = {
           msdos_dir_open,  
           msdos_dir_close,  
           msdos_dir_read,  
           rtems_filesystem_default_write,  
           rtems_filesystem_default_ioctl,  
           msdos_dir_lseek,  
           msdos_dir_stat,  
           msdos_dir_chmod,  
           rtems_filesystem_default_ftruncate,  
           rtems_filesystem_default_fpathconf,  
           msdos_dir_sync,  
           msdos_dir_sync,  
           rtems_filesystem_default_fcntl,  
           msdos_dir_rmnod
          };

libfs/src/dosfs/msdos_handlers_file.c

       1  /*
           * File Operations Table for MSDOS filesystem
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_handlers_file.c,  v 1.6 2010/07/01 20:18:40 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio.h>
          #include "msdos.h"
          
          const rtems_filesystem_file_handlers_r msdos_file_handlers = {
           msdos_file_open,  
           msdos_file_close,  
           msdos_file_read,  
           msdos_file_write,  
           msdos_file_ioctl,  
           msdos_file_lseek,  
           msdos_file_stat,  
           msdos_file_chmod,  
           msdos_file_ftruncate,  
           rtems_filesystem_default_fpathconf,  
           msdos_file_sync,  
           msdos_file_datasync,  
           rtems_filesystem_default_fcntl,  
           msdos_file_rmnod
          };

libfs/src/dosfs/msdos_init.c

       1  /*
           * Init routine for MSDOS
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_init.c,  v 1.12 2010/06/29 19:37:28 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          #include "dosfs.h"
          #include "msdos.h"
          
          const rtems_filesystem_operations_table msdos_ops = {
           .evalpath_h = msdos_eval_path,  
           .evalformake_h = msdos_eval4make,  
           .link_h = rtems_filesystem_default_link,  
           .unlink_h = msdos_file_rmnod,  
           .node_type_h = msdos_node_type,  
           .mknod_h = msdos_mknod,  
           .chown_h = rtems_filesystem_default_chown,  
           .freenod_h = msdos_free_node_info,  
           .mount_h = rtems_filesystem_default_mount,  
           .fsmount_me_h = rtems_dosfs_initialize,  
           .unmount_h = rtems_filesystem_default_unmount,  
           .fsunmount_me_h = msdos_shut_down,  
           .utime_h = rtems_filesystem_default_utime,  
           .eval_link_h = rtems_filesystem_default_evaluate_link,  
           .symlink_h = rtems_filesystem_default_symlink,  
           .readlink_h = rtems_filesystem_default_readlink,  
           .rename_h = msdos_rename,  
           .statvfs_h = rtems_filesystem_default_statvfs
          };
          
          /* msdos_initialize --
           * MSDOS filesystem initialization. Called when mounting an
           * MSDOS filesystem.
           *
           * PARAMETERS:
           * temp_mt_entry - mount table entry
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set apropriately ).
           *
           */
      54  int rtems_dosfs_initialize(  rtems_filesystem_mount_table_entry_t *mt_entry,  
           const void *data )
          {
           int rc;
          
           rc = msdos_initialize_support(  mt_entry,  
           &msdos_ops,  
           &msdos_file_handlers,  
           &msdos_dir_handlers );
           return rc;
          }

libfs/src/dosfs/msdos_initsupp.c

       1  /*
           * MSDOS Initialization support routine implementation
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_initsupp.c,  v 1.10 2010/07/04 14:53:47 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <stdlib.h>
          #include <stdio.h>
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          #include "msdos.h"
          
          /* msdos_initialize_support --
           * MSDOS filesystem initialization
           *
           * PARAMETERS:
           * temp_mt_entry - mount table entry
           * op_table - filesystem operations table
           * file_handlers - file operations table
           * directory_handlers - directory operations table
           *
           * RETURNS:
           * RC_OK and filled temp_mt_entry on success,   or -1 if error occured
           * (  errno set apropriately )
           *
           */
          int
      48  msdos_initialize_support(  
           rtems_filesystem_mount_table_entry_t *temp_mt_entry,  
           const rtems_filesystem_operations_table *op_table,  
           const rtems_filesystem_file_handlers_r *file_handlers,  
           const rtems_filesystem_file_handlers_r *directory_handlers
            )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = NULL;
           fat_file_fd_t *fat_fd = NULL;
           fat_dir_pos_t root_pos;
           uint32_t cl_buf_size;
          
           fs_info = (  msdos_fs_info_t * )calloc(  1,   sizeof(  msdos_fs_info_t ) );
           if (  !fs_info )
           rtems_set_errno_and_return_minus_one(  ENOMEM );
          
           temp_mt_entry->fs_info = fs_info;
          
           rc = fat_init_volume_info(  temp_mt_entry );
           if (  rc != RC_OK )
           {
           free(  fs_info );
           return rc;
           }
          
           fs_info->file_handlers = file_handlers;
           fs_info->directory_handlers = directory_handlers;
          
           /*
           * open fat-file which correspondes to root directory
           * (  so inode number 0x00000010 is always used for root directory )
           */
           fat_dir_pos_init(  &root_pos );
           root_pos.sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
           rc = fat_file_open(  temp_mt_entry,   &root_pos,   &fat_fd );
           if (  rc != RC_OK )
           {
           fat_shutdown_drive(  temp_mt_entry );
           free(  fs_info );
           return rc;
           }
          
           /* again: unfortunately "fat-file" is just almost fat file :(   */
           fat_fd->fat_file_type = FAT_DIRECTORY;
           fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
           fat_fd->cln = fs_info->fat.vol.rdir_cl;
          
           fat_fd->map.file_cln = 0;
           fat_fd->map.disk_cln = fat_fd->cln;
          
           /* if we have FAT12/16 */
           if (   fat_fd->cln == 0  )
           {
           fat_fd->fat_file_size = fs_info->fat.vol.rdir_size;
           cl_buf_size = (  fs_info->fat.vol.bpc > fs_info->fat.vol.rdir_size ) ?
           fs_info->fat.vol.bpc :
           fs_info->fat.vol.rdir_size;
           }
           else
           {
           rc = fat_file_size(  temp_mt_entry,   fat_fd );
           if (   rc != RC_OK  )
           {
           fat_file_close(  temp_mt_entry,   fat_fd );
           fat_shutdown_drive(  temp_mt_entry );
           free(  fs_info );
           return rc;
           }
           cl_buf_size = fs_info->fat.vol.bpc;
           }
          
           fs_info->cl_buf = (  uint8_t * )calloc(  cl_buf_size,   sizeof(  char ) );
           if (  fs_info->cl_buf == NULL )
           {
           fat_file_close(  temp_mt_entry,   fat_fd );
           fat_shutdown_drive(  temp_mt_entry );
           free(  fs_info );
           rtems_set_errno_and_return_minus_one(  ENOMEM );
           }
          
           sc = rtems_semaphore_create(  3,  
           1,  
           RTEMS_BINARY_SEMAPHORE | RTEMS_FIFO,  
           0,  
           &fs_info->vol_sema );
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fat_file_close(  temp_mt_entry,   fat_fd );
           fat_shutdown_drive(  temp_mt_entry );
           free(  fs_info->cl_buf );
           free(  fs_info );
           rtems_set_errno_and_return_minus_one(   EIO  );
           }
          
           temp_mt_entry->mt_fs_root.node_access = fat_fd;
           temp_mt_entry->mt_fs_root.handlers = directory_handlers;
           temp_mt_entry->mt_fs_root.ops = op_table;
          
           return rc;
          }

libfs/src/dosfs/msdos_misc.c

       1  /*
           * Miscellaneous routines implementation for MSDOS filesystem
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_misc.c,  v 1.24 2010/08/23 21:29:31 joel Exp $
           */
          
          #define MSDOS_TRACE 1
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          #include <ctype.h>
          #include <sys/time.h>
          #include <unistd.h>
          #include <string.h>
          #ifdef HAVE_STRINGS_H
          #include <strings.h>
          #endif
          #include <assert.h>
          #include <rtems/libio_.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          #include "msdos.h"
          
          
          #include <stdio.h>
          
          /*
           * External strings. Saves spave this way.
           */
      43  const char *const MSDOS_DOT_NAME = ". ";
      44  const char *const MSDOS_DOTDOT_NAME = ".. ";
          
          /* msdos_is_valid_name_char --
           * Routine to check the character in a file or directory name.
           * The characters support in the short file name are letters,  
           * digits,   or characters with code points values greater than
           * 127 (  not sure what this last is ) plus the following special
           * characters "$%'-_@~`!(   ){}^#&". The must be uppercase.
           *
           * The following 6 characters are allowed in a long names,  
           * " +,  ;=[]" including a space and lower case letters.
           *
           * PARAMETERS:
           * ch - character to check.
           *
           * RETURNS:
           * MSDOS_NAME_INVALID - Not valid in a long or short name.
           * MSDOS_NAME_SHORT - Valid in a short name or long name.
           * MSDOS_NAME_LONG - Valid in a long name only.
           *
           */
          static msdos_name_type_t
      66  msdos_is_valid_name_char(  const char ch )
          {
           if (  strchr(  " +,  ;=[]",   ch ) != NULL )
           return MSDOS_NAME_LONG;
          
           if (  (  ch == '.' ) || isalnum(  (  unsigned char )ch ) ||
           (  strchr(  "$%'-_@~`!(   ){}^#&",   ch ) != NULL ) )
           return MSDOS_NAME_SHORT;
          
           return MSDOS_NAME_INVALID;
          }
          
          /* msdos_short_hex_number --
           * Routine to set the hex number in the SFN.
           *
           * PARAMETERS:
           * name - name to change
           * num - number to set
           *
           * RETURNS:
           * nothing
           *
           */
          static void
      90  msdos_short_name_hex(  char* sfn,   int num )
          {
           static const char* hex = "0123456789ABCDEF";
           char* c = MSDOS_DIR_NAME(  sfn );
           int i;
           for (  i = 0; i < 3; i++,   c++ )
           if (  (  *c == ' ' ) || (  *c == '.' ) )
           *c = '~';
           *c++ = '~';
           for (  i = 0; i < 4; i++,   c++ )
           *c = hex[(  num >> (  (  3 - i ) * 4 ) ) & 0xf];
          }
          
          /* msdos_name_type --
           * Routine the type of file name.
           *
           * PARAMETERS:
           * name - name to check
           *
           * RETURNS:
           * true the name is long,   else the name is short.
           *
           */
          #define MSDOS_NAME_TYPE_PRINT 0
          static msdos_name_type_t
     115  msdos_name_type(  const char *name,   int name_len )
          {
           bool lowercase = false;
           bool uppercase = false;
           int dot_at = -1;
           int count = 0;
          
           while (  *name && (  count < name_len ) )
           {
           bool is_dot = *name == '.';
           msdos_name_type_t type = msdos_is_valid_name_char(  *name );
          
          #if MSDOS_NAME_TYPE_PRINT
           printf (  "MSDOS_NAME_TYPE: c:%02x type:%d\n",   *name,   type );
          #endif
          
           if (  (  type == MSDOS_NAME_INVALID ) || (  type == MSDOS_NAME_LONG ) )
           return type;
          
           if (  dot_at >= 0 )
           {
           if (  is_dot || (  (  count - dot_at ) > 3 ) )
           {
          #if MSDOS_NAME_TYPE_PRINT
           printf (  "MSDOS_NAME_TYPE: LONG[1]: is_dot:%d,   at:%d cnt\n",  
           is_dot,   dot_at,   count );
          #endif
           return MSDOS_NAME_LONG;
           }
           }
           else
           {
           if (  count == 8 && !is_dot )
           {
          #if MSDOS_NAME_TYPE_PRINT
           printf (  "MSDOS_NAME_TYPE: LONG[2]: is_dot:%d,   at:%d cnt\n",  
           is_dot,   dot_at,   count );
          #endif
           return MSDOS_NAME_LONG;
           }
           }
          
           if (  is_dot )
           dot_at = count;
           else if (  (  *name >= 'A' ) && (  *name <= 'Z' ) )
           uppercase = true;
           else if (  (  *name >= 'a' ) && (  *name <= 'z' ) )
           lowercase = true;
          
           count++;
           name++;
           }
          
           if (  lowercase && uppercase )
           {
          #if MSDOS_NAME_TYPE_PRINT
           printf (  "MSDOS_NAME_TYPE: LONG[3]\n" );
          #endif
           return MSDOS_NAME_LONG;
           }
          
          #if MSDOS_NAME_TYPE_PRINT
           printf (  "MSDOS_NAME_TYPE: SHORT[1]\n" );
          #endif
           return MSDOS_NAME_SHORT;
          }
          
          /* msdos_long_to_short --
           * Routine to creates a short name from a long. Start the end of the
           *
           * PARAMETERS:
           * name - name to check
           *
           * RETURNS:
           * true the name is long,   else the name is short.
           *
           */
          #define MSDOS_L2S_PRINT 0
          msdos_name_type_t
     194  msdos_long_to_short(  const char *lfn,   int lfn_len,   char* sfn,   int sfn_len )
          {
           msdos_name_type_t type;
           int i;
          
           /*
           * Fill with spaces. This is how a short directory entry is padded.
           */
           memset (  sfn,   ' ',   sfn_len );
          
           /*
           * Handle '.' and '..' specially.
           */
           if (  (  lfn[0] == '.' ) && (  lfn_len == 1 ) )
           {
           sfn[0] = '.';
          #if MSDOS_L2S_PRINT
           printf (  "MSDOS_L2S: SHORT[1]: lfn:'%s' SFN:'%s'\n",   lfn,   sfn );
          #endif
           return MSDOS_NAME_SHORT;
           }
          
           if (  (  lfn[0] == '.' ) && (  lfn[1] == '.' ) && (  lfn_len == 2 ) )
           {
           sfn[0] = sfn[1] = '.';
          #if MSDOS_L2S_PRINT
           printf (  "MSDOS_L2S: SHORT[2]: lfn:'%s' SFN:'%s'\n",   lfn,   sfn );
          #endif
           return MSDOS_NAME_SHORT;
           }
          
           /*
           * Filenames with only blanks and dots are not allowed!
           */
           for (  i = 0; i < lfn_len; i++ )
           if (  (  lfn[i] != ' ' ) && (  lfn[i] != '.' ) )
           break;
          
           if (  i == lfn_len )
           {
          #if MSDOS_L2S_PRINT
           printf (  "MSDOS_L2S: INVALID[1]: lfn:'%s' SFN:'%s'\n",   lfn,   sfn );
          #endif
           return MSDOS_NAME_INVALID;
           }
          
           /*
           * Is this a short name ?
           */
          
           type = msdos_name_type (  lfn,   lfn_len );
          
           if (  type == MSDOS_NAME_INVALID )
           {
          #if MSDOS_L2S_PRINT
           printf (  "MSDOS_L2S: INVALID[2]: lfn:'%s' SFN:'%s'\n",   lfn,   sfn );
          #endif
           return MSDOS_NAME_INVALID;
           }
          
           msdos_filename_unix2dos (  lfn,   lfn_len,   sfn );
          
          #if MSDOS_L2S_PRINT
           printf (  "MSDOS_L2S: TYPE:%d lfn:'%s' SFN:'%s'\n",   type,   lfn,   sfn );
          #endif
           return type;
          }
          
          /* msdos_get_token --
           * Routine to get a token (  name or separator ) from the path.
           *
           * PARAMETERS:
           * path - path to get token from
           * ret_token - returned token
           * token_len - length of returned token
           *
           * RETURNS:
           * token type,   token and token length
           *
           */
          msdos_token_types_t
     275  msdos_get_token(  const char *path,  
           int pathlen,  
           const char **ret_token,  
           int *ret_token_len )
          {
           msdos_token_types_t type = MSDOS_NAME;
           int i = 0;
          
           *ret_token = NULL;
           *ret_token_len = 0;
          
           if (  pathlen == 0 )
           return MSDOS_NO_MORE_PATH;
          
           /*
           * Check for a separator.
           */
           while (  !msdos_is_separator(  path[i] ) && (  i < pathlen ) )
           {
           if (   !msdos_is_valid_name_char(  path[i] )  )
           return MSDOS_INVALID_TOKEN;
           ++i;
           if (   i == MSDOS_NAME_MAX_LFN_WITH_DOT  )
           return MSDOS_INVALID_TOKEN;
           }
          
           *ret_token = path;
          
           /*
           * If it is just a separator then it is the current dir.
           */
           if (   i == 0  )
           {
           if (   (  *path != '\0' ) && pathlen  )
           {
           i++;
           type = MSDOS_CURRENT_DIR;
           }
           else
           type = MSDOS_NO_MORE_PATH;
           }
          
           /*
           * Set the token and token_len to the token start and length.
           */
           *ret_token_len = i;
          
           /*
           * If we copied something that was not a seperator see if
           * it was a special name.
           */
           if (   type == MSDOS_NAME  )
           {
           if (  (  i == 2 ) && (  (  *ret_token )[0] == '.' ) && (  (  *ret_token )[1] == '.' ) )
           {
           type = MSDOS_UP_DIR;
           return type;
           }
          
           if (  (  i == 1 ) && (  (  *ret_token )[0] == '.' ) )
           {
           type = MSDOS_CURRENT_DIR;
           return type;
           }
           }
          
           return type;
          }
          
          
          /* msdos_find_name --
           * Find the node which correspondes to the name,   open fat-file which
           * correspondes to the found node and close fat-file which correspondes
           * to the node we searched in.
           *
           * PARAMETERS:
           * parent_loc - parent node description
           * name - name to find
           *
           * RETURNS:
           * RC_OK and updated 'parent_loc' on success,   or -1 if error
           * occured (  errno set apropriately )
           *
           */
          int
     360  msdos_find_name(  
           rtems_filesystem_location_info_t *parent_loc,  
           const char *name,  
           int name_len
            )
          {
           int rc = RC_OK;
           msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
           fat_file_fd_t *fat_fd = NULL;
           msdos_name_type_t name_type;
           fat_dir_pos_t dir_pos;
           unsigned short time_val = 0;
           unsigned short date = 0;
           char node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
          
           memset(  node_entry,   0,   MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE );
          
           name_type = msdos_long_to_short (  name,  
           name_len,  
           MSDOS_DIR_NAME(  node_entry ),  
           MSDOS_NAME_MAX );
          
           /*
           * find the node which correspondes to the name in the directory pointed by
           * 'parent_loc'
           */
           rc = msdos_get_name_node(  parent_loc,   false,   name,   name_len,   name_type,  
           &dir_pos,   node_entry );
           if (  rc != RC_OK )
           return rc;
          
           if (  (  (  *MSDOS_DIR_ATTR(  node_entry ) ) & MSDOS_ATTR_VOLUME_ID ) ||
           (  (  *MSDOS_DIR_ATTR(  node_entry ) & MSDOS_ATTR_LFN_MASK ) == MSDOS_ATTR_LFN ) )
           return MSDOS_NAME_NOT_FOUND_ERR;
          
           /* open fat-file corresponded to the found node */
           rc = fat_file_open(  parent_loc->mt_entry,   &dir_pos,   &fat_fd );
           if (  rc != RC_OK )
           return rc;
          
           fat_fd->dir_pos = dir_pos;
          
           /*
           * I don't like this if,   but: we should do it,   or should write new file
           * size and first cluster num to the disk after each write operation
           * (  even if one byte is written - that is TOO slow ) because
           * otherwise real values of these fields stored in fat-file descriptor
           * may be accidentally rewritten with wrong values stored on the disk
           */
           if (  fat_fd->links_num == 1 )
           {
           fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(  node_entry );
          
           time_val = *MSDOS_DIR_WRITE_TIME(  node_entry );
           date = *MSDOS_DIR_WRITE_DATE(  node_entry );
          
           fat_fd->mtime = msdos_date_dos2unix(  CF_LE_W(  date ),   CF_LE_W(  time_val ) );
          
           if (  (  *MSDOS_DIR_ATTR(  node_entry ) ) & MSDOS_ATTR_DIRECTORY )
           {
           fat_fd->fat_file_type = FAT_DIRECTORY;
           fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
          
           rc = fat_file_size(  parent_loc->mt_entry,   fat_fd );
           if (  rc != RC_OK )
           {
           fat_file_close(  parent_loc->mt_entry,   fat_fd );
           return rc;
           }
           }
           else
           {
           fat_fd->fat_file_size = CF_LE_L(  *MSDOS_DIR_FILE_SIZE(  node_entry ) );
           fat_fd->fat_file_type = FAT_FILE;
           fat_fd->size_limit = MSDOS_MAX_FILE_SIZE;
           }
          
           /* these data is not actual for zero-length fat-file */
           fat_fd->map.file_cln = 0;
           fat_fd->map.disk_cln = fat_fd->cln;
          
           if (  (  fat_fd->fat_file_size != 0 ) &&
           (  fat_fd->fat_file_size <= fs_info->fat.vol.bpc ) )
           {
           fat_fd->map.last_cln = fat_fd->cln;
           }
           else
           {
           fat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
           }
           }
          
           /* close fat-file corresponded to the node we searched in */
           rc = fat_file_close(  parent_loc->mt_entry,   parent_loc->node_access );
           if (  rc != RC_OK )
           {
           fat_file_close(  parent_loc->mt_entry,   fat_fd );
           return rc;
           }
          
           /* update node_info_ptr field */
           parent_loc->node_access = fat_fd;
          
           return rc;
          }
          
          /* msdos_get_name_node --
           * This routine is used in two ways: for a new node creation (  a ) or for
           * search the node which correspondes to the name parameter (  b ).
           * In case (  a ) 'name' should be set up to NULL and 'name_dir_entry' should
           * point to initialized 32 bytes structure described a new node.
           * In case (  b ) 'name' should contain a valid string.
           *
           * (  a ): reading fat-file which correspondes to directory we are going to
           * create node in. If free slot is found write contents of
           * 'name_dir_entry' into it. If reach end of fat-file and no free
           * slot found,   write 32 bytes to the end of fat-file.
           *
           * (  b ): reading fat-file which correspondes to directory and trying to
           * find slot with the name field == 'name' parameter
           *
           *
           * PARAMETERS:
           * parent_loc - node description to create node in or to find name in
           * name - NULL or name to find
           * paux - identify a node location on the disk -
           * cluster num and offset inside the cluster
           * short_dir_entry - node to create/placeholder for found node (  IN/OUT )
           *
           * RETURNS:
           * RC_OK,   filled aux_struct_ptr and name_dir_entry on success,   or -1 if
           * error occured (  errno set apropriately )
           *
           */
          int
     495  msdos_get_name_node(  
           rtems_filesystem_location_info_t *parent_loc,  
           bool create_node,  
           const char *name,  
           int name_len,  
           msdos_name_type_t name_type,  
           fat_dir_pos_t *dir_pos,  
           char *name_dir_entry
            )
          {
           int rc = RC_OK;
           fat_file_fd_t *fat_fd = parent_loc->node_access;
           uint32_t dotdot_cln = 0;
          
           /* find name in fat-file which corresponds to the directory */
           rc = msdos_find_name_in_fat_file(  parent_loc->mt_entry,   fat_fd,  
           create_node,   name,   name_len,   name_type,  
           dir_pos,   name_dir_entry );
           if (  (  rc != RC_OK ) && (  rc != MSDOS_NAME_NOT_FOUND_ERR ) )
           return rc;
          
           if (  !create_node )
           {
           /* if we search for valid name and name not found -> return */
           if (  rc == MSDOS_NAME_NOT_FOUND_ERR )
           return rc;
          
           /*
           * if we have deal with ".." - it is a special case :(  (  (  
           *
           * Really,   we should return cluster num and offset not of ".." slot,   but
           * slot which correspondes to real directory name.
           */
           if (  rc == RC_OK )
           {
           if (  strncmp(  name,   "..",   2 ) == 0 )
           {
           dotdot_cln = MSDOS_EXTRACT_CLUSTER_NUM(  (  name_dir_entry ) );
          
           /* are we right under root dir ? */
           if (  dotdot_cln == 0 )
           {
           /*
           * we can relax about first_char field - it never should be
           * used for root dir
           */
           fat_dir_pos_init(  dir_pos );
           dir_pos->sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
           }
           else
           {
           rc =
           msdos_get_dotdot_dir_info_cluster_num_and_offset(  parent_loc->mt_entry,  
           dotdot_cln,  
           dir_pos,  
           name_dir_entry );
           if (  rc != RC_OK )
           return rc;
           }
           }
           }
           }
           return rc;
          }
          
          /*
           * msdos_get_dotdot_dir_info_cluster_num_and_offset
           *
           * Unfortunately,   in general,   we cann't work here in fat-file ideologic
           * (  open fat_file "..",   get ".." and ".",   open "..",   find an entry ... )
           * because if we open
           * fat-file ".." it may happend that we have two different fat-file
           * descriptors (   for real name of directory and ".." name  ) for a single
           * file (   cluster num of both pointers to the same cluster  )
           * But...we do it because we protected by semaphore
           *
           */
          
          /* msdos_get_dotdot_dir_info_cluster_num_and_offset --
           * Get cluster num and offset not of ".." slot,   but slot which correspondes
           * to real directory name.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * cln - data cluster num extracted drom ".." slot
           * paux - identify a node location on the disk -
           * number of cluster and offset inside the cluster
           * dir_entry - placeholder for found node
           *
           * RETURNS:
           * RC_OK,   filled 'paux' and 'dir_entry' on success,   or -1 if error occured
           * (  errno set apropriately )
           *
           */
          int
     590  msdos_get_dotdot_dir_info_cluster_num_and_offset(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           uint32_t cln,  
           fat_dir_pos_t *dir_pos,  
           char *dir_entry
            )
          {
           int rc = RC_OK;
           msdos_fs_info_t *fs_info = mt_entry->fs_info;
           fat_file_fd_t *fat_fd = NULL;
           char dot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
           char dotdot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
           uint32_t cl4find = 0;
          
           /*
           * open fat-file corresponded to ".."
           */
           rc = fat_file_open(  mt_entry,   dir_pos,   &fat_fd );
           if (  rc != RC_OK )
           return rc;
          
           fat_fd->cln = cln;
           fat_fd->fat_file_type = FAT_DIRECTORY;
           fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
          
           fat_fd->map.file_cln = 0;
           fat_fd->map.disk_cln = fat_fd->cln;
          
           rc = fat_file_size(  mt_entry,   fat_fd );
           if (  rc != RC_OK )
           {
           fat_file_close(  mt_entry,   fat_fd );
           return rc;
           }
          
           /* find "." node in opened directory */
           memset(  dot_node,   0,   MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE );
           msdos_long_to_short(  ".",   1,   dot_node,   MSDOS_SHORT_NAME_LEN );
           rc = msdos_find_name_in_fat_file(  mt_entry,   fat_fd,   false,   ".",   1,  
           MSDOS_NAME_SHORT,   dir_pos,   dot_node );
          
           if (  rc != RC_OK )
           {
           fat_file_close(  mt_entry,   fat_fd );
           return rc;
           }
          
           /* find ".." node in opened directory */
           memset(  dotdot_node,   0,   MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE );
           msdos_long_to_short(  "..",   2,   dotdot_node,   MSDOS_SHORT_NAME_LEN );
           rc = msdos_find_name_in_fat_file(  mt_entry,   fat_fd,   false,   "..",   2,  
           MSDOS_NAME_SHORT,   dir_pos,  
           dotdot_node );
          
           if (  rc != RC_OK )
           {
           fat_file_close(  mt_entry,   fat_fd );
           return rc;
           }
          
           cl4find = MSDOS_EXTRACT_CLUSTER_NUM(  dot_node );
          
           /* close fat-file corresponded to ".." directory */
           rc = fat_file_close(  mt_entry,   fat_fd );
           if (   rc != RC_OK  )
           return rc;
          
           if (   (  MSDOS_EXTRACT_CLUSTER_NUM(  dotdot_node ) ) == 0 )
           {
           /*
           * we handle root dir for all FAT types in the same way with the
           * ordinary directories (   through fat_file_* calls  )
           */
           fat_dir_pos_init(  dir_pos );
           dir_pos->sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
           }
          
           /* open fat-file corresponded to second ".." */
           rc = fat_file_open(  mt_entry,   dir_pos,   &fat_fd );
           if (  rc != RC_OK )
           return rc;
          
           if (  (  MSDOS_EXTRACT_CLUSTER_NUM(  dotdot_node ) ) == 0 )
           fat_fd->cln = fs_info->fat.vol.rdir_cl;
           else
           fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(  dotdot_node );
          
           fat_fd->fat_file_type = FAT_DIRECTORY;
           fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
          
           fat_fd->map.file_cln = 0;
           fat_fd->map.disk_cln = fat_fd->cln;
          
           rc = fat_file_size(  mt_entry,   fat_fd );
           if (  rc != RC_OK )
           {
           fat_file_close(  mt_entry,   fat_fd );
           return rc;
           }
          
           /* in this directory find slot with specified cluster num */
           rc = msdos_find_node_by_cluster_num_in_fat_file(  mt_entry,   fat_fd,   cl4find,  
           dir_pos,   dir_entry );
           if (  rc != RC_OK )
           {
           fat_file_close(  mt_entry,   fat_fd );
           return rc;
           }
           rc = fat_file_close(  mt_entry,   fat_fd );
           return rc;
          }
          
          
          /* msdos_set_dir_wrt_time_and_date --
           * Write last write date and time for a file to the disk (  to corresponded
           * 32bytes node )
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set apropriately ).
           *
           */
          int
     716  msdos_set_dir_wrt_time_and_date(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd
            )
          {
           ssize_t ret1 = 0,   ret2 = 0;
           msdos_fs_info_t *fs_info = mt_entry->fs_info;
           uint16_t time_val;
           uint16_t date;
           uint32_t sec = 0;
           uint32_t byte = 0;
          
           msdos_date_unix2dos(  fat_fd->mtime,   &date,   &time_val );
          
           /*
           * calculate input for _fat_block_write: convert (  cluster num,   offset ) to
           * (  sector num,   new offset )
           */
           sec = fat_cluster_num_to_sector_num(  mt_entry,   fat_fd->dir_pos.sname.cln );
           sec += (  fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2 );
           /* byte points to start of 32bytes structure */
           byte = fat_fd->dir_pos.sname.ofs & (  fs_info->fat.vol.bps - 1 );
          
           time_val = CT_LE_W(  time_val );
           ret1 = _fat_block_write(  mt_entry,   sec,   byte + MSDOS_FILE_WTIME_OFFSET,  
           2,   (  char * )(  &time_val ) );
           date = CT_LE_W(  date );
           ret2 = _fat_block_write(  mt_entry,   sec,   byte + MSDOS_FILE_WDATE_OFFSET,  
           2,   (  char * )(  &date ) );
          
           if (   (  ret1 < 0 ) || (  ret2 < 0 )  )
           return -1;
          
           return RC_OK;
          }
          
          /* msdos_set_first_cluster_num --
           * Write number of first cluster of the file to the disk (  to corresponded
           * 32bytes slot )
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured
           *
           */
          int
     765  msdos_set_first_cluster_num(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd
            )
          {
           ssize_t ret1 = 0,   ret2 = 0;
           msdos_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t new_cln = fat_fd->cln;
           uint16_t le_cl_low = 0;
           uint16_t le_cl_hi = 0;
           uint32_t sec = 0;
           uint32_t byte = 0;
          
           /*
           * calculate input for _fat_block_write: convert (  cluster num,   offset ) to
           * (  sector num,   new offset )
           */
           sec = fat_cluster_num_to_sector_num(  mt_entry,   fat_fd->dir_pos.sname.cln );
           sec += (  fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2 );
           /* byte from points to start of 32bytes structure */
           byte = fat_fd->dir_pos.sname.ofs & (  fs_info->fat.vol.bps - 1 );
          
           le_cl_low = CT_LE_W(  (  uint16_t  )(  new_cln & 0x0000FFFF ) );
           ret1 = _fat_block_write(  mt_entry,   sec,  
           byte + MSDOS_FIRST_CLUSTER_LOW_OFFSET,   2,  
           (  char * )(  &le_cl_low ) );
           le_cl_hi = CT_LE_W(  (  uint16_t  )(  (  new_cln & 0xFFFF0000 ) >> 16 ) );
           ret2 = _fat_block_write(  mt_entry,   sec,  
           byte + MSDOS_FIRST_CLUSTER_HI_OFFSET,   2,  
           (  char * )(  &le_cl_hi ) );
           if (   (  ret1 < 0 ) || (  ret2 < 0 )  )
           return -1;
          
           return RC_OK;
          }
          
          
          /* msdos_set_file size --
           * Write file size of the file to the disk (  to corresponded 32bytes slot )
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set apropriately ).
           *
           */
          int
     814  msdos_set_file_size(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd
            )
          {
           ssize_t ret = 0;
           msdos_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t le_new_length = 0;
           uint32_t sec = 0;
           uint32_t byte = 0;
          
           sec = fat_cluster_num_to_sector_num(  mt_entry,   fat_fd->dir_pos.sname.cln );
           sec += (  fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2 );
           byte = (  fat_fd->dir_pos.sname.ofs & (  fs_info->fat.vol.bps - 1 ) );
          
           le_new_length = CT_LE_L(  (  fat_fd->fat_file_size ) );
           ret = _fat_block_write(  mt_entry,   sec,   byte + MSDOS_FILE_SIZE_OFFSET,   4,  
           (  char * )(  &le_new_length ) );
           if (   ret < 0  )
           return -1;
          
           return RC_OK;
          }
          
          /*
           * We should not check whether this routine is called for root dir - it
           * never can happend
           */
          
          /* msdos_set_first_char4file_name --
           * Write first character of the name of the file to the disk (  to
           * corresponded 32bytes slot )
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * cl - number of cluster
           * ofs - offset inside cluster
           * fchar - character to set up
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set apropriately )
           *
           */
          int
     858  msdos_set_first_char4file_name(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_dir_pos_t *dir_pos,  
           unsigned char fchar
            )
          {
           ssize_t ret;
           msdos_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t dir_block_size;
           fat_pos_t start = dir_pos->lname;
           fat_pos_t end = dir_pos->sname;
          
           if (  (  end.cln == fs_info->fat.vol.rdir_cl ) &&
           (  fs_info->fat.vol.type & (  FAT_FAT12 | FAT_FAT16 ) ) )
           dir_block_size = fs_info->fat.vol.rdir_size;
           else
           dir_block_size = fs_info->fat.vol.bpc;
          
           if (  dir_pos->lname.cln == FAT_FILE_SHORT_NAME )
           start = dir_pos->sname;
          
           /*
           * We handle the changes directly due the way the short file
           * name code was written rather than use the fat_file_write
           * interface.
           */
           while (  true )
           {
           uint32_t sec = (  fat_cluster_num_to_sector_num(  mt_entry,   start.cln ) +
           (  start.ofs >> fs_info->fat.vol.sec_log2 ) );
           uint32_t byte = (  start.ofs & (  fs_info->fat.vol.bps - 1 ) );;
          
           ret = _fat_block_write(  mt_entry,   sec,   byte + MSDOS_FILE_NAME_OFFSET,   1,  
           &fchar );
           if (  ret < 0 )
           return -1;
          
           if (  (  start.cln == end.cln ) && (  start.ofs == end.ofs ) )
           break;
          
           start.ofs += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
           if (  start.ofs >= dir_block_size )
           {
           int rc;
           if (  (  end.cln == fs_info->fat.vol.rdir_cl ) &&
           (  fs_info->fat.vol.type & (  FAT_FAT12 | FAT_FAT16 ) ) )
           break;
           rc = fat_get_fat_cluster(  mt_entry,   start.cln,   &start.cln );
           if (   rc != RC_OK  )
           return rc;
           start.ofs = 0;
           }
           }
          
           return RC_OK;
          }
          
          /* msdos_dir_is_empty --
           * Check whether directory which correspondes to the fat-file descriptor is
           * empty.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           * ret_val - placeholder for result
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured
           *
           */
          int
     929  msdos_dir_is_empty(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd,  
           bool *ret_val
            )
          {
           ssize_t ret = 0;
           msdos_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t j = 0,   i = 0;
          
           /* dir is not empty */
           *ret_val = false;
          
           while (  (  ret = fat_file_read(  mt_entry,   fat_fd,   j * fs_info->fat.vol.bps,  
           fs_info->fat.vol.bps,  
           fs_info->cl_buf ) ) != FAT_EOF )
           {
           if (  ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE )
           return -1;
          
           assert(  ret == fs_info->fat.vol.bps );
          
           /* have to look at the DIR_NAME as "raw" 8-bit data */
           for (  i = 0;
           i < fs_info->fat.vol.bps;
           i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE )
           {
           char* entry = (  char* ) fs_info->cl_buf + i;
          
           /*
           * If the entry is empty,   a long file name entry,   or '.' or '..'
           * then consider it as empty.
           *
           * Just ignore long file name entries. They must have a short entry to
           * be valid.
           */
           if (  (  (  *MSDOS_DIR_ENTRY_TYPE(  entry ) ) ==
           MSDOS_THIS_DIR_ENTRY_EMPTY ) ||
           (  (  *MSDOS_DIR_ATTR(  entry ) & MSDOS_ATTR_LFN_MASK ) ==
           MSDOS_ATTR_LFN ) ||
           (  strncmp(  MSDOS_DIR_NAME(  (  entry ) ),   MSDOS_DOT_NAME,  
           MSDOS_SHORT_NAME_LEN ) == 0 ) ||
           (  strncmp(  MSDOS_DIR_NAME(  (  entry ) ),  
           MSDOS_DOTDOT_NAME,  
           MSDOS_SHORT_NAME_LEN ) == 0 ) )
           continue;
          
           /*
           * Nothing more to look at.
           */
           if (  (  *MSDOS_DIR_NAME(  entry ) ) ==
           MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY )
           {
           *ret_val = true;
           return RC_OK;
           }
          
           /*
           * Short file name entries mean not empty.
           */
           return RC_OK;
           }
           j++;
           }
           *ret_val = true;
           return RC_OK;
          }
          
          /* msdos_create_name_in_fat_file --
           * This routine creates an entry in the fat file for the file name
           * provided by the user. The directory entry passed is the short
           * file name and is added as it. If the file name is long a long
           * file name set of entries is added.
           *
           * Scan the directory for the file and if not found add the new entry.
           * When scanning remember the offset in the file where the directory
           * entry can be added.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           * name - NULL or name to find
           * paux - identify a node location on the disk -
           * number of cluster and offset inside the cluster
           * name_dir_entry - node to create/placeholder for found node
           *
           * RETURNS:
           * RC_OK on success,   or error code if error occured (  errno set
           * appropriately )
           *
           */
          #define MSDOS_FIND_PRINT 0
    1021  int msdos_find_name_in_fat_file(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd,  
           bool create_node,  
           const char *name,  
           int name_len,  
           msdos_name_type_t name_type,  
           fat_dir_pos_t *dir_pos,  
           char *name_dir_entry
            )
          {
           ssize_t ret = 0;
           msdos_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t dir_offset = 0;
           uint32_t dir_entry = 0;
           uint32_t bts2rd = 0;
           fat_pos_t lfn_start;
           bool lfn_matched = false;
           uint8_t lfn_checksum = 0;
           int lfn_entries;
           int lfn_entry = 0;
           uint32_t empty_space_offset = 0;
           uint32_t empty_space_entry = 0;
           uint32_t empty_space_count = 0;
           bool empty_space_found = false;
           uint32_t entries_per_block;
           bool read_cluster = false;
          
           assert(  name_len > 0 );
          
           fat_dir_pos_init(  dir_pos );
          
           lfn_start.cln = lfn_start.ofs = FAT_FILE_SHORT_NAME;
          
           /*
           * Set the number of short entries needed to store the LFN. If the name
           * is short still check for possible long entries with the short name.
           *
           * In PR1491 we need to have a LFN for a short file name entry. To
           * test this make this test always fail,   ie add "0 &&".
           */
           if (  create_node && (  name_type == MSDOS_NAME_SHORT ) )
           lfn_entries = 0;
           else
           lfn_entries =
           (  (  name_len - 1 ) + MSDOS_LFN_LEN_PER_ENTRY ) / MSDOS_LFN_LEN_PER_ENTRY;
          
           if (  FAT_FD_OF_ROOT_DIR(  fat_fd ) &&
           (  fs_info->fat.vol.type & (  FAT_FAT12 | FAT_FAT16 ) ) )
           bts2rd = fat_fd->fat_file_size;
           else
           bts2rd = fs_info->fat.vol.bpc;
          
           entries_per_block = bts2rd / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
          
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[1] nt:%d,   cn:%i ebp:%li bts2rd:%li lfne:%d nl:%i n:%s\n",  
           name_type,   create_node,   entries_per_block,   bts2rd,  
           lfn_entries,   name_len,   name );
          #endif
           /*
           * Scan the directory seeing if the file is present. While
           * doing this see if a suitable location can be found to
           * create the entry if the name is not found.
           */
           while (  (  ret = fat_file_read(  mt_entry,   fat_fd,   (  dir_offset * bts2rd ),  
           bts2rd,   fs_info->cl_buf ) ) != FAT_EOF )
           {
           bool remainder_empty = false;
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[2] dir_offset:%li\n",   dir_offset );
          #endif
          
           if (  ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           assert(  ret == bts2rd );
          
           /* have to look at the DIR_NAME as "raw" 8-bit data */
           for (  dir_entry = 0;
           dir_entry < bts2rd;
           dir_entry += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE )
           {
           char* entry = (  char* ) fs_info->cl_buf + dir_entry;
          
           /*
           * See if the entry is empty or the remainder of the directory is
           * empty ? Localise to make the code read better.
           */
           bool entry_empty = (  *MSDOS_DIR_ENTRY_TYPE(  entry ) ==
           MSDOS_THIS_DIR_ENTRY_EMPTY );
           remainder_empty = (  *MSDOS_DIR_ENTRY_TYPE(  entry ) ==
           MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY );
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[3] re:%i ee:%i do:%li de:%li(  %ld )\n",  
           remainder_empty,   entry_empty,   dir_offset,  
           dir_entry,   (  dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE ) );
          #endif
           /*
           * Remember where the we are,   ie the start,   so we can come back
           * to here and write the long file name if this is the start of
           * a series of empty entries. If empty_space_count is 0 then
           * we are currently not inside an empty series of entries. It
           * is a count of empty entries.
           */
           if (  empty_space_count == 0 )
           {
           empty_space_entry = dir_entry;
           empty_space_offset = dir_offset;
           }
          
           if (  remainder_empty )
           {
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[3.1] cn:%i esf:%i\n",   create_node,   empty_space_found );
          #endif
           /*
           * If just looking and there is no more entries in the
           * directory - return name-not-found
           */
           if (  !create_node )
           return MSDOS_NAME_NOT_FOUND_ERR;
          
           /*
           * Lets go and write the directory entries. If we have not found
           * any available space add the remaining number of entries to any that
           * we may have already found that are just before this entry. If more
           * are needed FAT_EOF is returned by the read and we extend the file.
           */
           if (  !empty_space_found )
           {
           empty_space_count +=
           entries_per_block - (  dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE );
           empty_space_found = true;
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[3.2] esf:%i esc%i\n",   empty_space_found,   empty_space_count );
          #endif
           }
           break;
           }
           else if (  entry_empty )
           {
           if (  create_node )
           {
           /*
           * Remainder is not empty so is this entry empty ?
           */
           empty_space_count++;
          
           if (  empty_space_count == (  lfn_entries + 1 ) )
           empty_space_found = true;
           }
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[4.1] esc:%li esf:%i\n",  
           empty_space_count,   empty_space_found );
          #endif
           }
           else
           {
           /*
           * A valid entry so handle it.
           *
           * If empty space has not been found we need to start the
           * count again.
           */
           if (  create_node && !empty_space_found )
           {
           empty_space_entry = 0;
           empty_space_count = 0;
           }
          
           /*
           * Check the attribute to see if the entry is for a long
           * file name.
           */
           if (  (  *MSDOS_DIR_ATTR(  entry ) & MSDOS_ATTR_LFN_MASK ) ==
           MSDOS_ATTR_LFN )
           {
           char* p;
           int o;
           int i;
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[4.2] lfn:%c entry:%i checksum:%i\n",  
           lfn_start.cln == FAT_FILE_SHORT_NAME ? 'f' : 't',  
           *MSDOS_DIR_ENTRY_TYPE(  entry ) & MSDOS_LAST_LONG_ENTRY_MASK,  
           *MSDOS_DIR_LFN_CHECKSUM(  entry ) );
          #endif
           /*
           * If we are not already processing a LFN see if this is
           * the first entry of a LFN ?
           */
           if (  lfn_start.cln == FAT_FILE_SHORT_NAME )
           {
           lfn_matched = false;
          
           /*
           * The first entry must have the last long entry
           * flag set.
           */
           if (  (  *MSDOS_DIR_ENTRY_TYPE(  entry ) &
           MSDOS_LAST_LONG_ENTRY ) == 0 )
           continue;
          
           /*
           * Does the number of entries in the LFN directory
           * entry match the number we expect for this
           * file name. Note we do not know the number of
           * characters in the entry so this is check further
           * on when the characters are checked.
           */
           if (  lfn_entries != (  *MSDOS_DIR_ENTRY_TYPE(  entry ) &
           MSDOS_LAST_LONG_ENTRY_MASK ) )
           continue;
          
           /*
           * Get the checksum of the short entry.
           */
           lfn_start.cln = dir_offset;
           lfn_start.ofs = dir_entry;
           lfn_entry = lfn_entries;
           lfn_checksum = *MSDOS_DIR_LFN_CHECKSUM(  entry );
          
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[4.3] lfn_checksum:%i\n",  
           *MSDOS_DIR_LFN_CHECKSUM(  entry ) );
          #endif
           }
          
           /*
           * If the entry number or the check sum do not match
           * forget this series of long directory entries. These
           * could be orphaned entries depending on the history
           * of the disk.
           */
           if (  (  lfn_entry != (  *MSDOS_DIR_ENTRY_TYPE(  entry ) &
           MSDOS_LAST_LONG_ENTRY_MASK ) ) ||
           (  lfn_checksum != *MSDOS_DIR_LFN_CHECKSUM(  entry ) ) )
           {
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[4.4] no match\n" );
          #endif
           lfn_start.cln = FAT_FILE_SHORT_NAME;
           continue;
           }
          
           lfn_entry--;
           o = lfn_entry * MSDOS_LFN_LEN_PER_ENTRY;
           p = entry + 1;
          
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[5] lfne:%i\n",   lfn_entry );
          #endif
           for (  i = 0; i < MSDOS_LFN_LEN_PER_ENTRY; i++ )
           {
          #if MSDOS_FIND_PRINT > 1
           printf (  "MSFS:[6] o:%i i:%i *p:%c(  %02x ) name[o + i]:%c(  %02x )\n",  
           o,   i,   *p,   *p,   name[o + i],   name[o + i] );
          #endif
           if (  *p == '\0' )
           {
           /*
           * If this is the first entry,   ie the last part of the
           * long file name and the length does not match then
           * the file names do not match.
           */
           if (  (  (  lfn_entry + 1 ) == lfn_entries ) &&
           (  (  o + i ) != name_len ) )
           lfn_start.cln = FAT_FILE_SHORT_NAME;
           break;
           }
          
           if (  (  (  o + i ) >= name_len ) || (  *p != name[o + i] ) )
           {
           lfn_start.cln = FAT_FILE_SHORT_NAME;
           break;
           }
          
           switch (  i )
           {
           case 4:
           p += 5;
           break;
           case 10:
           p += 4;
           break;
           default:
           p += 2;
           break;
           }
           }
          
           lfn_matched = (  (  lfn_entry == 0 ) &&
           (  lfn_start.cln != FAT_FILE_SHORT_NAME ) );
          
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[8.1] lfn_matched:%i\n",   lfn_matched );
          #endif
           }
           else
           {
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[9.1] SFN entry,   lfn_matched:%i\n",   lfn_matched );
          #endif
           /*
           * SFN entry found.
           *
           * If a LFN has been found and it matched check the
           * entries have all been found and the checksum is
           * correct. If this is the case return the short file
           * name entry.
           */
           if (  lfn_matched )
           {
           uint8_t cs = 0;
           uint8_t* p = (  uint8_t* ) MSDOS_DIR_NAME(  entry );
           int i;
          
           for (  i = 0; i < MSDOS_SHORT_NAME_LEN; i++,   p++ )
           cs = (  (  cs & 1 ) ? 0x80 : 0 ) + (  cs >> 1 ) + *p;
          
           if (  lfn_entry || (  lfn_checksum != cs ) )
           lfn_matched = false;
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[9.2] checksum,   lfn_matched:%i,   lfn_entry:%i,   lfn_checksum:%02x/%02x\n",  
           lfn_matched,   lfn_entry,   lfn_checksum,   cs );
          #endif
           }
          
           /*
           * If the long file names matched or the file name is
           * short and they match then we have the entry. We will not
           * match a long file name against a short file name because
           * a long file name that generates a matching short file
           * name is not a long file name.
           */
           if (  lfn_matched ||
           (  (  name_type == MSDOS_NAME_SHORT ) &&
           (  lfn_start.cln == FAT_FILE_SHORT_NAME ) &&
           (  memcmp(  MSDOS_DIR_NAME(  entry ),  
           MSDOS_DIR_NAME(  name_dir_entry ),  
           MSDOS_SHORT_NAME_LEN ) == 0 ) ) )
           {
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[9.3] SNF found\n" );
          #endif
           /*
           * We get the entry we looked for - fill the position
           * structure and the 32 bytes of the short entry
           */
           int rc = fat_file_ioctl(  mt_entry,   fat_fd,   F_CLU_NUM,  
           dir_offset * bts2rd,  
           &dir_pos->sname.cln );
           if (  rc != RC_OK )
           return rc;
          
           dir_pos->sname.ofs = dir_entry;
          
           if (  lfn_start.cln != FAT_FILE_SHORT_NAME )
           {
           rc = fat_file_ioctl(  mt_entry,   fat_fd,   F_CLU_NUM,  
           lfn_start.cln * bts2rd,  
           &lfn_start.cln );
           if (  rc != RC_OK )
           return rc;
           }
          
           dir_pos->lname.cln = lfn_start.cln;
           dir_pos->lname.ofs = lfn_start.ofs;
          
           memcpy(  name_dir_entry,   entry,  
           MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE );
           return RC_OK;
           }
          
           lfn_start.cln = FAT_FILE_SHORT_NAME;
           lfn_matched = false;
           }
           }
           }
          
           if (  remainder_empty )
           break;
          
           dir_offset++;
           }
          
           /*
           * If we are not to create the entry return a not found error.
           */
           if (  !create_node )
           return MSDOS_NAME_NOT_FOUND_ERR;
          
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[8.1] WRITE do:%ld esc:%ld eso:%ld ese:%ld\n",  
           dir_offset,   empty_space_count,   empty_space_offset,   empty_space_entry );
          #endif
          
           /*
           * If a long file name calculate the checksum of the short file name
           * data to place in each long file name entry. First set the short
           * file name to the slot of the SFN entry. This will mean no clashes
           * in this directory.
           */
           lfn_checksum = 0;
           if (  name_type == MSDOS_NAME_LONG )
           {
           int slot = (  (  (  empty_space_offset * bts2rd ) + empty_space_entry ) /
           MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE ) + lfn_entries + 1;
           msdos_short_name_hex(  MSDOS_DIR_NAME(  name_dir_entry ),   slot );
           }
          
           if (  lfn_entries )
           {
           uint8_t* p = (  uint8_t* ) MSDOS_DIR_NAME(  name_dir_entry );
           int i;
           for (  i = 0; i < 11; i++,   p++ )
           lfn_checksum =
           (  (  lfn_checksum & 1 ) ? 0x80 : 0 ) + (  lfn_checksum >> 1 ) + *p;
           }
          
           /*
           * If there is no space available then extend the file. The
           * empty_space_count is a count of empty entries in the currently
           * read cluster so if 0 there is no space. Note,   dir_offset will
           * be at the next cluster so we can just make empty_space_offset
           * that value.
           */
           if (  empty_space_count == 0 )
           {
           read_cluster = true;
           empty_space_offset = dir_offset;
           empty_space_entry = 0;
           }
          
           /*
           * Have we read past the empty block ? If so go back and read it again.
           */
           if (  dir_offset != empty_space_offset )
           read_cluster = true;
          
           /*
           * Handle the entry writes.
           */
           lfn_start.cln = lfn_start.ofs = FAT_FILE_SHORT_NAME;
           lfn_entry = 0;
          
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[9] read_cluster:%d eso:%ld ese:%ld\n",  
           read_cluster,   empty_space_offset,   empty_space_entry );
          #endif
          
           /*
           * The one more is the short entry.
           */
           while (  lfn_entry < (  lfn_entries + 1 ) )
           {
           int length = 0;
          
           if (  read_cluster )
           {
           uint32_t new_length;
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[9.1] eso:%li\n",   empty_space_offset );
          #endif
           ret = fat_file_read(  mt_entry,   fat_fd,  
           (  empty_space_offset * bts2rd ),   bts2rd,  
           fs_info->cl_buf );
          
           if (  ret != bts2rd )
           {
           if (  ret != FAT_EOF )
           rtems_set_errno_and_return_minus_one(  EIO );
          
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[9.2] extending file:%li\n",   empty_space_offset );
          #endif
           ret = fat_file_extend (  mt_entry,   fat_fd,   empty_space_offset * bts2rd,  
           &new_length );
          
           if (  ret != RC_OK )
           return ret;
          
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[9.3] extended: %d <-> %d\n",   new_length,   empty_space_offset * bts2rd );
          #endif
           if (  new_length != (  empty_space_offset * bts2rd ) )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           memset(  fs_info->cl_buf,   0,   bts2rd );
          
           ret = fat_file_write(  mt_entry,   fat_fd,  
           empty_space_offset * bts2rd,  
           bts2rd,   fs_info->cl_buf );
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[9.4] clear write: %d\n",   ret );
          #endif
           if (  ret == -1 )
           return ret;
           else if (  ret != bts2rd )
           rtems_set_errno_and_return_minus_one(  EIO );
           }
           }
          
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[10] eso:%li\n",   empty_space_offset );
          #endif
          
           for (  dir_entry = empty_space_entry;
           dir_entry < bts2rd;
           dir_entry += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE )
           {
           char* entry = (  char* ) fs_info->cl_buf + dir_entry;
           char* p;
           const char* n;
           int i;
          
           length += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
           lfn_entry++;
          
          #if MSDOS_FIND_PRINT
           printf (  "MSFS:[10] de:%li(  %li ) length:%i lfn_entry:%i\n",  
           dir_entry,   (  dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE ),  
           length,   lfn_entry );
          #endif
           /*
           * Time to write the short file name entry.
           */
           if (  lfn_entry == (  lfn_entries + 1 ) )
           {
           /* get current cluster number */
           int rc = fat_file_ioctl(  mt_entry,   fat_fd,   F_CLU_NUM,  
           empty_space_offset * bts2rd,  
           &dir_pos->sname.cln );
           if (  rc != RC_OK )
           return rc;
          
           dir_pos->sname.ofs = dir_entry;
          
           if (  lfn_start.cln != FAT_FILE_SHORT_NAME )
           {
           rc = fat_file_ioctl(  mt_entry,   fat_fd,   F_CLU_NUM,  
           lfn_start.cln * bts2rd,  
           &lfn_start.cln );
           if (  rc != RC_OK )
           return rc;
           }
          
           dir_pos->lname.cln = lfn_start.cln;
           dir_pos->lname.ofs = lfn_start.ofs;
          
           /* write new node entry */
           memcpy (  entry,   (  uint8_t * ) name_dir_entry,  
           MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE );
           break;
           }
          
           /*
           * This is a long file name and we need to write
           * a long file name entry. See if this is the
           * first entry written and if so remember the
           * the location of the long file name.
           */
           if (  lfn_start.cln == FAT_FILE_SHORT_NAME )
           {
           lfn_start.cln = empty_space_offset;
           lfn_start.ofs = dir_entry;
           }
          
           /*
           * Clear the entry before loading the data.
           */
           memset (  entry,   0,   MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE );
          
           *MSDOS_DIR_LFN_CHECKSUM(  entry ) = lfn_checksum;
          
           p = entry + 1;
           n = name + (  lfn_entries - lfn_entry ) * MSDOS_LFN_LEN_PER_ENTRY;
          
           for (  i = 0; i < MSDOS_LFN_LEN_PER_ENTRY; i++ )
           {
           *p = *n;
           if (  *n != 0 )
           n++;
          
           switch (  i )
           {
           case 4:
           p += 5;
           break;
           case 10:
           p += 4;
           break;
           default:
           p += 2;
           break;
           }
           }
          
           *MSDOS_DIR_ENTRY_TYPE(  entry ) = (  lfn_entries - lfn_entry ) + 1;
           if (  lfn_entry == 1 )
           *MSDOS_DIR_ENTRY_TYPE(  entry ) |= MSDOS_LAST_LONG_ENTRY;
           *MSDOS_DIR_ATTR(  entry ) |= MSDOS_ATTR_LFN;
           }
          
           ret = fat_file_write(  mt_entry,   fat_fd,  
           (  empty_space_offset * bts2rd ) + empty_space_entry,  
           length,   fs_info->cl_buf + empty_space_entry );
           if (  ret == -1 )
           return ret;
           else if (  ret != length )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           empty_space_offset++;
           empty_space_entry = 0;
           read_cluster = true;
           }
          
           return 0;
          }
          
          /* msdos_find_node_by_cluster_num_in_fat_file --
           * Find node with specified number of cluster in fat-file.
           *
           * Note,   not updated in the LFN change because it is only used
           * for . and .. entries and these are always short.
           *
           * PARAMETERS:
           * mt_entry - mount table entry
           * fat_fd - fat-file descriptor
           * cl4find - number of cluster to find
           * paux - identify a node location on the disk -
           * cluster num and offset inside the cluster
           * dir_entry - placeholder for found node
           *
           * RETURNS:
           * RC_OK on success,   or error code if error occured
           *
           */
    1659  int msdos_find_node_by_cluster_num_in_fat_file(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           fat_file_fd_t *fat_fd,  
           uint32_t cl4find,  
           fat_dir_pos_t *dir_pos,  
           char *dir_entry
            )
          {
           int rc = RC_OK;
           ssize_t ret = 0;
           msdos_fs_info_t *fs_info = mt_entry->fs_info;
           uint32_t bts2rd = 0;
           uint32_t i = 0,   j = 0;
          
           if (  FAT_FD_OF_ROOT_DIR(  fat_fd ) &&
           (  fs_info->fat.vol.type & (  FAT_FAT12 | FAT_FAT16 ) ) )
           bts2rd = fat_fd->fat_file_size;
           else
           bts2rd = fs_info->fat.vol.bpc;
          
           while (  (  ret = fat_file_read(  mt_entry,   fat_fd,   j * bts2rd,   bts2rd,  
           fs_info->cl_buf ) ) != FAT_EOF )
           {
           if (   ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE  )
           rtems_set_errno_and_return_minus_one(   EIO  );
          
           assert(  ret == bts2rd );
          
           for (  i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE )
           {
           char* entry = (  char* ) fs_info->cl_buf + i;
          
           /* if this and all rest entries are empty - return not-found */
           if (  (  *MSDOS_DIR_ENTRY_TYPE(  entry ) ) ==
           MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY )
           return MSDOS_NAME_NOT_FOUND_ERR;
          
           /* if this entry is empty - skip it */
           if (  (  *MSDOS_DIR_ENTRY_TYPE(  entry ) ) ==
           MSDOS_THIS_DIR_ENTRY_EMPTY )
           continue;
          
           /* if get a non-empty entry - compare clusters num */
           if (  MSDOS_EXTRACT_CLUSTER_NUM(  entry ) == cl4find )
           {
           /* on success fill aux structure and copy all 32 bytes */
           rc = fat_file_ioctl(  mt_entry,   fat_fd,   F_CLU_NUM,   j * bts2rd,  
           &dir_pos->sname.cln );
           if (  rc != RC_OK )
           return rc;
          
           dir_pos->sname.ofs = i;
           dir_pos->lname.cln = FAT_FILE_SHORT_NAME;
           dir_pos->lname.ofs = FAT_FILE_SHORT_NAME;
          
           memcpy(  dir_entry,   entry,  
           MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE );
           return RC_OK;
           }
           }
           j++;
           }
           return MSDOS_NAME_NOT_FOUND_ERR;
          }

libfs/src/dosfs/msdos_mknod.c

       1  /*
           * Routine for node creation in MSDOS filesystem.
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_mknod.c,  v 1.9 2009/11/29 13:18:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <rtems.h>
          
          #include <rtems/libio_.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          #include "msdos.h"
          
          /* msdos_mknod --
           * The following function checks spelling and formats name for a new node,  
           * determines type of the node to be created and creates it.
           *
           * PARAMETERS:
           * name - file name to create
           * mode - node type
           * dev - dev
           * pathloc - parent directory description
           *
           * RETURNS:
           * RC_OK on succes,   or -1 if error occured and set errno
           *
           */
      48  int msdos_mknod(  
           const char *name,  
           mode_t mode,  
           dev_t dev,  
           rtems_filesystem_location_info_t *pathloc
           )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
           msdos_token_types_t type = 0;
          
           /*
           * Figure out what type of msdos node this is.
           */
           if (  S_ISDIR(  mode ) )
           {
           type = MSDOS_DIRECTORY;
           }
           else if (  S_ISREG(  mode ) )
           {
           type = MSDOS_REGULAR_FILE;
           }
           else
           rtems_set_errno_and_return_minus_one(  EINVAL );
          
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           /* Create an MSDOS node */
           rc = msdos_creat_node(  pathloc,   type,   name,   strlen(  name ),   mode,   NULL );
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
          }

libfs/src/dosfs/msdos_node_type.c

       1  /*
           * The following returns the type of node that the loc refers to.
           *
           * Copyright (  C ) 2001 OKTET Ltd.,   St.-Petersburg,   Russia
           * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_node_type.c,  v 1.3 2004/04/17 08:34:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <rtems.h>
          
          #include <rtems/libio_.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          #include "msdos.h"
          
          /* msdos_node_type --
           * Determine type of the node that the pathloc refers to.
           *
           * PARAMETERS:
           * pathloc - node description
           *
           * RETURNS:
           * node type
           *
           */
          rtems_filesystem_node_types_t
      45  msdos_node_type(  rtems_filesystem_location_info_t *pathloc )
          {
           fat_file_fd_t *fat_fd;
          
           /*
           * we don't need to obtain the volume semaphore here because node_type_h
           * call always follows evalpath_h call(  hence link increment occured ) and
           * hence node_access memory can't be freed during processing node_type_h
           * call
           */
           fat_fd = pathloc->node_access;
          
           return fat_fd->fat_file_type;
          }

libfs/src/dosfs/msdos_rename.c

       1  /*
           * Routine to rename a MSDOS filesystem node
           *
           * Copyright (  C ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * @(  # ) $Id: msdos_rename.c,  v 1.2 2010/07/04 14:53:47 joel Exp $
           *
           */
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <rtems/libio_.h>
          #include <time.h>
          
          #include "fat.h"
          #include "fat_fat_operations.h"
          #include "fat_file.h"
          
          #include "msdos.h"
          
          /* msdos_rename --
           * Rename the node by removing the exitsing directory entry and creating a
           * new one.
           *
           * PARAMETERS:
           * old_parent_loc - node description for the "old parent" node
           * old_loc - node description for the "old" node
           * new_parent_loc - node description for the "parent" node
           * name - name of new node
           *
           * RETURNS:
           * RC_OK on success,   or -1 if error occured (  errno set appropriately )
           */
          int
      44  msdos_rename(  rtems_filesystem_location_info_t *old_parent_loc,  
           rtems_filesystem_location_info_t *old_loc,  
           rtems_filesystem_location_info_t *new_parent_loc,  
           const char *new_name )
          {
           int rc = RC_OK;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           msdos_fs_info_t *fs_info = new_parent_loc->mt_entry->fs_info;
           fat_file_fd_t *old_fat_fd = old_loc->node_access;
           const char *token;
           int len;
          
           /*
           * check spelling and format new node name
           */
           if (  MSDOS_NAME != msdos_get_token(  new_name,   strlen(  new_name ),   &token,   &len ) ) {
           rtems_set_errno_and_return_minus_one(  ENAMETOOLONG );
           }
           /*
           * lock volume
           */
           sc = rtems_semaphore_obtain(  fs_info->vol_sema,   RTEMS_WAIT,  
           MSDOS_VOLUME_SEMAPHORE_TIMEOUT );
           if (  sc != RTEMS_SUCCESSFUL )
           rtems_set_errno_and_return_minus_one(  EIO );
          
           /*
           * create new directory entry as "hard link",   copying relevant info from
           * existing file
           */
           rc = msdos_creat_node(  new_parent_loc,  
           MSDOS_HARD_LINK,  new_name,  len,  S_IFREG,  
           old_fat_fd );
           if (  rc != RC_OK )
           {
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
           }
          
           /*
           * mark file removed
           */
           rc = msdos_set_first_char4file_name(  old_loc->mt_entry,  
           &old_fat_fd->dir_pos,  
           MSDOS_THIS_DIR_ENTRY_EMPTY );
          
           rtems_semaphore_release(  fs_info->vol_sema );
           return rc;
          }

libfs/src/imfs/deviceerrno.c

       1  /*
           * IMFS Device Node Handlers
           *
           * This file contains the set of handlers used to map operations on
           * IMFS device nodes onto calls to the RTEMS Classic API IO Manager.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: deviceerrno.c,  v 1.2 2010/06/08 08:30:04 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/libio.h>
          
          static const int status_code_to_errno [RTEMS_STATUS_CODES_LAST + 1] = {
           [RTEMS_SUCCESSFUL] = 0,  
           [RTEMS_TASK_EXITTED] = EIO,  
           [RTEMS_MP_NOT_CONFIGURED] = EIO,  
           [RTEMS_INVALID_NAME] = EINVAL,  
           [RTEMS_INVALID_ID] = EIO,  
           [RTEMS_TOO_MANY] = EIO,  
           [RTEMS_TIMEOUT] = ETIMEDOUT,  
           [RTEMS_OBJECT_WAS_DELETED] = EIO,  
           [RTEMS_INVALID_SIZE] = EIO,  
           [RTEMS_INVALID_ADDRESS] = EIO,  
           [RTEMS_INVALID_NUMBER] = EBADF,  
           [RTEMS_NOT_DEFINED] = EIO,  
           [RTEMS_RESOURCE_IN_USE] = EBUSY,  
           [RTEMS_UNSATISFIED] = ENODEV,  
           [RTEMS_INCORRECT_STATE] = EIO,  
           [RTEMS_ALREADY_SUSPENDED] = EIO,  
           [RTEMS_ILLEGAL_ON_SELF] = EIO,  
           [RTEMS_ILLEGAL_ON_REMOTE_OBJECT] = EIO,  
           [RTEMS_CALLED_FROM_ISR] = EIO,  
           [RTEMS_INVALID_PRIORITY] = EIO,  
           [RTEMS_NOT_OWNER_OF_RESOURCE] = EPERM,  
           [RTEMS_NOT_IMPLEMENTED] = ENOSYS,  
           [RTEMS_INTERNAL_ERROR] = EIO,  
           [RTEMS_NO_MEMORY] = ENOMEM,  
           [RTEMS_IO_ERROR] = EIO,  
           [RTEMS_PROXY_BLOCKING] = EIO
          };
          
      55  int rtems_deviceio_errno(  rtems_status_code sc )
          {
           if (  sc == RTEMS_SUCCESSFUL ) {
           return 0;
           } else {
           int eno = EINVAL;
          
           if (  (  unsigned ) sc <= RTEMS_STATUS_CODES_LAST ) {
           eno = status_code_to_errno [sc];
           }
          
           errno = eno;
          
           return -1;
           }
          }

libfs/src/imfs/deviceio.c

       1  /*
           * IMFS Device Node Handlers
           *
           * This file contains the set of handlers used to map operations on
           * IMFS device nodes onto calls to the RTEMS Classic API IO Manager.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: deviceio.c,  v 1.24 2010/07/15 08:10:47 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <rtems/devfs.h>
          
          #include "imfs.h"
          
          /*
           * device_open
           *
           * This handler maps an open(   ) operation onto rtems_io_open(   ).
           */
          
      33  int device_open(  
           rtems_libio_t *iop,  
           const char *pathname,  
           uint32_t flag,  
           uint32_t mode
           )
          {
           rtems_libio_open_close_args_t args;
           rtems_status_code status;
           IMFS_jnode_t *the_jnode;
          
           the_jnode = iop->pathinfo.node_access;
          
           args.iop = iop;
           args.flags = iop->flags;
           args.mode = mode;
          
           status = rtems_io_open(  
           the_jnode->info.device.major,  
           the_jnode->info.device.minor,  
           (  void * ) &args
            );
          
           return rtems_deviceio_errno(   status  );
          }
          
          /*
           * device_close
           *
           * This handler maps a close(   ) operation onto rtems_io_close(   ).
           */
          
      65  int device_close(  
           rtems_libio_t *iop
           )
          {
           rtems_libio_open_close_args_t args;
           rtems_status_code status;
           IMFS_jnode_t *the_jnode;
          
           the_jnode = iop->pathinfo.node_access;
          
           args.iop = iop;
           args.flags = 0;
           args.mode = 0;
          
           status = rtems_io_close(  
           the_jnode->info.device.major,  
           the_jnode->info.device.minor,  
           (  void * ) &args
            );
          
           IMFS_check_node_remove(   the_jnode  );
          
           return rtems_deviceio_errno(   status  );
          }
          
          /*
           * device_read
           *
           * This handler maps a read(   ) operation onto rtems_io_read(   ).
           */
          
      96  ssize_t device_read(  
           rtems_libio_t *iop,  
           void *buffer,  
           size_t count
           )
          {
           rtems_libio_rw_args_t args;
           rtems_status_code status;
           IMFS_jnode_t *the_jnode;
          
           the_jnode = iop->pathinfo.node_access;
          
           args.iop = iop;
           args.offset = iop->offset;
           args.buffer = buffer;
           args.count = count;
           args.flags = iop->flags;
           args.bytes_moved = 0;
          
           status = rtems_io_read(  
           the_jnode->info.device.major,  
           the_jnode->info.device.minor,  
           (  void * ) &args
            );
          
           if (   status  )
           return rtems_deviceio_errno(  status );
          
           return (  ssize_t ) args.bytes_moved;
          }
          
          /*
           * device_write
           *
           * This handler maps a write(   ) operation onto rtems_io_write(   ).
           */
          
     133  ssize_t device_write(  
           rtems_libio_t *iop,  
           const void *buffer,  
           size_t count
           )
          {
           rtems_libio_rw_args_t args;
           rtems_status_code status;
           IMFS_jnode_t *the_jnode;
          
           the_jnode = iop->pathinfo.node_access;
          
           args.iop = iop;
           args.offset = iop->offset;
           args.buffer = (  void * ) buffer;
           args.count = count;
           args.flags = iop->flags;
           args.bytes_moved = 0;
          
           status = rtems_io_write(  
           the_jnode->info.device.major,  
           the_jnode->info.device.minor,  
           (  void * ) &args
            );
          
           if (   status  )
           return rtems_deviceio_errno(  status );
          
           return (  ssize_t ) args.bytes_moved;
          }
          
          /*
           * device_ioctl
           *
           * This handler maps an ioctl(   ) operation onto rtems_io_ioctl(   ).
           */
          
     170  int device_ioctl(  
           rtems_libio_t *iop,  
           uint32_t command,  
           void *buffer
           )
          {
           rtems_libio_ioctl_args_t args;
           rtems_status_code status;
           IMFS_jnode_t *the_jnode;
          
           args.iop = iop;
           args.command = command;
           args.buffer = buffer;
          
           the_jnode = iop->pathinfo.node_access;
          
           status = rtems_io_control(  
           the_jnode->info.device.major,  
           the_jnode->info.device.minor,  
           (  void * ) &args
            );
          
           if (   status  )
           return rtems_deviceio_errno(  status );
          
           return args.ioctl_return;
          }
          
          /*
           * device_lseek
           *
           * This handler eats all lseek(   ) operations and does not create
           * an error. It assumes all devices can handle the seek. The
           * writes fail.
           */
          
     206  rtems_off64_t device_lseek(  
           rtems_libio_t *iop,  
           rtems_off64_t offset,  
           int whence
           )
          {
           return offset;
          }
          
          /*
           * device_stat
           *
           * The IMFS_stat(   ) is used.
           */
          
          /*
           * device_rmnod
           *
           * The IMFS_rmnod(   ) is used.
           */
          
     227  int device_ftruncate(  
           rtems_libio_t *iop,  
           rtems_off64_t length
           )
          {
           return 0;
          }

libfs/src/imfs/fifoimfs_init.c

       1  /**
           * @file
           *
           * @ingroup LibFSIMFS
           *
           * @brief IMFS without fifo support initialization.
           */
          
          /*
           * Copyright (  c ) 2010
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * D-82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include "imfs.h"
          
          const rtems_filesystem_operations_table fifoIMFS_ops = {
           .evalpath_h = IMFS_eval_path,  
           .evalformake_h = IMFS_evaluate_for_make,  
           .link_h = IMFS_link,  
           .unlink_h = IMFS_unlink,  
           .node_type_h = IMFS_node_type,  
           .mknod_h = IMFS_mknod,  
           .chown_h = IMFS_chown,  
           .freenod_h = rtems_filesystem_default_freenode,  
           .mount_h = IMFS_mount,  
           .fsmount_me_h = fifoIMFS_initialize,  
           .unmount_h = IMFS_unmount,  
           .fsunmount_me_h = IMFS_fsunmount,  
           .utime_h = IMFS_utime,  
           .eval_link_h = IMFS_evaluate_link,  
           .symlink_h = IMFS_symlink,  
           .readlink_h = IMFS_readlink,  
           .rename_h = IMFS_rename,  
           .statvfs_h = rtems_filesystem_default_statvfs
          };
          
      49  int fifoIMFS_initialize(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           const void *data
           )
          {
           return IMFS_initialize_support(  
           mt_entry,  
           &fifoIMFS_ops,  
           &IMFS_memfile_handlers,  
           &IMFS_directory_handlers,  
           &IMFS_fifo_handlers
            );
          }

libfs/src/imfs/imfs_chown.c

       1  /*
           * IMFS_chown
           *
           * This routine is the implementation of the chown(   ) system
           * call for the IMFS.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_chown.c,  v 1.8 2004/04/17 08:34:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          #include "imfs.h"
          
      26  int IMFS_chown(  
           rtems_filesystem_location_info_t *pathloc,   /* IN */
           uid_t owner,   /* IN */
           gid_t group /* IN */
           )
          {
           IMFS_jnode_t *jnode;
          #if defined(  RTEMS_POSIX_API )
           uid_t st_uid;
          #endif
          
           jnode = (  IMFS_jnode_t * ) pathloc->node_access;
          
           /*
           * Verify I am the owner of the node or the super user.
           */
          
          #if defined(  RTEMS_POSIX_API )
           st_uid = geteuid(   );
          
           if (   (   st_uid != jnode->st_uid  ) && (   st_uid != 0  )  )
           rtems_set_errno_and_return_minus_one(   EPERM  );
          #endif
          
           jnode->st_uid = owner;
           jnode->st_gid = group;
          
           IMFS_update_ctime(   jnode  );
          
           return 0;
          }

libfs/src/imfs/imfs_config.c

       1  /*
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_config.c,  v 1.6 2008/05/27 10:34:14 thomas Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          #include "imfs.h"
          
          /* XXX this structure should use real constants */
          
          const rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS = {
           5,   /* link_max */
           6,   /* max_canon */
           7,   /* max_input */
           IMFS_NAME_MAX,   /* name_max */
           255,   /* path_max */
           2,   /* pipe_buf */
           1,   /* posix_async_io */
           2,   /* posix_chown_restrictions */
           3,   /* posix_no_trunc */
           4,   /* posix_prio_io */
           5,   /* posix_sync_io */
           6 /* posix_vdisable */
          };

libfs/src/imfs/imfs_creat.c

       1  /*
           * IMFS_create_node(   )
           *
           * Routine to create a new in memory file system node.
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_creat.c,  v 1.21 2010/08/18 09:58:15 ccj Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          #include <string.h>
          #include "imfs.h"
          #include <rtems/libio_.h>
          
          /*
           * Create an IMFS filesystem node of an arbitrary type that is NOT
           * the root directory node.
           */
      29  IMFS_jnode_t *IMFS_create_node(  
           rtems_filesystem_location_info_t *parent_loc,  
           IMFS_jnode_types_t type,  
           const char *name,  
           mode_t mode,  
           const IMFS_types_union *info
           )
          {
           IMFS_jnode_t *node;
           IMFS_jnode_t *parent;
           IMFS_fs_info_t *fs_info;
          
           /*
           * MUST have a parent node to call this routine.
           */
           if (   parent_loc == NULL  )
           return NULL;
          
           parent = parent_loc->node_access;
           fs_info = parent_loc->mt_entry->fs_info;
          
           /*
           * Reject creation of FIFOs if support is disabled.
           */
           if (   type == IMFS_FIFO &&
           fs_info->fifo_handlers == &rtems_filesystem_handlers_default  )
           return NULL;
          
           /*
           * Allocate filesystem node and fill in basic information
           */
           node = IMFS_allocate_node(   type,   name,   mode & ~rtems_filesystem_umask  );
           if (   !node  )
           return NULL;
          
           /*
           * Set the type specific information
           */
           if (   type == IMFS_DIRECTORY  ) {
           rtems_chain_initialize_empty(  &node->info.directory.Entries );
           } else if (   type == IMFS_HARD_LINK  ) {
           node->info.hard_link.link_node = info->hard_link.link_node;
           } else if (   type == IMFS_SYM_LINK  ) {
           node->info.sym_link.name = info->sym_link.name;
           } else if (   type == IMFS_DEVICE  ) {
           node->info.device.major = info->device.major;
           node->info.device.minor = info->device.minor;
           } else if (   type == IMFS_LINEAR_FILE  ) {
           node->info.linearfile.size = 0;
           node->info.linearfile.direct = 0;
           } else if (   type == IMFS_MEMORY_FILE  ) {
           node->info.file.size = 0;
           node->info.file.indirect = 0;
           node->info.file.doubly_indirect = 0;
           node->info.file.triply_indirect = 0;
           } else if (   type == IMFS_FIFO  ) {
           node->info.fifo.pipe = NULL;
           } else {
           IMFS_assert(  0 );
           }
          
           /*
           * This node MUST have a parent,   so put it in that directory list.
           */
           node->Parent = parent;
           node->st_ino = ++fs_info->ino_count;
          
           rtems_chain_append(   &parent->info.directory.Entries,   &node->Node  );
          
           return node;
          }
          
          /*
           * Allocate filesystem node and fill in basic information
           */
     104  IMFS_jnode_t *IMFS_allocate_node(  
           IMFS_jnode_types_t type,  
           const char *name,  
           mode_t mode
           )
          {
           IMFS_jnode_t *node;
           struct timeval tv;
          
           /*
           * Allocate an IMFS jnode
           */
           node = calloc(   1,   sizeof(   IMFS_jnode_t  )  );
           if (   !node  )
           return NULL;
          
           /*
           * Fill in the basic information
           */
           node->st_nlink = 1;
           node->type = type;
           strncpy(   node->name,   name,   IMFS_NAME_MAX  );
          
           /*
           * Fill in the mode and permission information for the jnode structure.
           */
           node->st_mode = mode;
           #if defined(  RTEMS_POSIX_API )
           node->st_uid = geteuid(   );
           node->st_gid = getegid(   );
           #else
           node->st_uid = 0;
           node->st_gid = 0;
           #endif
          
           /*
           * Now set all the times.
           */
           gettimeofday(   &tv,   0  );
          
           node->stat_atime = (  time_t ) tv.tv_sec;
           node->stat_mtime = (  time_t ) tv.tv_sec;
           node->stat_ctime = (  time_t ) tv.tv_sec;
          
           return node;
          }
          
     151  IMFS_jnode_t *IMFS_create_root_node(  void )
          {
           IMFS_jnode_t *node;
          
           /*
           * Allocate filesystem node and fill in basic information
           */
           node = IMFS_allocate_node(   IMFS_DIRECTORY,   "",   (  S_IFDIR | 0755 )  );
           if (   !node  )
           return NULL;
          
           /*
           * Set the type specific information
           *
           * NOTE: Root node is always a directory.
           */
           rtems_chain_initialize_empty(  &node->info.directory.Entries );
          
           return node;
          }

libfs/src/imfs/imfs_debug.c

       1  /*
           * IMFS debug support routines
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_debug.c,  v 1.17 2010/07/30 22:36:32 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          #include <fcntl.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <unistd.h> /* for close */
          #include <inttypes.h>
          
          #include <stdio.h>
          #include <sys/stat.h>
          
          #include "imfs.h"
          #include <rtems/libio_.h>
          
          /*
           * IMFS_print_jnode
           *
           * This routine prints the contents of the specified jnode.
           */
      36  void IMFS_print_jnode(  
           IMFS_jnode_t *the_jnode
           )
          {
           IMFS_assert(   the_jnode  );
          
           fprintf(  stdout,   "%s",   the_jnode->name  );
           switch(   the_jnode->type  ) {
           case IMFS_DIRECTORY:
           fprintf(  stdout,   "/"  );
           break;
          
           case IMFS_DEVICE:
           fprintf(  stdout,   " (  device %" PRId32 ",   %" PRId32 " )",  
           the_jnode->info.device.major,   the_jnode->info.device.minor  );
           break;
          
           case IMFS_LINEAR_FILE:
           fprintf(  stdout,   " (  file %" PRId32 " %p )",  
           (  uint32_t )the_jnode->info.linearfile.size,  
           the_jnode->info.linearfile.direct
            );
           break;
          
           case IMFS_MEMORY_FILE:
           /* Useful when debugging .. varies between targets */
          #if 0
           fprintf(  stdout,   " (  file %" PRId32 " %p %p %p )",  
           (  uint32_t )the_jnode->info.file.size,  
           the_jnode->info.file.indirect,  
           the_jnode->info.file.doubly_indirect,  
           the_jnode->info.file.triply_indirect
            );
          #else
           fprintf(  stdout,   " (  file %" PRId32 " )",  
           (  uint32_t )the_jnode->info.file.size  );
          #endif
           break;
          
           case IMFS_HARD_LINK:
           fprintf(  stdout,   " links not printed\n"  );
           return;
          
           case IMFS_SYM_LINK:
           fprintf(  stdout,   " links not printed\n"  );
           return;
          
           case IMFS_FIFO:
           fprintf(  stdout,   " FIFO not printed\n"  );
           return;
          
           default:
           fprintf(  stdout,   " bad type %d\n",   the_jnode->type  );
           return;
           }
           puts(  "" );
          }
          
          /*
           * IMFS_dump_directory
           *
           * This routine prints the contents of a directory in the IMFS. If a
           * directory is encountered,   then this routine will recurse to process
           * the subdirectory.
           */
     101  void IMFS_dump_directory(  
           IMFS_jnode_t *the_directory,  
           int level
           )
          {
           rtems_chain_node *the_node;
           rtems_chain_control *the_chain;
           IMFS_jnode_t *the_jnode;
           int i;
          
           IMFS_assert(   the_directory  );
           IMFS_assert(   level >= 0  );
           IMFS_assert(   the_directory->type == IMFS_DIRECTORY  );
          
           the_chain = &the_directory->info.directory.Entries;
          
           for (   the_node = the_chain->first;
           !rtems_chain_is_tail(   the_chain,   the_node  );
           the_node = the_node->next  ) {
          
           the_jnode = (  IMFS_jnode_t * ) the_node;
          
           for (   i=0 ; i<=level ; i++  )
           fprintf(  stdout,   "...."  );
           IMFS_print_jnode(   the_jnode  );
           if (   the_jnode->type == IMFS_DIRECTORY  )
           IMFS_dump_directory(   the_jnode,   level + 1  );
           }
          }
          
          /*
           * IMFS_dump
           *
           * This routine dumps the entire IMFS that is mounted at the root
           * directory.
           *
           * NOTE: Assuming the "/" directory is bad.
           * Not checking that the starting directory is in an IMFS is bad.
           */
          
     141  void IMFS_dump(   void  )
          {
           fprintf(  stdout,   "*************** Dump of Entire IMFS ***************\n"  );
           fprintf(  stdout,   "/\n"  );
           IMFS_dump_directory(   rtems_filesystem_root.node_access,   0  );
           fprintf(  stdout,   "*************** End of Dump ***************\n"  );
          }
          
          /*
           * IMFS_memfile_maximum_size(   )
           *
           * This routine returns the size of the largest file which can be created
           * using the IMFS memory file type.
           *
           */
     156  int IMFS_memfile_maximum_size(   void  )
          {
           return IMFS_MEMFILE_MAXIMUM_SIZE;
          }

libfs/src/imfs/imfs_directory.c

       1  /*
           * IMFS Directory Access Routines
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_directory.c,  v 1.27 2010/07/15 08:10:48 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <rtems/chain.h>
          #include <fcntl.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <stdio.h>
          #include <string.h>
          #include <dirent.h>
          
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          /*
           * imfs_dir_open
           *
           * This rountine will verify that the node being opened as a directory is
           * in fact a directory node. If it is then the offset into the directory
           * will be set to 0 to position to the first directory entry.
           */
          
      40  int imfs_dir_open(  
           rtems_libio_t *iop,  
           const char *pathname,  
           uint32_t flag,  
           uint32_t mode
           )
          {
           IMFS_jnode_t *the_jnode;
          
           /* Is the node a directory ? */
           the_jnode = (  IMFS_jnode_t * ) iop->pathinfo.node_access;
          
           if (   the_jnode->type != IMFS_DIRECTORY  )
           return -1; /* It wasn't a directory --> return error */
          
           iop->offset = 0;
           return 0;
          }
          
          /*
           * imfs_dir_read
           *
           * This routine will read the next directory entry based on the directory
           * offset. The offset should be equal to -n- time the size of an individual
           * dirent structure. If n is not an integer multiple of the sizeof a
           * dirent structure,   an integer division will be performed to determine
           * directory entry that will be returned in the buffer. Count should reflect
           * -m- times the sizeof dirent bytes to be placed in the buffer.
           * If there are not -m- dirent elements from the current directory position
           * to the end of the exisiting file,   the remaining entries will be placed in
           * the buffer and the returned value will be equal to -m actual- times the
           * size of a directory entry.
           */
          
      74  ssize_t imfs_dir_read(  
           rtems_libio_t *iop,  
           void *buffer,  
           size_t count
           )
          {
           /*
           * Read up to element iop->offset in the directory chain of the
           * imfs_jnode_t struct for this file descriptor.
           */
           rtems_chain_node *the_node;
           rtems_chain_control *the_chain;
           IMFS_jnode_t *the_jnode;
           int bytes_transferred;
           int current_entry;
           int first_entry;
           int last_entry;
           struct dirent tmp_dirent;
          
           the_jnode = (  IMFS_jnode_t * )iop->pathinfo.node_access;
           the_chain = &the_jnode->info.directory.Entries;
          
           if (   rtems_chain_is_empty(   the_chain  )  )
           return 0;
          
           /* Move to the first of the desired directory entries */
           the_node = the_chain->first;
          
           bytes_transferred = 0;
           first_entry = iop->offset;
           /* protect against using sizes that are not exact multiples of the */
           /* -dirent- size. These could result in unexpected results */
           last_entry = first_entry + (  count/sizeof(  struct dirent ) ) * sizeof(  struct dirent );
          
           /* The directory was not empty so try to move to the desired entry in chain*/
           for (  
           current_entry = 0;
           current_entry < last_entry;
           current_entry = current_entry + sizeof(  struct dirent )  ){
          
           if (   rtems_chain_is_tail(   the_chain,   the_node  )  ){
           /* We hit the tail of the chain while trying to move to the first */
           /* entry in the read */
           return bytes_transferred; /* Indicate that there are no more */
           /* entries to return */
           }
          
           if(   current_entry >= first_entry  ) {
           /* Move the entry to the return buffer */
           tmp_dirent.d_off = current_entry;
           tmp_dirent.d_reclen = sizeof(   struct dirent  );
           the_jnode = (  IMFS_jnode_t * ) the_node;
           tmp_dirent.d_ino = the_jnode->st_ino;
           tmp_dirent.d_namlen = strlen(   the_jnode->name  );
           strcpy(   tmp_dirent.d_name,   the_jnode->name  );
           memcpy(  
           buffer + bytes_transferred,  
           (  void * )&tmp_dirent,  
           sizeof(   struct dirent  )
            );
           iop->offset = iop->offset + sizeof(  struct dirent );
           bytes_transferred = bytes_transferred + sizeof(   struct dirent  );
           }
          
           the_node = the_node->next;
           }
          
           /* Success */
           return bytes_transferred;
          }
          
          
          
          /*
           * imfs_dir_close
           *
           * This routine will be called by the generic close routine to cleanup any
           * resources that have been allocated for the management of the file
           */
          
     154  int imfs_dir_close(  
           rtems_libio_t *iop
           )
          {
           /*
           * The generic close routine handles the deallocation of the file control
           * and associated memory. At present the imfs_dir_close simply
           * returns a successful completion status.
           */
          
           return 0;
          }
          
          
          
          /*
           * imfs_dir_lseek
           *
           * This routine will behave in one of three ways based on the state of
           * argument whence. Based on the state of its value the offset argument will
           * be interpreted using one of the following methods:
           *
           * SEEK_SET - offset is the absolute byte offset from the start of the
           * logical start of the dirent sequence that represents the
           * directory
           * SEEK_CUR - offset is used as the relative byte offset from the current
           * directory position index held in the iop structure
           * SEEK_END - N/A --> This will cause an EINVAL to be returned.
           */
          
     184  rtems_off64_t imfs_dir_lseek(  
           rtems_libio_t *iop,  
           rtems_off64_t offset,  
           int whence
           )
          {
           switch(   whence  ) {
           case SEEK_SET: /* absolute move from the start of the file */
           case SEEK_CUR: /* relative move */
           iop->offset = (  iop->offset/sizeof(  struct dirent ) ) *
           sizeof(  struct dirent );
           break;
          
           case SEEK_END: /* Movement past the end of the directory via lseek */
           /* is not a permitted operation */
           default:
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           break;
           }
          
           return 0;
          }
          
          
          
          /*
           * imfs_dir_fstat
           *
           * This routine will obtain the following information concerning the current
           * directory:
           * st_dev 0ll
           * st_ino 1
           * st_mode mode extracted from the jnode
           * st_nlink number of links to this node
           * st_uid uid extracted from the jnode
           * st_gid gid extracted from the jnode
           * st_rdev 0ll
           * st_size the number of bytes in the directory
           * This is calculated by taking the number of entries
           * in the directory and multiplying by the size of a
           * dirent structure
           * st_blksize 0
           * st_blocks 0
           * stat_atime time of last access
           * stat_mtime time of last modification
           * stat_ctime time of the last change
           *
           * This information will be returned to the calling function in a -stat- struct
           *
           */
          
     235  int imfs_dir_fstat(  
           rtems_filesystem_location_info_t *loc,  
           struct stat *buf
           )
          {
           rtems_chain_node *the_node;
           rtems_chain_control *the_chain;
           IMFS_jnode_t *the_jnode;
          
          
           the_jnode = (  IMFS_jnode_t * ) loc->node_access;
          
           buf->st_dev = 0ll;
           buf->st_ino = the_jnode->st_ino;
           buf->st_mode = the_jnode->st_mode;
           buf->st_nlink = the_jnode->st_nlink;
           buf->st_uid = the_jnode->st_uid;
           buf->st_gid = the_jnode->st_gid;
           buf->st_rdev = 0ll;
           buf->st_blksize = 0;
           buf->st_blocks = 0;
           buf->st_atime = the_jnode->stat_atime;
           buf->st_mtime = the_jnode->stat_mtime;
           buf->st_ctime = the_jnode->stat_ctime;
          
           buf->st_size = 0;
          
           the_chain = &the_jnode->info.directory.Entries;
          
           /* Run through the chain and count the number of directory entries */
           /* that are subordinate to this directory node */
           for (   the_node = the_chain->first ;
           !rtems_chain_is_tail(   the_chain,   the_node  ) ;
           the_node = the_node->next  ) {
          
           buf->st_size = buf->st_size + sizeof(   struct dirent  );
           }
          
           return 0;
          }
          
          /*
           * IMFS_dir_rmnod
           *
           * This routine is available from the optable to remove a node
           * from the IMFS file system.
           */
          
     283  int imfs_dir_rmnod(  
           rtems_filesystem_location_info_t *parent_pathloc,   /* IN */
           rtems_filesystem_location_info_t *pathloc /* IN */
           )
          {
           IMFS_jnode_t *the_jnode;
          
           the_jnode = (  IMFS_jnode_t * ) pathloc->node_access;
          
           /*
           * You cannot remove a node that still has children
           */
          
           if (   ! rtems_chain_is_empty(   &the_jnode->info.directory.Entries  )  )
           rtems_set_errno_and_return_minus_one(   ENOTEMPTY  );
          
           /*
           * You cannot remove the file system root node.
           */
          
           if (   pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access  )
           rtems_set_errno_and_return_minus_one(   EBUSY  );
          
           /*
           * You cannot remove a mountpoint.
           */
          
           if (   the_jnode->info.directory.mt_fs != NULL  )
           rtems_set_errno_and_return_minus_one(   EBUSY  );
          
           IMFS_create_orphan(   the_jnode  );
           IMFS_check_node_remove(   the_jnode  );
          
           return 0;
          }

libfs/src/imfs/imfs_eval.c

       1  /*
           * Evaluation IMFS Node Support Routines
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_eval.c,  v 1.31 2010/08/27 17:32:59 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          #define RTEMS_LIBIO_PERMS_RX (  RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ )
          #define RTEMS_LIBIO_PERMS_WX (  RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE )
          
          #define MAXSYMLINK 5
          
      34  int IMFS_Set_handlers(  
           rtems_filesystem_location_info_t *loc
           )
          {
           IMFS_jnode_t *node = loc->node_access;
           IMFS_fs_info_t *fs_info;
          
           fs_info = loc->mt_entry->fs_info;
           switch(   node->type  ) {
           case IMFS_DIRECTORY:
           loc->handlers = fs_info->directory_handlers;
           break;
           case IMFS_DEVICE:
           loc->handlers = &IMFS_device_handlers;
           break;
           case IMFS_SYM_LINK:
           case IMFS_HARD_LINK:
           loc->handlers = &IMFS_link_handlers;
           break;
           case IMFS_LINEAR_FILE:
           loc->handlers = fs_info->memfile_handlers;
           break;
           case IMFS_MEMORY_FILE:
           loc->handlers = fs_info->memfile_handlers;
           break;
           case IMFS_FIFO:
           loc->handlers = fs_info->fifo_handlers;
           break;
           }
          
           return 0;
          }
          
          /*
           * IMFS_evaluate_permission
           *
           * The following routine evaluates that we have permission
           * to do flags on the node.
           */
      73  int IMFS_evaluate_permission(  
           rtems_filesystem_location_info_t *node,  
           int flags
           )
          {
           uid_t st_uid;
           gid_t st_gid;
           IMFS_jnode_t *jnode;
           int flags_to_test;
          
           if (   !rtems_libio_is_valid_perms(   flags  )  )
           rtems_set_errno_and_return_minus_one(   EPERM  );
          
           jnode = node->node_access;
          
          #if defined(  RTEMS_POSIX_API )
           st_uid = geteuid(   );
           st_gid = getegid(   );
          #else
           st_uid = jnode->st_uid;
           st_gid = jnode->st_gid;
          #endif
          
           /*
           * Check if I am owner or a group member or someone else.
           */
          
           flags_to_test = flags;
          
           if (   st_uid == jnode->st_uid  )
           flags_to_test <<= 6;
           else if (   st_gid == jnode->st_gid  )
           flags_to_test <<= 3;
           else {
           /* must be other - do nothing */;
           }
          
           /*
           * If all of the flags are set we have permission
           * to do this.
           */
           if (   (   flags_to_test & jnode->st_mode ) == flags_to_test  )
           return 1;
          
           return 0;
          }
          
          /*
           * IMFS_evaluate_hard_link
           *
           * The following routine evaluates a hardlink to the actual node.
           */
          
     126  int IMFS_evaluate_hard_link(  
           rtems_filesystem_location_info_t *node,   /* IN/OUT */
           int flags /* IN */
           )
          {
           IMFS_jnode_t *jnode = node->node_access;
           int result = 0;
          
           /*
           * Check for things that should never happen.
           */
           IMFS_assert(   jnode->type == IMFS_HARD_LINK  );
          
           /*
           * Set the hard link value and the handlers.
           */
           node->node_access = jnode->info.hard_link.link_node;
          
           IMFS_Set_handlers(   node  );
          
           /*
           * Verify we have the correct permissions for this node.
           */
          
           if (   !IMFS_evaluate_permission(   node,   flags  )  )
           rtems_set_errno_and_return_minus_one(   EACCES  );
          
           return result;
          }
          
          
          /*
           * IMFS_evaluate_sym_link
           *
           * The following routine evaluates a symbolic link to the actual node.
           */
          
     163  int IMFS_evaluate_sym_link(  
           rtems_filesystem_location_info_t *node,   /* IN/OUT */
           int flags /* IN */
           )
          {
           IMFS_jnode_t *jnode = node->node_access;
           int result = 0;
           int i;
          
           /*
           * Check for things that should never happen.
           */
           IMFS_assert(   jnode->type == IMFS_SYM_LINK  );
           IMFS_assert(   jnode->Parent  );
          
           /*
           * Move the node_access to either the symbolic links parent or
           * root depending on the symbolic links path.
           */
           node->node_access = jnode->Parent;
          
           rtems_filesystem_get_sym_start_loc(  
           jnode->info.sym_link.name,  
           &i,  
           node
            );
          
           /*
           * Use eval path to evaluate the path of the symbolic link.
           */
           result = IMFS_eval_path(  
           &jnode->info.sym_link.name[i],  
           strlen(   &jnode->info.sym_link.name[i]  ),  
           flags,  
           node
            );
          
           IMFS_Set_handlers(   node  );
          
           /*
           * Verify we have the correct permissions for this node.
           */
           if (   !IMFS_evaluate_permission(   node,   flags  )  )
           rtems_set_errno_and_return_minus_one(   EACCES  );
          
           return result;
          }
          
          /*
           * IMFS_evaluate_link
           *
           * The following routine returns the real node pointed to by a link.
           */
     216  int IMFS_evaluate_link(  
           rtems_filesystem_location_info_t *node,   /* IN/OUT */
           int flags /* IN */
           )
          {
           IMFS_jnode_t *jnode;
           int result = 0;
          
           do {
           jnode = node->node_access;
          
           /*
           * Increment and check the link counter.
           */
          
           rtems_filesystem_link_counts ++;
           if (   rtems_filesystem_link_counts > MAXSYMLINK  ) {
           rtems_filesystem_link_counts = 0;
           rtems_set_errno_and_return_minus_one(   ELOOP  );
           }
          
           /*
           * Follow the Link node.
           */
          
           if (   jnode->type == IMFS_HARD_LINK  )
           result = IMFS_evaluate_hard_link(   node,   flags  );
          
           else if (  jnode->type == IMFS_SYM_LINK  )
           result = IMFS_evaluate_sym_link(   node,   flags  );
          
           } while (   (   result == 0  ) && (   (   jnode->type == IMFS_SYM_LINK  ) ||
           (   jnode->type == IMFS_HARD_LINK  )  )  );
          
           /*
           * Clear link counter.
           */
          
           rtems_filesystem_link_counts = 0;
          
           return result;
          }
          
          
          /*
           * IMFS_evaluate_for_make
           *
           * The following routine evaluate path for a new node to be created.
           * pathloc is returned with a pointer to the parent of the new node.
           * name is returned with a pointer to the first character in the
           * new node name. The parent node is verified to be a directory.
           */
          
     269  int IMFS_evaluate_for_make(  
           const char *path,   /* IN */
           rtems_filesystem_location_info_t *pathloc,   /* IN/OUT */
           const char **name /* OUT */
           )
          {
           int i = 0;
           int len;
           IMFS_token_types type;
           char token[ IMFS_NAME_MAX + 1 ];
           rtems_filesystem_location_info_t newloc;
           IMFS_jnode_t *node;
           bool done = false;
           int pathlen;
           int result;
          
           /*
           * This was filled in by the caller and is valid in the
           * mount table.
           */
           node = pathloc->node_access;
          
           /*
           * Get the path length.
           */
           pathlen = strlen(   path  );
           /*
           * Evaluate all tokens until we are done or an error occurs.
           */
          
           while(   !done  ) {
          
           type = IMFS_get_token(   &path[i],   pathlen,   token,   &len  );
           pathlen -= len;
           i += len;
          
           if (   !pathloc->node_access  )
           rtems_set_errno_and_return_minus_one(   ENOENT  );
          
           /*
           * I cannot move out of this directory without execute permission.
           */
          
           if (   type != IMFS_NO_MORE_PATH  )
           if (   node->type == IMFS_DIRECTORY  )
           if (   !IMFS_evaluate_permission(   pathloc,   RTEMS_LIBIO_PERMS_SEARCH  )  )
           rtems_set_errno_and_return_minus_one(   EACCES  );
          
           node = pathloc->node_access;
          
           switch(   type  ) {
          
           case IMFS_UP_DIR:
           /*
           * Am I at the root of all filesystems? (  chroot'ed? )
           */
          
           if (   pathloc->node_access == rtems_filesystem_root.node_access  )
           break; /* Throw out the .. in this case */
          
          
           /*
           * Am I at the root of this mounted filesystem?
           */
          
           if (  pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access ){
          
           /*
           * Am I at the root of all filesystems?
           */
          
           if (   pathloc->node_access == rtems_filesystem_root.node_access  ) {
           break;
          
           } else {
           newloc = pathloc->mt_entry->mt_point_node;
           *pathloc = newloc;
           return (  *pathloc->ops->evalformake_h )(   &path[i-len],   pathloc,   name  );
           }
           } else {
          
           if (   !node->Parent  )
           rtems_set_errno_and_return_minus_one(   ENOENT  );
          
           node = node->Parent;
           }
          
           pathloc->node_access = node;
           break;
          
           case IMFS_NAME:
          
           if (   node->type == IMFS_HARD_LINK  ) {
          
           result = IMFS_evaluate_link(   pathloc,   0  );
           if (   result == -1  )
           return -1;
          
           } else if (   node->type == IMFS_SYM_LINK  ) {
          
           result = IMFS_evaluate_link(   pathloc,   0  );
          
           if (   result == -1  )
           return -1;
           }
          
           node = pathloc->node_access;
           if (   !node  )
           rtems_set_errno_and_return_minus_one(   ENOTDIR  );
          
           /*
           * Only a directory can be decended into.
           */
          
           if (   node->type != IMFS_DIRECTORY  )
           rtems_set_errno_and_return_minus_one(   ENOTDIR  );
          
           /*
           * If we are at a node that is a mount point. Set loc to the
           * new fs root node and let them finish evaluating the path.
           */
          
           if (   node->info.directory.mt_fs != NULL  ) {
           newloc = node->info.directory.mt_fs->mt_fs_root;
           *pathloc = newloc;
           return (  *pathloc->ops->evalformake_h )(   &path[i-len],   pathloc,   name  );
           }
          
           /*
           * Otherwise find the token name in the present location.
           */
          
           node = IMFS_find_match_in_dir(   node,   token  );
          
           /*
           * If there is no node we have found the name of the node we
           * wish to create.
           */
          
           if (   ! node  )
           done = true;
           else
           pathloc->node_access = node;
          
           break;
          
           case IMFS_NO_MORE_PATH:
           rtems_set_errno_and_return_minus_one(   EEXIST  );
           break;
          
           case IMFS_INVALID_TOKEN:
           rtems_set_errno_and_return_minus_one(   ENAMETOOLONG  );
           break;
          
           case IMFS_CURRENT_DIR:
           break;
           }
           }
          
           *name = &path[ i - len ];
          
           /*
           * We have evaluated the path as far as we can.
           * Verify there is not any invalid stuff at the end of the name.
           */
          
           for(   ; path[i] != '\0'; i++ ) {
           if (   !IMFS_is_separator(   path[ i ]  )  )
           rtems_set_errno_and_return_minus_one(   ENOENT  );
           }
          
           /*
           * Verify we can execute and write to this directory.
           */
          
           result = IMFS_Set_handlers(   pathloc  );
          
           /*
           * The returned node must be a directory
           */
           node = pathloc->node_access;
           if (   node->type != IMFS_DIRECTORY  )
           rtems_set_errno_and_return_minus_one(   ENOTDIR  );
          
           /*
           * We must have Write and execute permission on the returned node.
           */
          
           if (   !IMFS_evaluate_permission(   pathloc,   RTEMS_LIBIO_PERMS_WX  )  )
           rtems_set_errno_and_return_minus_one(   EACCES  );
          
           return result;
          }
          
          
          /*
           * IMFS_eval_path
           *
           * The following routine evaluate path for a node that wishes to be
           * accessed with mode. pathloc is returned with a pointer to the
           * node to be accessed.
           */
          
     472  int IMFS_eval_path(  
           const char *pathname,   /* IN */
           size_t pathnamelen,   /* IN */
           int flags,   /* IN */
           rtems_filesystem_location_info_t *pathloc /* IN/OUT */
            )
          {
           int i = 0;
           int len;
           IMFS_token_types type = IMFS_CURRENT_DIR;
           char token[ IMFS_NAME_MAX + 1 ];
           rtems_filesystem_location_info_t newloc;
           IMFS_jnode_t *node;
           int result;
          
           if (   !rtems_libio_is_valid_perms(   flags  )  ) {
           rtems_set_errno_and_return_minus_one(   EIO  );
           }
          
           /*
           * This was filled in by the caller and is valid in the
           * mount table.
           */
          
           node = pathloc->node_access;
          
           /*
           * Evaluate all tokens until we are done or an error occurs.
           */
          
           while(   (  type != IMFS_NO_MORE_PATH ) && (  type != IMFS_INVALID_TOKEN )  ) {
          
           type = IMFS_get_token(   &pathname[i],   pathnamelen,   token,   &len  );
           pathnamelen -= len;
           i += len;
          
           if (   !pathloc->node_access  )
           rtems_set_errno_and_return_minus_one(   ENOENT  );
          
           /*
           * I cannot move out of this directory without execute permission.
           */
           if (   type != IMFS_NO_MORE_PATH  )
           if (   node->type == IMFS_DIRECTORY  )
           if (   !IMFS_evaluate_permission(   pathloc,   RTEMS_LIBIO_PERMS_SEARCH  )  )
           rtems_set_errno_and_return_minus_one(   EACCES  );
          
           node = pathloc->node_access;
          
           switch(   type  ) {
           case IMFS_UP_DIR:
           /*
           * Am I at the root of all filesystems? (  chroot'ed? )
           */
          
           if (   pathloc->node_access == rtems_filesystem_root.node_access  )
           break; /* Throw out the .. in this case */
          
           /*
           * Am I at the root of this mounted filesystem?
           */
          
           if (  pathloc->node_access ==
           pathloc->mt_entry->mt_fs_root.node_access ) {
          
           /*
           * Am I at the root of all filesystems?
           */
          
           if (   pathloc->node_access == rtems_filesystem_root.node_access  ) {
           break; /* Throw out the .. in this case */
           } else {
           newloc = pathloc->mt_entry->mt_point_node;
           *pathloc = newloc;
           return (  *pathloc->ops->evalpath_h )(  &(  pathname[i-len] ),  
           pathnamelen+len,  
           flags,  pathloc );
           }
           } else {
          
           if (   !node->Parent  )
           rtems_set_errno_and_return_minus_one(   ENOENT  );
          
           node = node->Parent;
           pathloc->node_access = node;
          
           }
          
           pathloc->node_access = node;
           break;
          
           case IMFS_NAME:
           /*
           * If we are at a link follow it.
           */
           if (   node->type == IMFS_HARD_LINK  ) {
           IMFS_evaluate_hard_link(   pathloc,   0  );
           node = pathloc->node_access;
          
           /*
           * It would be a design error if we evaluated the link and
           * was broken.
           */
           IMFS_assert(   node  );
          
           } else if (   node->type == IMFS_SYM_LINK  ) {
           result = IMFS_evaluate_sym_link(   pathloc,   0  );
          
           /*
           * In contrast to a hard link,   it is possible to have a broken
           * symbolic link.
           */
           node = pathloc->node_access;
           if (   result == -1  )
           return -1;
           }
          
           /*
           * Only a directory can be decended into.
           */
           if (   node->type != IMFS_DIRECTORY  )
           rtems_set_errno_and_return_minus_one(   ENOTDIR  );
          
           /*
           * If we are at a node that is a mount point. Set loc to the
           * new fs root node and let them finish evaluating the path.
           */
           if (   node->info.directory.mt_fs != NULL  ) {
           newloc = node->info.directory.mt_fs->mt_fs_root;
           *pathloc = newloc;
           return (  *pathloc->ops->evalpath_h )(   &pathname[i-len],  
           pathnamelen+len,  
           flags,   pathloc  );
           }
          
           /*
           * Otherwise find the token name in the present location.
           */
           node = IMFS_find_match_in_dir(   node,   token  );
           if (   !node  )
           rtems_set_errno_and_return_minus_one(   ENOENT  );
          
           /*
           * Set the node access to the point we have found.
           */
          
           pathloc->node_access = node;
           break;
          
           case IMFS_NO_MORE_PATH:
           case IMFS_CURRENT_DIR:
           break;
          
           case IMFS_INVALID_TOKEN:
           rtems_set_errno_and_return_minus_one(   ENAMETOOLONG  );
           break;
          
           }
           }
          
           /*
           * Always return the root node.
           *
           * If we are at a node that is a mount point. Set loc to the
           * new fs root node and let let the mounted filesystem set the handlers.
           *
           * NOTE: The behavior of stat(   ) on a mount point appears to be questionable.
           */
          
           if (   node->type == IMFS_DIRECTORY  ) {
           if (   node->info.directory.mt_fs != NULL  ) {
           newloc = node->info.directory.mt_fs->mt_fs_root;
           *pathloc = newloc;
           return (  *pathloc->ops->evalpath_h )(   &pathname[i-len],  
           pathnamelen+len,  
           flags,   pathloc  );
           } else {
           result = IMFS_Set_handlers(   pathloc  );
           }
           } else {
           result = IMFS_Set_handlers(   pathloc  );
           }
          
           /*
           * Verify we have the correct permissions for this node.
           */
          
           if (   !IMFS_evaluate_permission(   pathloc,   flags  )  )
           rtems_set_errno_and_return_minus_one(   EACCES  );
          
           return result;
          }

libfs/src/imfs/imfs_fchmod.c

       1  /*
           * IMFS file change mode routine.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_fchmod.c,  v 1.15 2009/06/12 01:53:33 ccj Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          #include "imfs.h"
          
      24  int IMFS_fchmod(  
           rtems_filesystem_location_info_t *loc,  
           mode_t mode
           )
          {
           IMFS_jnode_t *jnode;
          #if defined(  RTEMS_POSIX_API )
           uid_t st_uid;
          #endif
          
           jnode = loc->node_access;
          
           /*
           * Verify I am the owner of the node or the super user.
           */
          #if defined(  RTEMS_POSIX_API )
           st_uid = geteuid(   );
          
           if (   (   st_uid != jnode->st_uid  ) && (   st_uid != 0  )  )
           rtems_set_errno_and_return_minus_one(   EPERM  );
          #endif
          
           /*
           * Change only the RWX permissions on the jnode to mode.
           */
          
           jnode->st_mode &= ~(  S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX );
           jnode->st_mode |= mode & (  S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX );
          
           IMFS_update_ctime(   jnode  );
          
           return 0;
          }

libfs/src/imfs/imfs_fdatasync.c

       1  /*
           * IMFS_fdatasync
           *
           * The following routine does a sync on an IMFS node. The In Memory
           * File System is always in sync,   therefore this routine always returns
           * pass.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_fdatasync.c,  v 1.4 2003/09/04 18:54:17 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include "imfs.h"
          
      24  int IMFS_fdatasync(  
           rtems_libio_t *iop
           )
          {
           return 0;
          }

libfs/src/imfs/imfs_fifo.c

       1  /*
           * imfs_fifo.c: FIFO support for IMFS
           *
           * Author: Wei Shen <cquark@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: imfs_fifo.c,  v 1.8 2010/08/25 09:37:48 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          #include "imfs.h"
          
          #define JNODE2PIPE(  _jnode ) (   (  _jnode )->info.fifo.pipe  )
          
          #define LIBIO2PIPE(  _iop ) (   JNODE2PIPE(  (  IMFS_jnode_t * )(  _iop )->pathinfo.node_access )  )
          
          /* Set errno and return -1 if error,   else return _err */
          #define IMFS_FIFO_RETURN(  _err ) \
          do { \
      30   if (  _err < 0 ) \
           rtems_set_errno_and_return_minus_one(  -_err ); \
           return _err; \
          } while (  0 )
          
          int IMFS_fifo_open(  
           rtems_libio_t *iop,  
           const char *pathname,  
           uint32_t flag,  
           uint32_t mode
           )
          {
           IMFS_jnode_t *jnode = iop->pathinfo.node_access;
      43  
           int err = fifo_open(  &JNODE2PIPE(  jnode ),   iop );
           IMFS_FIFO_RETURN(  err );
          }
          
          int IMFS_fifo_close(  
           rtems_libio_t *iop
           )
          {
           int err = 0;
           IMFS_jnode_t *jnode = iop->pathinfo.node_access;
          
           pipe_release(  &JNODE2PIPE(  jnode ),   iop );
          
           iop->flags &= ~LIBIO_FLAGS_OPEN;
      58   IMFS_check_node_remove(  jnode );
          
           IMFS_FIFO_RETURN(  err );
          }
          
          ssize_t IMFS_fifo_read(  
           rtems_libio_t *iop,  
           void *buffer,  
           size_t count
           )
          {
           IMFS_jnode_t *jnode = iop->pathinfo.node_access;
          
           int err = pipe_read(  JNODE2PIPE(  jnode ),   buffer,   count,   iop );
           if (  err > 0 )
      73   IMFS_update_atime(  jnode );
          
           IMFS_FIFO_RETURN(  err );
          }
          
          ssize_t IMFS_fifo_write(  
           rtems_libio_t *iop,  
           const void *buffer,  
           size_t count
           )
          {
           IMFS_jnode_t *jnode = iop->pathinfo.node_access;
          
           int err = pipe_write(  JNODE2PIPE(  jnode ),   buffer,   count,   iop );
           if (  err > 0 ) {
           IMFS_mtime_ctime_update(  jnode );
      89   }
          
           IMFS_FIFO_RETURN(  err );
          }
          
          int IMFS_fifo_ioctl(  
           rtems_libio_t *iop,  
           uint32_t command,  
           void *buffer
           )
          {
           int err;
          
           if (  command == FIONBIO ) {
           if (  buffer == NULL )
           err = -EFAULT;
           else {
           if (  *(  int * )buffer )
           iop->flags |= LIBIO_FLAGS_NO_DELAY;
           else
           iop->flags &= ~LIBIO_FLAGS_NO_DELAY;
           return 0;
           }
           }
           else
     114   err = pipe_ioctl(  LIBIO2PIPE(  iop ),   command,   buffer,   iop );
          
           IMFS_FIFO_RETURN(  err );
          }
          
          rtems_off64_t IMFS_fifo_lseek(  
           rtems_libio_t *iop,  
           rtems_off64_t offset,  
           int whence
           )
          {
           off_t err = pipe_lseek(  LIBIO2PIPE(  iop ),   offset,   whence,   iop );
           IMFS_FIFO_RETURN(  err );
          }
          
          /*
           * Handler table for IMFS FIFO nodes
           */
          
          const rtems_filesystem_file_handlers_r IMFS_fifo_handlers = {
           IMFS_fifo_open,  
           IMFS_fifo_close,  
           IMFS_fifo_read,  
           IMFS_fifo_write,  
           IMFS_fifo_ioctl,  
           IMFS_fifo_lseek,  
           IMFS_stat,  
           IMFS_fchmod,  
           rtems_filesystem_default_ftruncate,  
           rtems_filesystem_default_fpathconf,  
           rtems_filesystem_default_fsync,  
           rtems_filesystem_default_fdatasync,  
           rtems_filesystem_default_fcntl,  
           IMFS_rmnod,  
          };

libfs/src/imfs/imfs_fsunmount.c

       1  /*
           * IMFS Initialization
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_fsunmount.c,  v 1.13 2010/06/24 21:31:22 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h> /* for mkdir */
          #include <fcntl.h>
          #include <unistd.h>
          #include <stdlib.h>
          
          #include "imfs.h"
          #include <rtems/libio_.h>
          
          #if defined(  IMFS_DEBUG )
          #include <stdio.h>
          #endif
          
          /*
           * IMFS_fsunmount
           */
          
          #define jnode_get_control(   jnode  ) \
           (  &jnode->info.directory.Entries )
          
          #define jnode_has_no_children(   jnode  ) \
           rtems_chain_is_empty(   jnode_get_control(   jnode  )  )
          
          #define jnode_has_children(   jnode  ) \
           (   ! jnode_has_no_children(   jnode  )  )
      42  
          #define jnode_get_first_child(   jnode  ) \
           (  (  IMFS_jnode_t * )(   rtems_chain_head(   jnode_get_control(   jnode  )  )->next ) )
          
          int IMFS_fsunmount(  
           rtems_filesystem_mount_table_entry_t *temp_mt_entry
           )
          {
           IMFS_jnode_t *jnode;
           IMFS_jnode_t *next;
           rtems_filesystem_location_info_t loc;
           int result = 0;
          
           /*
           * Traverse tree that starts at the mt_fs_root and deallocate memory
           * associated memory space
           */
          
           jnode = (  IMFS_jnode_t * )temp_mt_entry->mt_fs_root.node_access;
           loc = temp_mt_entry->mt_fs_root;
          
           /*
           * Set this to null to indicate that it is being unmounted.
           */
          
           temp_mt_entry->mt_fs_root.node_access = NULL;
          
           do {
           next = jnode->Parent;
           loc.node_access = (  void * )jnode;
           IMFS_Set_handlers(   &loc  );
          
           if (   jnode->type != IMFS_DIRECTORY  ) {
           result = IMFS_unlink(   NULL,   &loc  );
           if (  result != 0 )
           return -1;
           jnode = next;
           } else if (   jnode_has_no_children(   jnode  )  ) {
           result = IMFS_unlink(   NULL,   &loc  );
           if (  result != 0 )
           return -1;
           jnode = next;
           }
           if (   jnode != NULL  ) {
           if (   jnode->type == IMFS_DIRECTORY  ) {
           if (   jnode_has_children(   jnode  )  )
           jnode = jnode_get_first_child(   jnode  );
           }
           }
           } while (  jnode != NULL );
          
           return 0;
          }

libfs/src/imfs/imfs_getchild.c

       1  /*
           * IMFS_find_match_in_dir(   )
           *
           * This routine returns the child name in the given directory.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_getchild.c,  v 1.12 2010/07/30 22:36:32 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <string.h>
          #include "imfs.h"
          
          static const char dotname[2] = ".";
          static const char dotdotname[3] = "..";
          
      27  IMFS_jnode_t *IMFS_find_match_in_dir(  
           IMFS_jnode_t *directory,  
           char *name
           )
          {
           rtems_chain_node *the_node;
           rtems_chain_control *the_chain;
           IMFS_jnode_t *the_jnode;
          
           /*
           * Check for fatal errors. A NULL directory show a problem in the
           * the IMFS code.
           */
           IMFS_assert(   directory  );
           IMFS_assert(   name  );
          
           /*
           * Check for "." and ".."
           */
          
           if (   !strcmp(   name,   dotname  )  )
           return directory;
          
           if (   !strcmp(   name,   dotdotname  )  )
           return directory->Parent;
          
           the_chain = &directory->info.directory.Entries;
          
           for (   the_node = the_chain->first;
           !rtems_chain_is_tail(   the_chain,   the_node  );
           the_node = the_node->next  ) {
          
           the_jnode = (  IMFS_jnode_t * ) the_node;
          
           if (   !strcmp(   name,   the_jnode->name  )  )
           return the_jnode;
           }
          
           return 0;
          }

libfs/src/imfs/imfs_gtkn.c

       1  /*
           * IMFS_get_token
           *
           * Routine to get a token (  name or separator ) from the path
           * the length of the token is returned in token_len.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_gtkn.c,  v 1.11 2009/06/12 01:53:33 ccj Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          #include <string.h>
          
          #include "imfs.h"
          #include <rtems/libio_.h>
          
      27  IMFS_token_types IMFS_get_token(  
           const char *path,  
           int pathlen,  
           char *token,  
           int *token_len
           )
          {
           register int i = 0;
           IMFS_token_types type = IMFS_NAME;
           register char c;
          
           /*
           * Copy a name into token. (  Remember NULL is a token. )
           */
           c = path[i];
           while (   (  !IMFS_is_separator(  c ) ) && (  i < pathlen ) && (  i <= IMFS_NAME_MAX )  ) {
          
           token[i] = c;
          
           if (   i == IMFS_NAME_MAX  )
           return IMFS_INVALID_TOKEN;
          
           if (   !IMFS_is_valid_name_char(  c )  )
           type = IMFS_INVALID_TOKEN;
          
           c = path [++i];
           }
          
           /*
           * Copy a seperator into token.
           */
          
           if (   i == 0  ) {
           token[i] = c;
          
           if (   (  token[i] != '\0' ) && pathlen  ) {
           i++;
           type = IMFS_CURRENT_DIR;
           } else {
           type = IMFS_NO_MORE_PATH;
           }
           } else if (  token[ i-1 ] != '\0' ) {
           token[i] = '\0';
           }
          
           /*
           * Set token_len to the number of characters copied.
           */
          
           *token_len = i;
          
           /*
           * If we copied something that was not a seperator see if
           * it was a special name.
           */
          
           if (   type == IMFS_NAME  ) {
           if (   strcmp(   token,   ".." ) == 0  )
           type = IMFS_UP_DIR;
           else if (   strcmp(   token,   "."  ) == 0  )
           type = IMFS_CURRENT_DIR;
           }
          
           return type;
          }

libfs/src/imfs/imfs_handlers_device.c

       1  /*
           * Device Operations Table for the IMFS
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_handlers_device.c,  v 1.10 2010/07/01 20:18:40 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include "imfs.h"
          
          /*
           * Handler table for IMFS device nodes
           */
          
          const rtems_filesystem_file_handlers_r IMFS_device_handlers = {
           device_open,  
           device_close,  
           device_read,  
           device_write,  
           device_ioctl,  
           device_lseek,  
           IMFS_stat,  
           IMFS_fchmod,  
           device_ftruncate,  
           rtems_filesystem_default_fpathconf,  
           rtems_filesystem_default_fsync,  
           rtems_filesystem_default_fdatasync,  
           rtems_filesystem_default_fcntl,  
           IMFS_rmnod
          };

libfs/src/imfs/imfs_handlers_directory.c

       1  /*
           * Operations Table for Directories for the IMFS
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_handlers_directory.c,  v 1.11 2010/08/25 09:37:48 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include "imfs.h"
          
          /*
           * Set of operations handlers for operations on directories.
           */
          
          const rtems_filesystem_file_handlers_r IMFS_directory_handlers = {
           imfs_dir_open,  
           imfs_dir_close,  
           imfs_dir_read,  
           rtems_filesystem_default_write,  
           rtems_filesystem_default_ioctl,  
           imfs_dir_lseek,  
           imfs_dir_fstat,  
           IMFS_fchmod,  
           rtems_filesystem_default_ftruncate,  
           rtems_filesystem_default_fpathconf,  
           rtems_filesystem_default_fsync,  
           IMFS_fdatasync,  
           rtems_filesystem_default_fcntl,  
           imfs_dir_rmnod
          };

libfs/src/imfs/imfs_handlers_link.c

       1  /*
           * Link Operations Table for the IMFS
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_handlers_link.c,  v 1.7 2010/07/01 20:18:41 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include "imfs.h"
          
          /*
           * Handler table for IMFS device nodes
           */
          
          const rtems_filesystem_file_handlers_r IMFS_link_handlers = {
           rtems_filesystem_default_open,  
           rtems_filesystem_default_close,  
           rtems_filesystem_default_read,  
           rtems_filesystem_default_write,  
           rtems_filesystem_default_ioctl,  
           rtems_filesystem_default_lseek,  
           IMFS_stat,   /* stat */
           rtems_filesystem_default_fchmod,  
           rtems_filesystem_default_ftruncate,  
           rtems_filesystem_default_fpathconf,  
           rtems_filesystem_default_fsync,  
           rtems_filesystem_default_fdatasync,  
           rtems_filesystem_default_fcntl,  
           IMFS_rmnod
          };

libfs/src/imfs/imfs_handlers_memfile.c

       1  /*
           * Memfile Operations Tables for the IMFS
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_handlers_memfile.c,  v 1.14 2010/08/25 09:37:48 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include "imfs.h"
          
          /*
           * Set of operations handlers for operations on memfile entities.
           */
          
          const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = {
           memfile_open,  
           memfile_close,  
           memfile_read,  
           memfile_write,  
           memfile_ioctl,  
           memfile_lseek,  
           IMFS_stat,  
           IMFS_fchmod,  
           memfile_ftruncate,  
           rtems_filesystem_default_fpathconf,  
           IMFS_fdatasync,   /* fsync */
           IMFS_fdatasync,  
           rtems_filesystem_default_fcntl,  
           IMFS_rmnod
          };

libfs/src/imfs/imfs_init.c

       1  /**
           * @file
           *
           * @ingroup LibFSIMFS
           *
           * @brief IMFS initialization.
           */
          
          /*
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_init.c,  v 1.21 2010/07/15 08:46:06 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          
          #include "imfs.h"
          
          const rtems_filesystem_operations_table IMFS_ops = {
           .evalpath_h = IMFS_eval_path,  
           .evalformake_h = IMFS_evaluate_for_make,  
           .link_h = IMFS_link,  
           .unlink_h = IMFS_unlink,  
           .node_type_h = IMFS_node_type,  
           .mknod_h = IMFS_mknod,  
           .chown_h = IMFS_chown,  
           .freenod_h = rtems_filesystem_default_freenode,  
           .mount_h = IMFS_mount,  
           .fsmount_me_h = IMFS_initialize,  
           .unmount_h = IMFS_unmount,  
           .fsunmount_me_h = IMFS_fsunmount,  
           .utime_h = IMFS_utime,  
           .eval_link_h = IMFS_evaluate_link,  
           .symlink_h = IMFS_symlink,  
           .readlink_h = IMFS_readlink,  
           .rename_h = IMFS_rename,  
           .statvfs_h = rtems_filesystem_default_statvfs
          };
          
      49  int IMFS_initialize(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           const void *data
           )
          {
           return IMFS_initialize_support(  
           mt_entry,  
           &IMFS_ops,  
           &IMFS_memfile_handlers,  
           &IMFS_directory_handlers,  
           &rtems_filesystem_handlers_default /* for fifos */
            );
          }

libfs/src/imfs/imfs_initsupp.c

       1  /*
           * IMFS Initialization
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_initsupp.c,  v 1.24 2010/08/10 17:41:32 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h> /* for mkdir */
          #include <fcntl.h>
          #include <unistd.h>
          #include <stdlib.h>
          
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          #if defined(  IMFS_DEBUG )
          #include <stdio.h>
          #endif
          
          /*
           * IMFS_determine_bytes_per_block
           */
          int imfs_memfile_bytes_per_block = 0;
          
      36  static int IMFS_determine_bytes_per_block(  
           int *dest_bytes_per_block,  
           int requested_bytes_per_block,  
           int default_bytes_per_block
           )
          {
           bool is_valid = false;
           int bit_mask;
          
           /*
           * check,   whether requested bytes per block is valid
           */
           for (  bit_mask = 16; !is_valid && (  bit_mask <= 512 ); bit_mask <<= 1 ) {
           if (  bit_mask == requested_bytes_per_block ) {
           is_valid = true;
           break;
           }
           if(  bit_mask > requested_bytes_per_block )
           break;
           }
           *dest_bytes_per_block = (  (  is_valid )
           ? requested_bytes_per_block
           : default_bytes_per_block );
           return 0;
          }
          
          
          /*
           * IMFS_initialize
           */
      66  int IMFS_initialize_support(  
           rtems_filesystem_mount_table_entry_t *temp_mt_entry,  
           const rtems_filesystem_operations_table *op_table,  
           const rtems_filesystem_file_handlers_r *memfile_handlers,  
           const rtems_filesystem_file_handlers_r *directory_handlers,  
           const rtems_filesystem_file_handlers_r *fifo_handlers
           )
          {
           static int imfs_instance;
           IMFS_fs_info_t *fs_info;
           IMFS_jnode_t *jnode;
          
           /*
           * determine/check value for imfs_memfile_bytes_per_block
           */
           IMFS_determine_bytes_per_block(  &imfs_memfile_bytes_per_block,  
           imfs_rq_memfile_bytes_per_block,  
           IMFS_MEMFILE_DEFAULT_BYTES_PER_BLOCK );
          
           /*
           * Create the root node
           *
           * NOTE: UNIX root is 755 and owned by root/root (  0/0 ).
           */
           temp_mt_entry->mt_fs_root.node_access = IMFS_create_root_node(   );
           temp_mt_entry->mt_fs_root.handlers = directory_handlers;
           temp_mt_entry->mt_fs_root.ops = op_table;
           temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
          
           /*
           * Create custom file system data.
           */
           fs_info = calloc(   1,   sizeof(   IMFS_fs_info_t  )  );
           if (   !fs_info  ) {
           free(  temp_mt_entry->mt_fs_root.node_access );
           rtems_set_errno_and_return_minus_one(  ENOMEM );
           }
           temp_mt_entry->fs_info = fs_info;
          
           /*
           * Set st_ino for the root to 1.
           */
          
           fs_info->instance = imfs_instance++;
           fs_info->ino_count = 1;
           fs_info->memfile_handlers = memfile_handlers;
           fs_info->directory_handlers = directory_handlers;
           fs_info->fifo_handlers = fifo_handlers;
          
           jnode = temp_mt_entry->mt_fs_root.node_access;
           jnode->st_ino = fs_info->ino_count;
          
           return 0;
          }

libfs/src/imfs/imfs_link.c

       1  /*
           * IMFS_link
           *
           * The following rouine creates a new link node under parent with the
           * name given in name. The link node is set to point to the node at
           * to_loc.
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_link.c,  v 1.13 2010/01/19 19:31:00 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      27  int IMFS_link(  
           rtems_filesystem_location_info_t *to_loc,   /* IN */
           rtems_filesystem_location_info_t *parent_loc,   /* IN */
           const char *token /* IN */
           )
          {
           IMFS_types_union info;
           IMFS_jnode_t *new_node;
           char new_name[ IMFS_NAME_MAX + 1 ];
           int i;
          
           /*
           * Verify this node can be linked to.
           */
           info.hard_link.link_node = to_loc->node_access;
           if (   info.hard_link.link_node->st_nlink >= LINK_MAX  )
           rtems_set_errno_and_return_minus_one(   EMLINK  );
          
           /*
           * Remove any separators at the end of the string.
           */
           IMFS_get_token(   token,   strlen(   token  ),   new_name,   &i  );
          
           /*
           * Create a new link node.
           *
           * NOTE: Coverity Id 19 reports this as a leak
           * While technically not a leak,   it indicated that IMFS_create_node
           * was ONLY passed a NULL when we created the root node. We
           * added a new IMFS_create_root_node(   ) so this path no longer
           * existed. The result was simpler code which should not have
           * this path.
           */
           new_node = IMFS_create_node(  
           parent_loc,  
           IMFS_HARD_LINK,  
           new_name,  
           (   S_IFLNK | (   S_IRWXU | S_IRWXG | S_IRWXO  ) ),  
           &info
            );
          
           if (   !new_node  )
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
          
           /*
           * Increment the link count of the node being pointed to.
           */
           info.hard_link.link_node->st_nlink++;
           IMFS_update_ctime(   info.hard_link.link_node  );
          
           return 0;
          }

libfs/src/imfs/imfs_load_tar.c

       1  /*
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_load_tar.c,  v 1.19 2010/07/27 18:11:42 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * This file implements the "mount" procedure for tar-based IMFS
           * extensions. The TAR is not actually mounted under the IMFS.
           * Directories from the TAR file are created as usual in the IMFS.
           * File entries are created as IMFS_LINEAR_FILE nodes with their nods
           * pointing to addresses in the TAR image.
           */
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <tar.h>
          
          #include <string.h>
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          #include <rtems/imfs.h>
          #include <rtems/untar.h>
          
          /*
           * TAR file format:
           *
           * Offset Length Contents
           * 0 100 bytes File name (  '\0' terminated,   99 maxmum length )
           * 100 8 bytes File mode (  in octal ascii )
           * 108 8 bytes User ID (  in octal ascii )
           * 116 8 bytes Group ID (  in octal ascii )
           * 124 12 bytes File size (  s ) (  in octal ascii )
           * 136 12 bytes Modify time (  in octal ascii )
           * 148 8 bytes Header checksum (  in octal ascii )
           * 156 1 bytes Link flag
           * 157 100 bytes Linkname (  '\0' terminated,   99 maxmum length )
           * 257 8 bytes Magic PAX (  "ustar\0" + 2 bytes padding )
           * 257 8 bytes Magic GNU tar (  "ustar \0" )
           * 265 32 bytes User name (  '\0' terminated,   31 maxmum length )
           * 297 32 bytes Group name (  '\0' terminated,   31 maxmum length )
           * 329 8 bytes Major device ID (  in octal ascii )
           * 337 8 bytes Minor device ID (  in octal ascii )
           * 345 167 bytes Padding
           * 512 (  s+p )bytes File contents (  s+p ) := (  (  (  s ) + 511 ) & ~511 ),  
           * round up to 512 bytes
           *
           * Checksum:
           * int i,   sum;
           * char* header = tar_header_pointer;
           * sum = 0;
           * for(  i = 0; i < 512; i++ )
           * sum += 0xFF & header[i];
           */
          
          #define MAX_NAME_FIELD_SIZE 99
          
          #define MIN(  a,  b ) (  (  a )>(  b )?(  b ):(  a ) )
          
          /*
           * rtems_tarfs_load
           *
           * Here we create the mountpoint directory and load the tarfs at
           * that node. Once the IMFS has been mounted,   we work through the
           * tar image and perform as follows:
           * - For directories,   simply call mkdir(   ). The IMFS creates nodes as
           * needed.
           * - For files,   we make our own calls to IMFS eval_for_make and
           * create_node.
           */
      82  int rtems_tarfs_load(  
           char *mountpoint,  
           uint8_t *tar_image,  
           size_t tar_size
           )
          {
           rtems_filesystem_location_info_t root_loc;
           rtems_filesystem_location_info_t loc;
           const char *hdr_ptr;
           char filename[100];
           char full_filename[256];
           int hdr_chksum;
           unsigned char linkflag;
           unsigned long file_size;
           unsigned long file_mode;
           int offset;
           unsigned long nblocks;
           IMFS_jnode_t *node;
           int status;
          
           status = rtems_filesystem_evaluate_path(  
           mountpoint,  
           strlen(  mountpoint ),  
           0,  
           &root_loc,  
           0
            );
           if (  status != 0 )
           return -1;
          
           if (  root_loc.ops != &IMFS_ops && root_loc.ops != &fifoIMFS_ops )
           return -1;
          
           /*
           * Create an IMFS node structure pointing to tar image memory.
           */
           offset = 0;
           while (  1 ) {
           if (  offset + 512 > tar_size )
           break;
          
           /*
           * Read a header.
           */
           hdr_ptr = (  char * ) &tar_image[offset];
           offset += 512;
           if (  strncmp(  &hdr_ptr[257],   "ustar",   5 ) )
           break;
          
           strncpy(  filename,   hdr_ptr,   MAX_NAME_FIELD_SIZE );
           filename[MAX_NAME_FIELD_SIZE] = '\0';
          
           linkflag = hdr_ptr[156];
           file_mode = _rtems_octal2ulong(  &hdr_ptr[100],   8 );
           file_size = _rtems_octal2ulong(  &hdr_ptr[124],   12 );
           hdr_chksum = _rtems_octal2ulong(  &hdr_ptr[148],   8 );
          
           if (  _rtems_tar_header_checksum(  hdr_ptr ) != hdr_chksum )
           break;
          
           /*
           * Generate an IMFS node depending on the file type.
           * - For directories,   just create directories as usual. IMFS
           * will take care of the rest.
           * - For files,   create a file node with special tarfs properties.
           */
           if (  linkflag == DIRTYPE ) {
           strcpy(  full_filename,   mountpoint );
           if (  full_filename[strlen(  full_filename )-1] != '/' )
           strcat(  full_filename,   "/" );
           strcat(  full_filename,   filename );
           mkdir(  full_filename,   S_IRWXU | S_IRWXG | S_IRWXO );
           }
           /*
           * Create a LINEAR_FILE node
           *
           * NOTE: Coverity Id 20 reports this as a leak.
           * While technically not a leak,   it indicated that
           * IMFS_create_node was ONLY passed a NULL when we created the
           * root node. We added a new IMFS_create_root_node(   ) so this
           * path no longer existed. The result was simpler code which
           * should not have this path.
           */
           else if (  linkflag == REGTYPE ) {
           const char *name;
          
           loc = root_loc;
           if (  IMFS_evaluate_for_make(  filename,   &loc,   &name ) == 0 ) {
           node = IMFS_create_node(  
           &loc,  
           IMFS_LINEAR_FILE,   (  char * )name,  
           (  file_mode & (  S_IRWXU | S_IRWXG | S_IRWXO ) ) | S_IFREG,  
           NULL
            );
           node->info.linearfile.size = file_size;
           node->info.linearfile.direct = &tar_image[offset];
           }
          
           nblocks = (  (  (  file_size ) + 511 ) & ~511 ) / 512;
           offset += 512 * nblocks;
           }
           }
           return status;
          }
          

libfs/src/imfs/imfs_mknod.c

       1  /*
           * IMFS_mknod
           *
           * Routine to create a node in the IMFS file system.
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_mknod.c,  v 1.15 2010/08/02 18:27:23 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <errno.h>
          #include <stdlib.h>
          
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      31  int IMFS_mknod(  
           const char *token,   /* IN */
           mode_t mode,   /* IN */
           dev_t dev,   /* IN */
           rtems_filesystem_location_info_t *pathloc /* IN/OUT */
           )
          {
           IMFS_token_types type = 0;
           IMFS_jnode_t *new_node;
           int result;
           char new_name[ IMFS_NAME_MAX + 1 ];
           IMFS_types_union info;
          
           IMFS_get_token(   token,   strlen(   token  ),   new_name,   &result  );
          
           /*
           * Figure out what type of IMFS node this is.
           */
           if (   S_ISDIR(  mode )  )
           type = IMFS_DIRECTORY;
           else if (   S_ISREG(  mode )  )
           type = IMFS_MEMORY_FILE;
           else if (   S_ISBLK(  mode ) || S_ISCHR(  mode )  ) {
           type = IMFS_DEVICE;
           rtems_filesystem_split_dev_t(   dev,   info.device.major,   info.device.minor  );
           } else if (  S_ISFIFO(  mode ) )
           type = IMFS_FIFO;
           else
           IMFS_assert(   0  );
          
           /*
           * Allocate and fill in an IMFS jnode
           *
           * NOTE: Coverity Id 21 reports this as a leak.
           * While technically not a leak,   it indicated that IMFS_create_node
           * was ONLY passed a NULL when we created the root node. We
           * added a new IMFS_create_root_node(   ) so this path no longer
           * existed. The result was simpler code which should not have
           * this path.
           */
           new_node = IMFS_create_node(   pathloc,   type,   new_name,   mode,   &info  );
           if (   !new_node  )
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
          
           return 0;
          }

libfs/src/imfs/imfs_mount.c

       1  /*
           * IMFS_mount
           *
           * This routine will look at a mount table entry that we are going to
           * add to the mount table. If the mount point rtems_filesystem
           * location_info_t struct refers to a node that is a directory,  
           * the node will be marked as a mount point by setting its directory.mt_fs
           * pointer to point to the mount table entry that we are about to add
           * to the mount table chain.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_mount.c,  v 1.7 2004/04/17 08:34:41 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      31  int IMFS_mount(  
           rtems_filesystem_mount_table_entry_t *mt_entry
           )
          {
           IMFS_jnode_t *node;
          
           node = mt_entry->mt_point_node.node_access;
          
           /*
           * Is the node that we are mounting onto a directory node ?
           */
          
           if (   node->type != IMFS_DIRECTORY  )
           rtems_set_errno_and_return_minus_one(   ENOTDIR  );
          
           /*
           * Set mt_fs pointer to point to the mount table entry for
           * the mounted file system.
           */
          
           node->info.directory.mt_fs = mt_entry;
           return 0;
          }

libfs/src/imfs/imfs_ntype.c

       1  /*
           * IMFS_node_type
           *
           * The following verifies that returns the type of node that the
           * loc refers to.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_ntype.c,  v 1.5 2004/04/17 08:34:41 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include "imfs.h"
          
      24  rtems_filesystem_node_types_t IMFS_node_type(  
           rtems_filesystem_location_info_t *pathloc /* IN */
           )
          {
           IMFS_jnode_t *node;
          
           node = pathloc->node_access;
           return node->type;
          }

libfs/src/imfs/imfs_readlink.c

       1  /*
           * IMFS_readlink
           *
           * The following rouine puts the symblic links destination name into
           * buff.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_readlink.c,  v 1.8 2010/08/02 18:27:23 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      26  int IMFS_readlink(  
           rtems_filesystem_location_info_t *loc,  
           char *buf,   /* OUT */
           size_t bufsize
           )
          {
           IMFS_jnode_t *node;
           int i;
          
           node = loc->node_access;
          
           IMFS_assert(   node->type == IMFS_SYM_LINK  );
          
           for(   i=0; (  (  i<bufsize ) && (  node->info.sym_link.name[i] != '\0' ) ); i++  )
           buf[i] = node->info.sym_link.name[i];
          
           return i;
          }

libfs/src/imfs/imfs_rename.c

       1  /*
           * IMFS_rename
           *
           * The following rouine creates a new link node under parent with the
           * name given in name and removes the old.
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_rename.c,  v 1.1 2010/03/04 06:36:51 ccj Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      26  int IMFS_rename(  
           rtems_filesystem_location_info_t *old_parent_loc,   /* IN */
           rtems_filesystem_location_info_t *old_loc,   /* IN */
           rtems_filesystem_location_info_t *new_parent_loc,   /* IN */
           const char *new_name /* IN */
           )
          {
           IMFS_jnode_t *the_jnode;
           IMFS_jnode_t *new_parent;
          
           the_jnode = old_loc->node_access;
          
           strncpy(   the_jnode->name,   new_name,   IMFS_NAME_MAX  );
          
           if (   the_jnode->Parent != NULL  )
           rtems_chain_extract(   (  rtems_chain_node * ) the_jnode  );
          
           new_parent = new_parent_loc->node_access;
           the_jnode->Parent = new_parent;
          
           rtems_chain_append(   &new_parent->info.directory.Entries,   &the_jnode->Node  );
          
           /*
           * Update the time.
           */
           IMFS_update_ctime(   the_jnode  );
          
           return 0;
          }

libfs/src/imfs/imfs_rmnod.c

       1  /*
           * IMFS Node Removal Handler
           *
           * This file contains the handler used to remove a node when a file type
           * does not require special actions.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_rmnod.c,  v 1.17 2010/06/08 08:50:56 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          
          #include "imfs.h"
          
      29  void IMFS_create_orphan(   IMFS_jnode_t *jnode  )
          {
           if (   jnode->Parent != NULL  ) {
           rtems_chain_extract(   &jnode->Node  );
           jnode->Parent = NULL;
           }
          
           --jnode->st_nlink;
          
           IMFS_update_ctime(   jnode  );
          }
          
      41  void IMFS_check_node_remove(   IMFS_jnode_t *jnode  )
          {
           if (   !rtems_libio_is_file_open(   jnode  ) && jnode->st_nlink < 1  ) {
           if (   rtems_filesystem_current.node_access == jnode  )
           rtems_filesystem_current.node_access = NULL;
          
           switch (   jnode->type  ) {
           case IMFS_MEMORY_FILE:
           IMFS_memfile_remove(   jnode  );
           break;
           case IMFS_SYM_LINK:
           free(   jnode->info.sym_link.name  );
           break;
           default:
           break;
           }
          
           free(   jnode  );
           }
          }
          
          /*
           * IMFS_rmnod
           */
          
      66  int IMFS_rmnod(  
           rtems_filesystem_location_info_t *parent_pathloc,   /* IN */
           rtems_filesystem_location_info_t *pathloc /* IN */
           )
          {
           IMFS_jnode_t *jnode = (  IMFS_jnode_t * ) pathloc->node_access;
          
           IMFS_create_orphan(   jnode  );
           IMFS_check_node_remove(   jnode  );
          
           return 0;
          }

libfs/src/imfs/imfs_stat.c

       1  /*
           * IMFS_stat
           *
           * This routine provides a stat for the IMFS file system.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_stat.c,  v 1.14 2010/05/15 06:29:55 ccj Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      25  int IMFS_stat(  
           rtems_filesystem_location_info_t *loc,  
           struct stat *buf
           )
          {
           IMFS_fs_info_t *fs_info;
           IMFS_jnode_t *the_jnode;
           IMFS_device_t *io;
          
           the_jnode = loc->node_access;
          
          
           switch (   the_jnode->type  ) {
          
           case IMFS_DEVICE:
           io = &the_jnode->info.device;
           buf->st_rdev = rtems_filesystem_make_dev_t(   io->major,   io->minor  );
           break;
          
           case IMFS_LINEAR_FILE:
           case IMFS_MEMORY_FILE:
           buf->st_size = the_jnode->info.file.size;
           break;
          
           case IMFS_SYM_LINK:
           buf->st_size = 0;
           break;
          
           case IMFS_FIFO:
           buf->st_size = 0;
           break;
          
           default:
           rtems_set_errno_and_return_minus_one(   ENOTSUP  );
           break;
           }
          
           /*
           * The device number of the IMFS is the major number and the minor is the
           * instance.
           */
           fs_info = loc->mt_entry->fs_info;
           buf->st_dev =
           rtems_filesystem_make_dev_t(   IMFS_DEVICE_MAJOR_NUMBER,   fs_info->instance  );
          
           buf->st_mode = the_jnode->st_mode;
           buf->st_nlink = the_jnode->st_nlink;
           buf->st_ino = the_jnode->st_ino;
           buf->st_uid = the_jnode->st_uid;
           buf->st_gid = the_jnode->st_gid;
          
           buf->st_atime = the_jnode->stat_atime;
           buf->st_mtime = the_jnode->stat_mtime;
           buf->st_ctime = the_jnode->stat_ctime;
          
           return 0;
          }

libfs/src/imfs/imfs_symlink.c

       1  /*
           * IMFS_symlink
           *
           * The following rouine creates a new symbolic link node under parent
           * with the name given in name. The node is set to point to the node at
           * to_loc.
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_symlink.c,  v 1.14 2010/01/19 19:31:00 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <string.h>
          #include <stdlib.h>
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      29  int IMFS_symlink(  
           rtems_filesystem_location_info_t *parent_loc,  
           const char *link_name,  
           const char *node_name
           )
          {
           IMFS_types_union info;
           IMFS_jnode_t *new_node;
           char new_name[ IMFS_NAME_MAX + 1 ];
           int i;
          
           /*
           * Remove any separators at the end of the string.
           */
           IMFS_get_token(   node_name,   strlen(   node_name  ),   new_name,   &i  );
          
           /*
           * Duplicate link name
           */
           info.sym_link.name = strdup(  link_name );
           if (  info.sym_link.name == NULL ) {
           rtems_set_errno_and_return_minus_one(  ENOMEM );
           }
          
           /*
           * Create a new link node.
           *
           * NOTE: Coverity CID 22 notes this as a resource leak.
           * While technically not a leak,   it indicated that IMFS_create_node
           * was ONLY passed a NULL when we created the root node. We
           * added a new IMFS_create_root_node(   ) so this path no longer
           * existed. The result was simpler code which should not have
           * this path.
           */
           new_node = IMFS_create_node(  
           parent_loc,  
           IMFS_SYM_LINK,  
           new_name,  
           (   S_IFLNK | (   S_IRWXU | S_IRWXG | S_IRWXO  ) ),  
           &info
            );
          
           if (  new_node == NULL ) {
           free(  info.sym_link.name );
           rtems_set_errno_and_return_minus_one(  ENOMEM );
           }
          
           return 0;
          }

libfs/src/imfs/imfs_unlink.c

       1  /*
           * IMFS_unlink
           *
           * Routine to remove a link node from the tree.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_unlink.c,  v 1.15 2009/06/12 01:53:33 ccj Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <stdlib.h>
          
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      27  int IMFS_unlink(  
           rtems_filesystem_location_info_t *parentloc,   /* IN */
           rtems_filesystem_location_info_t *loc /* IN */
           )
          {
           IMFS_jnode_t *node;
           rtems_filesystem_location_info_t the_link;
           int result = 0;
          
           node = loc->node_access;
          
           /*
           * Decrement the link counter of node pointed to and free the
           * space.
           */
          
           /*
           * If this is the last last pointer to the node
           * free the node.
           */
          
           if (   node->type == IMFS_HARD_LINK  ) {
          
           if (   !node->info.hard_link.link_node  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           the_link = *loc;
           the_link.node_access = node->info.hard_link.link_node;
           IMFS_Set_handlers(   &the_link  );
          
           /*
           * If removing the last hard link to a node,   then we need
           * to remove the node that is a link and the node itself.
           */
          
           if (   node->info.hard_link.link_node->st_nlink == 1 )
           {
           result = (  *the_link.handlers->rmnod_h )(   parentloc,   &the_link  );
           if (   result != 0  )
           return -1;
           }
           else
           {
           node->info.hard_link.link_node->st_nlink --;
           IMFS_update_ctime(   node->info.hard_link.link_node  );
           }
           }
          
           /*
           * Now actually free the node we were asked to free.
           */
          
           result = (  *loc->handlers->rmnod_h )(   parentloc,   loc  );
          
           return result;
          }

libfs/src/imfs/imfs_unmount.c

       1  /*
           * IMFS_unmount
           *
           * This routine will look at a mount table entry that we are going to
           * add to the mount table. If the mount point
           * rtems_filesystem_location_info_t struct refers to a node that is a
           * directory that has a file system mounted on it,   the node will be
           * marked as a mount point by * setting its directory.mt_fs pointer
           * to NULL. This indicates that a directory is no longer mounted on
           * this node.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_unmount.c,  v 1.7 2004/04/17 08:34:41 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
      32  int IMFS_unmount(  
           rtems_filesystem_mount_table_entry_t *mt_entry
           )
          {
           IMFS_jnode_t *node;
          
           node = mt_entry->mt_point_node.node_access;
          
           /*
           * Is the node that we are mounting onto a directory node ?
           */
          
           if (   node->type != IMFS_DIRECTORY  )
           rtems_set_errno_and_return_minus_one(   ENOTDIR  );
          
           /*
           * Did the node indicate that there was a directory mounted here?
           */
          
           if (   node->info.directory.mt_fs == NULL  )
           rtems_set_errno_and_return_minus_one(   EINVAL  ); /* XXX */
          
           /*
           * Set the mt_fs pointer to indicate that there is no longer
           * a file system mounted to this point.
           */
          
           node->info.directory.mt_fs = NULL;
          
           return 0;
          }

libfs/src/imfs/imfs_utime.c

       1  /*
           * IMFS_utime
           *
           * This routine is the implementation of the utime(   ) system
           * call for the IMFS.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: imfs_utime.c,  v 1.8 2010/07/01 16:29:17 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <sys/time.h>
          
          #include <rtems/libio_.h>
          #include "imfs.h"
          
      27  int IMFS_utime(  
           rtems_filesystem_location_info_t *pathloc,   /* IN */
           time_t actime,   /* IN */
           time_t modtime /* IN */
           )
          {
           IMFS_jnode_t *the_jnode;
          
           the_jnode = (  IMFS_jnode_t * ) pathloc->node_access;
          
           the_jnode->stat_atime = actime;
           the_jnode->stat_mtime = modtime;
           the_jnode->stat_ctime = time(   NULL  );
          
           return 0;
          }

libfs/src/imfs/ioman.c

       1  /*
           * This file emulates the old Classic RTEMS IO manager directives
           * which register and lookup names using the in-memory filesystem.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ioman.c,  v 1.20 2010/07/06 22:32:23 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <string.h>
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          #include "imfs.h"
          
          /*
           * rtems_io_register_name
           *
           * This assumes that all registered devices are character devices.
           */
          
      36  rtems_status_code rtems_io_register_name(  
           const char *device_name,  
           rtems_device_major_number major,  
           rtems_device_minor_number minor
           )
          {
           int status;
           dev_t dev;
          
           dev = rtems_filesystem_make_dev_t(   major,   minor  );
           status = mknod(   device_name,   0777 | S_IFCHR,   dev  );
          
           /* this is the only error returned by the old version */
           if (   status  )
           return RTEMS_TOO_MANY;
          
           return RTEMS_SUCCESSFUL;
          }
          
          /*
           * rtems_io_lookup_name
           *
           * This version is reentrant.
           *
           * XXX - This is dependent upon IMFS and should not be.
           * Suggest adding a filesystem routine to fill in the device_info.
           */
          
      64  rtems_status_code rtems_io_lookup_name(  
           const char *name,  
           rtems_driver_name_t *device_info
           )
          {
           IMFS_jnode_t *the_jnode;
           rtems_filesystem_location_info_t loc;
           int result;
           rtems_filesystem_node_types_t node_type;
          
           result = rtems_filesystem_evaluate_path(  
           name,   strlen(   name  ),   0x00,   &loc,   true  );
           the_jnode = loc.node_access;
          
           node_type = (  *loc.ops->node_type_h )(   &loc  );
          
           if (   (  result != 0 ) || node_type != RTEMS_FILESYSTEM_DEVICE  ) {
           rtems_filesystem_freenode(   &loc  );
           return RTEMS_UNSATISFIED;
           }
          
           device_info->device_name = (  char * ) name;
           device_info->device_name_length = strlen(   name  );
           device_info->major = the_jnode->info.device.major;
           device_info->minor = the_jnode->info.device.minor;
          
           rtems_filesystem_freenode(   &loc  );
          
           return RTEMS_SUCCESSFUL;
          }

libfs/src/imfs/memfile.c

          /*
           * IMFS Device Node Handlers
           *
           * This file contains the set of handlers used to process operations on
           * IMFS memory file nodes. The memory files are created in memory using
           * malloc'ed memory. Thus any data stored in one of these files is lost
           * at system shutdown unless special arrangements to copy the data to
           * some type of non-volailte storage are made by the application.
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: memfile.c,  v 1.39 2010/08/27 17:43:26 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include "imfs.h"
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          #define MEMFILE_STATIC
          
          /*
           * Prototypes of private routines
           */
      39  MEMFILE_STATIC int IMFS_memfile_extend(  
           IMFS_jnode_t *the_jnode,  
           off_t new_length
           );
          
      44  MEMFILE_STATIC int IMFS_memfile_addblock(  
           IMFS_jnode_t *the_jnode,  
           unsigned int block
           );
          
      49  MEMFILE_STATIC int IMFS_memfile_remove_block(  
           IMFS_jnode_t *the_jnode,  
           unsigned int block
           );
          
          MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(  
           IMFS_jnode_t *the_jnode,  
           unsigned int block,  
           int malloc_it
           );
          
          MEMFILE_STATIC ssize_t IMFS_memfile_read(  
           IMFS_jnode_t *the_jnode,  
           off_t start,  
           unsigned char *destination,  
           unsigned int length
           );
          
      67  ssize_t IMFS_memfile_write(   /* cannot be static as used in imfs_fchmod.c */
           IMFS_jnode_t *the_jnode,  
           off_t start,  
           const unsigned char *source,  
           unsigned int length
           );
          
      74  void *memfile_alloc_block(  void );
          
      76  void memfile_free_block(  
           void *memory
           );
          
          /*
           * memfile_open
           *
           * This routine processes the open(   ) system call. Note that there is
           * nothing special to be done at open(   ) time.
           */
      86  int memfile_open(  
           rtems_libio_t *iop,  
           const char *pathname,  
           uint32_t flag,  
           uint32_t mode
           )
          {
           IMFS_jnode_t *the_jnode;
          
           the_jnode = iop->pathinfo.node_access;
          
           /*
           * Perform 'copy on write' for linear files
           */
           if (  (  iop->flags & (  LIBIO_FLAGS_WRITE | LIBIO_FLAGS_APPEND ) )
           && (  the_jnode->type == IMFS_LINEAR_FILE ) ) {
           uint32_t count = the_jnode->info.linearfile.size;
           const unsigned char *buffer = the_jnode->info.linearfile.direct;
          
           the_jnode->type = IMFS_MEMORY_FILE;
           the_jnode->info.file.size = 0;
           the_jnode->info.file.indirect = 0;
           the_jnode->info.file.doubly_indirect = 0;
           the_jnode->info.file.triply_indirect = 0;
           if (  (  count != 0 )
           && (  IMFS_memfile_write(  the_jnode,   0,   buffer,   count ) == -1 ) )
           return -1;
           }
           if (  iop->flags & LIBIO_FLAGS_APPEND )
           iop->offset = the_jnode->info.file.size;
          
           iop->size = the_jnode->info.file.size;
           return 0;
          }
          
          /*
           * memfile_close
           *
           * This routine processes the close(   ) system call. Note that there is
           * nothing to flush or memory to free at this point.
           */
     127  int memfile_close(  
           rtems_libio_t *iop
           )
          {
           IMFS_jnode_t *the_jnode;
          
           the_jnode = iop->pathinfo.node_access;
          
           if (  iop->flags & LIBIO_FLAGS_APPEND )
           iop->offset = the_jnode->info.file.size;
          
           IMFS_check_node_remove(   the_jnode  );
          
           return 0;
          }
          
          /*
           * memfile_read
           *
           * This routine processes the read(   ) system call.
           */
     148  ssize_t memfile_read(  
           rtems_libio_t *iop,  
           void *buffer,  
           size_t count
           )
          {
           IMFS_jnode_t *the_jnode;
          
           the_jnode = iop->pathinfo.node_access;
          
           return IMFS_memfile_read(   the_jnode,   iop->offset,   buffer,   count  );
          }
          
          /*
           * memfile_write
           *
           * This routine processes the write(   ) system call.
           */
     166  ssize_t memfile_write(  
           rtems_libio_t *iop,  
           const void *buffer,  
           size_t count
           )
          {
           IMFS_jnode_t *the_jnode;
           ssize_t status;
          
           the_jnode = iop->pathinfo.node_access;
          
           status = IMFS_memfile_write(   the_jnode,   iop->offset,   buffer,   count  );
           iop->size = the_jnode->info.file.size;
          
           return status;
          }
          
          /*
           * memfile_ioctl
           *
           * This routine processes the ioctl(   ) system call.
           *
           * NOTE: No ioctl(   )'s are supported for in-memory files.
           */
     190  int memfile_ioctl(  
           rtems_libio_t *iop,  
           uint32_t command,  
           void *buffer
           )
          {
           IMFS_jnode_t *the_jnode;
          
           the_jnode = iop->pathinfo.node_access;
          
           return 0;
          }
          
          /*
           * memfile_lseek
           *
           * This routine processes the lseek(   ) system call.
           */
     208  rtems_off64_t memfile_lseek(  
           rtems_libio_t *iop,  
           rtems_off64_t offset,  
           int whence
           )
          {
           IMFS_jnode_t *the_jnode;
          
           the_jnode = iop->pathinfo.node_access;
          
           if (  the_jnode->type == IMFS_LINEAR_FILE ) {
           if (  iop->offset > the_jnode->info.linearfile.size )
           iop->offset = the_jnode->info.linearfile.size;
           }
           else { /* Must be a block file (  IMFS_MEMORY_FILE ). */
           if (  IMFS_memfile_extend(   the_jnode,   iop->offset  ) )
           rtems_set_errno_and_return_minus_one(   ENOSPC  );
          
           iop->size = the_jnode->info.file.size;
           }
           return iop->offset;
          }
          
          /*
           * memfile_stat
           *
           * This IMFS_stat(   ) can be used.
           */
          
          /*
           * memfile_ftruncate
           *
           * This routine processes the ftruncate(   ) system call.
           */
     242  int memfile_ftruncate(  
           rtems_libio_t *iop,  
           rtems_off64_t length
           )
          {
           IMFS_jnode_t *the_jnode;
          
           the_jnode = iop->pathinfo.node_access;
          
           /*
           * POSIX 1003.1b does not specify what happens if you truncate a file
           * and the new length is greater than the current size. We treat this
           * as an extend operation.
           */
          
           if (   length > the_jnode->info.file.size  )
           return IMFS_memfile_extend(   the_jnode,   length  );
          
           /*
           * The in-memory files do not currently reclaim memory until the file is
           * deleted. So we leave the previously allocated blocks in place for
           * future use and just set the length.
           */
           the_jnode->info.file.size = length;
           iop->size = the_jnode->info.file.size;
          
           IMFS_update_atime(   the_jnode  );
          
           return 0;
          }
          
          /*
           * IMFS_memfile_extend
           *
           * This routine insures that the in-memory file is of the length
           * specified. If necessary,   it will allocate memory blocks to
           * extend the file.
           */
     280  MEMFILE_STATIC int IMFS_memfile_extend(  
           IMFS_jnode_t *the_jnode,  
           off_t new_length
           )
          {
           unsigned int block;
           unsigned int new_blocks;
           unsigned int old_blocks;
          
           /*
           * Perform internal consistency checks
           */
           IMFS_assert(   the_jnode  );
           IMFS_assert(   the_jnode->type == IMFS_MEMORY_FILE  );
          
           /*
           * Verify new file size is supported
           */
           if (   new_length >= IMFS_MEMFILE_MAXIMUM_SIZE  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /*
           * Verify new file size is actually larger than current size
           */
           if (   new_length <= the_jnode->info.file.size  )
           return 0;
          
           /*
           * Calculate the number of range of blocks to allocate
           */
           new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
           old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
          
           /*
           * Now allocate each of those blocks.
           */
           for (   block=old_blocks ; block<=new_blocks ; block++  ) {
           if (   IMFS_memfile_addblock(   the_jnode,   block  )  ) {
           for (   ; block>=old_blocks ; block--  ) {
           IMFS_memfile_remove_block(   the_jnode,   block  );
           }
           rtems_set_errno_and_return_minus_one(   ENOSPC  );
           }
           }
          
           /*
           * Set the new length of the file.
           */
           the_jnode->info.file.size = new_length;
           return 0;
          }
          
          /*
           * IMFS_memfile_addblock
           *
           * This routine adds a single block to the specified in-memory file.
           */
     337  MEMFILE_STATIC int IMFS_memfile_addblock(  
           IMFS_jnode_t *the_jnode,  
           unsigned int block
           )
          {
           block_p memory;
           block_p *block_entry_ptr;
          
           IMFS_assert(   the_jnode  );
           IMFS_assert(   the_jnode->type == IMFS_MEMORY_FILE  );
          
           /*
           * Obtain the pointer for the specified block number
           */
           block_entry_ptr = IMFS_memfile_get_block_pointer(   the_jnode,   block,   1  );
           if (   *block_entry_ptr  )
           return 0;
          
           /*
           * There is no memory for this block number so allocate it.
           */
           memory = memfile_alloc_block(   );
           if (   !memory  )
           return 1;
          
           *block_entry_ptr = memory;
           return 0;
          }
          
          /*
           * IMFS_memfile_remove_block
           *
           * This routine removes the specified block from the in-memory file.
           *
           * NOTE: This is a support routine and is called only to remove
           * the last block or set of blocks in a file. Removing a
           * block from the middle of a file would be exceptionally
           * dangerous and the results unpredictable.
           */
     376  MEMFILE_STATIC int IMFS_memfile_remove_block(  
           IMFS_jnode_t *the_jnode,  
           unsigned int block
           )
          {
           block_p *block_ptr;
           block_p ptr;
          
           block_ptr = IMFS_memfile_get_block_pointer(   the_jnode,   block,   0  );
           IMFS_assert(   block_ptr  );
          
           ptr = *block_ptr;
           *block_ptr = 0;
           memfile_free_block(   ptr  );
          
           return 1;
          }
          
          /*
           * memfile_free_blocks_in_table
           *
           * This is a support routine for IMFS_memfile_remove. It frees all the
           * blocks in one of the indirection tables.
           */
     400  void memfile_free_blocks_in_table(  
           block_p **block_table,  
           int entries
           )
          {
           int i;
           block_p *b;
          
           /*
           * Perform internal consistency checks
           */
           IMFS_assert(   block_table  );
          
           /*
           * Now go through all the slots in the table and free the memory.
           */
           b = *block_table;
          
           for (   i=0 ; i<entries ; i++  ) {
           if (   b[i]  ) {
           memfile_free_block(   b[i]  );
           b[i] = 0;
           }
           }
          
           /*
           * Now that all the blocks in the block table are free,   we can
           * free the block table itself.
           */
           memfile_free_block(   *block_table  );
           *block_table = 0;
          }
          
          /*
           * IMFS_memfile_remove
           *
           * This routine frees all memory associated with an in memory file.
           *
           * NOTE: This is an exceptionally conservative implementation.
           * It will check EVERY pointer which is non-NULL and insure
           * any child non-NULL pointers are freed. Optimistically,   all that
           * is necessary is to scan until a NULL pointer is found. There
           * should be no allocated data past that point.
           *
           * In experimentation on the powerpc simulator,   it was noted
           * that using blocks which held 128 slots versus 16 slots made
           * a significant difference in the performance of this routine.
           *
           * Regardless until the IMFS implementation is proven,   it
           * is better to stick to simple,   easy to understand algorithms.
           */
     451  int IMFS_memfile_remove(  
           IMFS_jnode_t *the_jnode
           )
          {
           IMFS_memfile_t *info;
           int i;
           int j;
           unsigned int to_free;
           block_p *p;
          
           /*
           * Perform internal consistency checks
           */
           IMFS_assert(   the_jnode  );
           IMFS_assert(   the_jnode->type == IMFS_MEMORY_FILE  );
          
           /*
           * Eventually this could be set smarter at each call to
           * memfile_free_blocks_in_table to greatly speed this up.
           */
           to_free = IMFS_MEMFILE_BLOCK_SLOTS;
          
           /*
           * Now start freeing blocks in this order:
           * + indirect
           * + doubly indirect
           * + triply indirect
           */
           info = &the_jnode->info.file;
          
           if (   info->indirect  ) {
           memfile_free_blocks_in_table(   &info->indirect,   to_free  );
           }
          
           if (   info->doubly_indirect  ) {
           for (   i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++  ) {
           if (   info->doubly_indirect[i]  ) {
           memfile_free_blocks_in_table(  
           (  block_p ** )&info->doubly_indirect[i],   to_free  );
           }
           }
           memfile_free_blocks_in_table(   &info->doubly_indirect,   to_free  );
          
           }
          
           if (   info->triply_indirect  ) {
           for (   i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++  ) {
           p = (  block_p * ) info->triply_indirect[i];
           if (   !p  ) /* ensure we have a valid pointer */
           break;
           for (   j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++  ) {
           if (   p[j]  ) {
           memfile_free_blocks_in_table(   (  block_p ** )&p[j],   to_free );
           }
           }
           memfile_free_blocks_in_table(  
           (  block_p ** )&info->triply_indirect[i],   to_free  );
           }
           memfile_free_blocks_in_table(  
           (  block_p ** )&info->triply_indirect,   to_free  );
           }
          
           return 0;
          }
          
          /*
           * IMFS_memfile_read
           *
           * This routine read from memory file pointed to by the_jnode into
           * the specified data buffer specified by destination. The file
           * is NOT extended. An offset greater than the length of the file
           * is considered an error. Read from an offset for more bytes than
           * are between the offset and the end of the file will result in
           * reading the data between offset and the end of the file (  truncated
           * read ).
           */
          MEMFILE_STATIC ssize_t IMFS_memfile_read(  
           IMFS_jnode_t *the_jnode,  
           off_t start,  
           unsigned char *destination,  
           unsigned int length
           )
          {
           block_p *block_ptr;
           unsigned int block;
           unsigned int my_length;
           unsigned int to_copy = 0;
           unsigned int last_byte;
           unsigned int copied;
           unsigned int start_offset;
           unsigned char *dest;
          
     543   dest = destination;
          
           /*
           * Perform internal consistency checks
           */
     548   IMFS_assert(   the_jnode  );
     549   IMFS_assert(   the_jnode->type == IMFS_MEMORY_FILE ||
           the_jnode->type != IMFS_LINEAR_FILE  );
     551   IMFS_assert(   dest  );
          
           /*
           * Linear files (  as created from a tar file are easier to handle
           * than block files ).
           */
     557   my_length = length;
          
           if (  the_jnode->type == IMFS_LINEAR_FILE ) {
           unsigned char *file_ptr;
          
           file_ptr = (  unsigned char * )the_jnode->info.linearfile.direct;
          
           if (  my_length > (  the_jnode->info.linearfile.size - start ) )
           my_length = the_jnode->info.linearfile.size - start;
          
           memcpy(  dest,   &file_ptr[start],   my_length );
          
           IMFS_update_atime(   the_jnode  );
          
           return my_length;
           }
          
           /*
           * If the last byte we are supposed to read is past the end of this
           * in memory file,   then shorten the length to read.
           */
           last_byte = start + length;
           if (   last_byte > the_jnode->info.file.size  )
           my_length = the_jnode->info.file.size - start;
          
           copied = 0;
          
           /*
           * Three phases to the read:
           * + possibly the last part of one block
           * + all of zero of more blocks
           * + possibly the first part of one block
           */
          
           /*
           * Phase 1: possibly the last part of one block
           */
           start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
           block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
           if (   start_offset  ) {
           to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
           if (   to_copy > my_length  )
           to_copy = my_length;
           block_ptr = IMFS_memfile_get_block_pointer(   the_jnode,   block,   0  );
           if (   !block_ptr  )
           return copied;
           memcpy(   dest,   &(  *block_ptr )[ start_offset ],   to_copy  );
           dest += to_copy;
           block++;
           my_length -= to_copy;
           copied += to_copy;
           }
          
           /*
           * Phase 2: all of zero of more blocks
           */
           to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
           while (   my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK  ) {
           block_ptr = IMFS_memfile_get_block_pointer(   the_jnode,   block,   0  );
           if (   !block_ptr  )
           return copied;
           memcpy(   dest,   &(  *block_ptr )[ 0 ],   to_copy  );
           dest += to_copy;
           block++;
           my_length -= to_copy;
           copied += to_copy;
           }
          
           /*
           * Phase 3: possibly the first part of one block
           */
           IMFS_assert(   my_length < IMFS_MEMFILE_BYTES_PER_BLOCK  );
          
           if (   my_length  ) {
           block_ptr = IMFS_memfile_get_block_pointer(   the_jnode,   block,   0  );
           if (   !block_ptr  )
           return copied;
           memcpy(   dest,   &(  *block_ptr )[ 0 ],   my_length  );
           copied += my_length;
           }
          
           IMFS_update_atime(   the_jnode  );
          
           return copied;
          }
          
          /*
           * IMFS_memfile_write
           *
           * This routine writes the specified data buffer into the in memory
           * file pointed to by the_jnode. The file is extended as needed.
           */
          MEMFILE_STATIC ssize_t IMFS_memfile_write(  
           IMFS_jnode_t *the_jnode,  
           off_t start,  
           const unsigned char *source,  
           unsigned int length
           )
          {
           block_p *block_ptr;
           unsigned int block;
           int status;
           unsigned int my_length;
           unsigned int to_copy = 0;
           unsigned int last_byte;
           unsigned int start_offset;
           int copied;
           const unsigned char *src;
          
           src = source;
          
           /*
           * Perform internal consistency checks
           */
           IMFS_assert(   source  );
           IMFS_assert(   the_jnode  );
           IMFS_assert(   the_jnode->type == IMFS_MEMORY_FILE  );
          
           my_length = length;
           /*
           * If the last byte we are supposed to write is past the end of this
           * in memory file,   then extend the length.
           */
          
           last_byte = start + my_length;
           if (   last_byte > the_jnode->info.file.size  ) {
           status = IMFS_memfile_extend(   the_jnode,   last_byte  );
           if (   status  )
           rtems_set_errno_and_return_minus_one(   ENOSPC  );
           }
          
           copied = 0;
          
           /*
           * Three phases to the write:
           * + possibly the last part of one block
           * + all of zero of more blocks
           * + possibly the first part of one block
           */
          
           /*
           * Phase 1: possibly the last part of one block
           */
           start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
           block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
           if (   start_offset  ) {
           to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
           if (   to_copy > my_length  )
           to_copy = my_length;
           block_ptr = IMFS_memfile_get_block_pointer(   the_jnode,   block,   0  );
           if (   !block_ptr  )
           return copied;
           #if 0
           fprintf(  
           stderr,  
           "write %d at %d in %d: %*s\n",  
           to_copy,  
           start_offset,  
           block,  
           to_copy,  
           src
            );
           #endif
           memcpy(   &(  *block_ptr )[ start_offset ],   src,   to_copy  );
           src += to_copy;
           block++;
           my_length -= to_copy;
           copied += to_copy;
           }
          
           /*
           * Phase 2: all of zero of more blocks
           */
          
           to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
           while (   my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK  ) {
           block_ptr = IMFS_memfile_get_block_pointer(   the_jnode,   block,   0  );
           if (   !block_ptr  )
           return copied;
           #if 0
           fprintf(  stdout,   "write %d in %d: %*s\n",   to_copy,   block,   to_copy,   src  );
           #endif
           memcpy(   &(  *block_ptr )[ 0 ],   src,   to_copy  );
           src += to_copy;
           block++;
           my_length -= to_copy;
           copied += to_copy;
           }
          
           /*
           * Phase 3: possibly the first part of one block
           */
           IMFS_assert(   my_length < IMFS_MEMFILE_BYTES_PER_BLOCK  );
          
           to_copy = my_length;
           if (   my_length  ) {
           block_ptr = IMFS_memfile_get_block_pointer(   the_jnode,   block,   0  );
           if (   !block_ptr  )
           return copied;
           #if 0
           fprintf(  stdout,   "write %d in %d: %*s\n",   to_copy,   block,   to_copy,   src  );
           #endif
           memcpy(   &(  *block_ptr )[ 0 ],   src,   my_length  );
           my_length = 0;
           copied += to_copy;
           }
          
           IMFS_mtime_ctime_update(   the_jnode  );
          
           return copied;
          }
          
          /*
           * IMFS_memfile_get_block_pointer
           *
           * This routine looks up the block pointer associated with the given block
           * number. If that block has not been allocated and "malloc_it" is
           * TRUE,   then the block is allocated. Otherwise,   it is an error.
           */
          #if 0
          block_p *IMFS_memfile_get_block_pointer_DEBUG(  
           IMFS_jnode_t *the_jnode,  
           unsigned int block,  
           int malloc_it
           );
          
          block_p *IMFS_memfile_get_block_pointer(  
           IMFS_jnode_t *the_jnode,  
           unsigned int block,  
           int malloc_it
           )
          {
           block_p *p;
          
           p = IMFS_memfile_get_block_pointer_DEBUG(   the_jnode,   block,   malloc_it  );
           fprintf(  stdout,   "(  %d -> %p ) ",   block,   p  );
           return p;
          }
          
          block_p *IMFS_memfile_get_block_pointer_DEBUG(  
          #else
          block_p *IMFS_memfile_get_block_pointer(  
          #endif
           IMFS_jnode_t *the_jnode,  
           unsigned int block,  
           int malloc_it
           )
          {
           unsigned int my_block;
           IMFS_memfile_t *info;
           unsigned int singly;
           unsigned int doubly;
           unsigned int triply;
           block_p *p;
           block_p *p1;
           block_p *p2;
          
           /*
           * Perform internal consistency checks
           */
           IMFS_assert(   the_jnode  );
           IMFS_assert(   the_jnode->type == IMFS_MEMORY_FILE  );
          
           info = &the_jnode->info.file;
           my_block = block;
          
           /*
           * Is the block number in the simple indirect portion?
           */
           if (   my_block <= LAST_INDIRECT  ) {
           p = info->indirect;
          
           if (   malloc_it  ) {
          
           if (   !p  ) {
           p = memfile_alloc_block(   );
           if (   !p  )
           return 0;
           info->indirect = p;
           }
           return &info->indirect[ my_block ];
           }
          
           if (   !p  )
           return 0;
          
           return &info->indirect[ my_block ];
           }
          
           /*
           * Is the block number in the doubly indirect portion?
           */
          
           if (   my_block <= LAST_DOUBLY_INDIRECT  ) {
           my_block -= FIRST_DOUBLY_INDIRECT;
          
           singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
           doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
          
           p = info->doubly_indirect;
           if (   malloc_it  ) {
          
           if (   !p  ) {
           p = memfile_alloc_block(   );
           if (   !p  )
           return 0;
           info->doubly_indirect = p;
           }
          
           p1 = (  block_p * )p[ doubly ];
           if (   !p1  ) {
           p1 = memfile_alloc_block(   );
           if (   !p1  )
           return 0;
           p[ doubly ] = (  block_p ) p1;
           }
          
           return (  block_p * )&p1[ singly ];
           }
          
           if (   !p  )
           return 0;
          
           p = (  block_p * )p[ doubly ];
           if (   !p  )
           return 0;
          
           return (  block_p * )&p[ singly ];
           }
          
           /*
           * Is the block number in the triply indirect portion?
           */
           if (   my_block <= LAST_TRIPLY_INDIRECT  ) {
           my_block -= FIRST_TRIPLY_INDIRECT;
          
           singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
           doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
           triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
           doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
          
           p = info->triply_indirect;
          
           if (   malloc_it  ) {
           if (   !p  ) {
           p = memfile_alloc_block(   );
           if (   !p  )
           return 0;
           info->triply_indirect = p;
           }
          
           p1 = (  block_p * ) p[ triply ];
           if (   !p1  ) {
           p1 = memfile_alloc_block(   );
           if (   !p1  )
           return 0;
           p[ triply ] = (  block_p ) p1;
           }
          
           p2 = (  block_p * )p1[ doubly ];
           if (   !p2  ) {
           p2 = memfile_alloc_block(   );
           if (   !p2  )
           return 0;
           p1[ doubly ] = (  block_p ) p2;
           }
           return (  block_p * )&p2[ singly ];
           }
          
           if (   !p  )
           return 0;
          
           p1 = (  block_p * ) p[ triply ];
           if (   !p1  )
           return 0;
          
           p2 = (  block_p * )p1[ doubly ];
           if (   !p2  )
           return 0;
          
           return (  block_p * )&p2[ singly ];
           }
          
           /*
           * This means the requested block number is out of range.
           */
           return 0;
          }
          
          /*
           * memfile_alloc_block
           *
           * Allocate a block for an in-memory file.
           */
          int memfile_blocks_allocated = 0;
          
          void *memfile_alloc_block(  void )
          {
           void *memory;
          
           memory = (  void * )calloc(  1,   IMFS_MEMFILE_BYTES_PER_BLOCK );
           if (   memory  )
           memfile_blocks_allocated++;
          
           return memory;
          }
          
          /*
           * memfile_free_block
           *
           * Free a block from an in-memory file.
           */
          void memfile_free_block(  
           void *memory
           )
          {
           free(  memory );
           memfile_blocks_allocated--;
          }

libfs/src/imfs/miniimfs_init.c

       1  /**
           * @file
           *
           * @ingroup LibFSIMFS
           *
           * @brief Mini-IMFS initialization.
           */
          
          /*
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: miniimfs_init.c,  v 1.17 2010/07/15 08:46:06 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/libio_.h>
          
          #include "imfs.h"
          
          static const rtems_filesystem_operations_table miniIMFS_ops = {
           .evalpath_h = IMFS_eval_path,  
           .evalformake_h = IMFS_evaluate_for_make,  
           .link_h = rtems_filesystem_default_link,  
           .unlink_h = rtems_filesystem_default_unlink,  
           .node_type_h = IMFS_node_type,  
           .mknod_h = IMFS_mknod,  
           .chown_h = rtems_filesystem_default_chown,  
           .freenod_h = rtems_filesystem_default_freenode,  
           .mount_h = IMFS_mount,  
           .fsmount_me_h = miniIMFS_initialize,  
           .unmount_h = rtems_filesystem_default_unmount,  
           .fsunmount_me_h = rtems_filesystem_default_unmount,  
           .utime_h = rtems_filesystem_default_utime,  
           .eval_link_h = rtems_filesystem_default_evaluate_link,  
           .symlink_h = rtems_filesystem_default_symlink,  
           .readlink_h = rtems_filesystem_default_readlink,  
           .rename_h = rtems_filesystem_default_rename,  
           .statvfs_h = rtems_filesystem_default_statvfs
          };
          
      49  int miniIMFS_initialize(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           const void *data
           )
          {
           return IMFS_initialize_support(  
           mt_entry,  
           &miniIMFS_ops,  
           &rtems_filesystem_handlers_default,   /* for memfiles */
           &rtems_filesystem_handlers_default,   /* for directories */
           &rtems_filesystem_handlers_default /* for fifos */
            );
          }

libfs/src/nfsclient/proto/mount_prot_xdr.c

       1  /*
           * Please do not edit this file.
           * It was generated using rpcgen.
           */
          
          #include "mount_prot.h"
          
          bool_t
       9  xdr_fhandle (  XDR *xdrs,   fhandle objp )
          {
           if (  !xdr_opaque (  xdrs,   objp,   FHSIZE ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      17  xdr_fhstatus (  XDR *xdrs,   fhstatus *objp )
          {
           if (  !xdr_u_int (  xdrs,   &objp->fhs_status ) )
           return FALSE;
           switch (  objp->fhs_status ) {
           case 0:
           if (  !xdr_fhandle (  xdrs,   objp->fhstatus_u.fhs_fhandle ) )
           return FALSE;
           break;
           default:
           break;
           }
           return TRUE;
          }
          
          bool_t
      33  xdr_dirpath (  XDR *xdrs,   dirpath *objp )
          {
           if (  !xdr_string (  xdrs,   objp,   MNTPATHLEN ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      41  xdr_name (  XDR *xdrs,   name *objp )
          {
           if (  !xdr_string (  xdrs,   objp,   MNTNAMLEN ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      49  xdr_mountlist (  XDR *xdrs,   mountlist *objp )
          {
           if (  !xdr_pointer (  xdrs,   (  char ** )objp,   sizeof (  struct mountbody ),   (  xdrproc_t ) xdr_mountbody ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      57  xdr_mountbody (  XDR *xdrs,   mountbody *objp )
          {
           if (  !xdr_name (  xdrs,   &objp->ml_hostname ) )
           return FALSE;
           if (  !xdr_dirpath (  xdrs,   &objp->ml_directory ) )
           return FALSE;
           if (  !xdr_mountlist (  xdrs,   &objp->ml_next ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      69  xdr_groups (  XDR *xdrs,   groups *objp )
          {
           if (  !xdr_pointer (  xdrs,   (  char ** )objp,   sizeof (  struct groupnode ),   (  xdrproc_t ) xdr_groupnode ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      77  xdr_groupnode (  XDR *xdrs,   groupnode *objp )
          {
           if (  !xdr_name (  xdrs,   &objp->gr_name ) )
           return FALSE;
           if (  !xdr_groups (  xdrs,   &objp->gr_next ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      87  xdr_exports (  XDR *xdrs,   exports *objp )
          {
           if (  !xdr_pointer (  xdrs,   (  char ** )objp,   sizeof (  struct exportnode ),   (  xdrproc_t ) xdr_exportnode ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      95  xdr_exportnode (  XDR *xdrs,   exportnode *objp )
          {
           if (  !xdr_dirpath (  xdrs,   &objp->ex_dir ) )
           return FALSE;
           if (  !xdr_groups (  xdrs,   &objp->ex_groups ) )
           return FALSE;
           if (  !xdr_exports (  xdrs,   &objp->ex_next ) )
           return FALSE;
           return TRUE;
          }

libfs/src/nfsclient/proto/nfs_prot_xdr.c

       1  /*
           * Please do not edit this file.
           * It was generated using rpcgen.
           */
          
          #include "nfs_prot.h"
          #ifndef lint
          /*static char sccsid[] = "from: @(  # )nfs_prot.x 1.2 87/10/12 Copyr 1987 Sun Micro";*/
          /*static char sccsid[] = "from: @(  # )nfs_prot.x 2.1 88/08/01 4.0 RPCSRC";*/
           #if !defined(  __rtems__ )
           static char rcsid[] = "$Id: nfs_prot_xdr.c,  v 1.1 2008/02/26 19:23:53 joel Exp $";
           #endif
          #endif /* not lint */
          
          bool_t
      16  xdr_nfsstat (  XDR *xdrs,   nfsstat *objp )
          {
           if (  !xdr_enum (  xdrs,   (  enum_t * ) objp ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      24  xdr_ftype (  XDR *xdrs,   ftype *objp )
          {
           if (  !xdr_enum (  xdrs,   (  enum_t * ) objp ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      32  xdr_nfs_fh (  XDR *xdrs,   nfs_fh *objp )
          {
           if (  !xdr_opaque (  xdrs,   objp->data,   NFS_FHSIZE ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      40  xdr_nfstime (  XDR *xdrs,   nfstime *objp )
          {
           if (  !xdr_u_int (  xdrs,   &objp->seconds ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->useconds ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
      50  xdr_fattr (  XDR *xdrs,   fattr *objp )
          {
           register int32_t *buf;
          
          
           if (  xdrs->x_op == XDR_ENCODE ) {
           if (  !xdr_ftype (  xdrs,   &objp->type ) )
           return FALSE;
           buf = XDR_INLINE (  xdrs,   10 * BYTES_PER_XDR_UNIT );
           if (  buf == NULL ) {
           if (  !xdr_u_int (  xdrs,   &objp->mode ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->nlink ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->uid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->gid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->size ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->blocksize ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->rdev ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->blocks ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->fsid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->fileid ) )
           return FALSE;
          
           } else {
           IXDR_PUT_U_LONG(  buf,   objp->mode );
           IXDR_PUT_U_LONG(  buf,   objp->nlink );
           IXDR_PUT_U_LONG(  buf,   objp->uid );
           IXDR_PUT_U_LONG(  buf,   objp->gid );
           IXDR_PUT_U_LONG(  buf,   objp->size );
           IXDR_PUT_U_LONG(  buf,   objp->blocksize );
           IXDR_PUT_U_LONG(  buf,   objp->rdev );
           IXDR_PUT_U_LONG(  buf,   objp->blocks );
           IXDR_PUT_U_LONG(  buf,   objp->fsid );
           IXDR_PUT_U_LONG(  buf,   objp->fileid );
           }
           if (  !xdr_nfstime (  xdrs,   &objp->atime ) )
           return FALSE;
           if (  !xdr_nfstime (  xdrs,   &objp->mtime ) )
           return FALSE;
           if (  !xdr_nfstime (  xdrs,   &objp->ctime ) )
           return FALSE;
           return TRUE;
           } else if (  xdrs->x_op == XDR_DECODE ) {
           if (  !xdr_ftype (  xdrs,   &objp->type ) )
           return FALSE;
           buf = XDR_INLINE (  xdrs,   10 * BYTES_PER_XDR_UNIT );
           if (  buf == NULL ) {
           if (  !xdr_u_int (  xdrs,   &objp->mode ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->nlink ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->uid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->gid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->size ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->blocksize ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->rdev ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->blocks ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->fsid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->fileid ) )
           return FALSE;
          
           } else {
           objp->mode = IXDR_GET_U_LONG(  buf );
           objp->nlink = IXDR_GET_U_LONG(  buf );
           objp->uid = IXDR_GET_U_LONG(  buf );
           objp->gid = IXDR_GET_U_LONG(  buf );
           objp->size = IXDR_GET_U_LONG(  buf );
           objp->blocksize = IXDR_GET_U_LONG(  buf );
           objp->rdev = IXDR_GET_U_LONG(  buf );
           objp->blocks = IXDR_GET_U_LONG(  buf );
           objp->fsid = IXDR_GET_U_LONG(  buf );
           objp->fileid = IXDR_GET_U_LONG(  buf );
           }
           if (  !xdr_nfstime (  xdrs,   &objp->atime ) )
           return FALSE;
           if (  !xdr_nfstime (  xdrs,   &objp->mtime ) )
           return FALSE;
           if (  !xdr_nfstime (  xdrs,   &objp->ctime ) )
           return FALSE;
           return TRUE;
           }
          
           if (  !xdr_ftype (  xdrs,   &objp->type ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->mode ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->nlink ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->uid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->gid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->size ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->blocksize ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->rdev ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->blocks ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->fsid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->fileid ) )
           return FALSE;
           if (  !xdr_nfstime (  xdrs,   &objp->atime ) )
           return FALSE;
           if (  !xdr_nfstime (  xdrs,   &objp->mtime ) )
           return FALSE;
           if (  !xdr_nfstime (  xdrs,   &objp->ctime ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     179  xdr_sattr (  XDR *xdrs,   sattr *objp )
          {
           register int32_t *buf;
          
          
           if (  xdrs->x_op == XDR_ENCODE ) {
           buf = XDR_INLINE (  xdrs,   4 * BYTES_PER_XDR_UNIT );
           if (  buf == NULL ) {
           if (  !xdr_u_int (  xdrs,   &objp->mode ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->uid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->gid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->size ) )
           return FALSE;
          
           } else {
           IXDR_PUT_U_LONG(  buf,   objp->mode );
           IXDR_PUT_U_LONG(  buf,   objp->uid );
           IXDR_PUT_U_LONG(  buf,   objp->gid );
           IXDR_PUT_U_LONG(  buf,   objp->size );
           }
           if (  !xdr_nfstime (  xdrs,   &objp->atime ) )
           return FALSE;
           if (  !xdr_nfstime (  xdrs,   &objp->mtime ) )
           return FALSE;
           return TRUE;
           } else if (  xdrs->x_op == XDR_DECODE ) {
           buf = XDR_INLINE (  xdrs,   4 * BYTES_PER_XDR_UNIT );
           if (  buf == NULL ) {
           if (  !xdr_u_int (  xdrs,   &objp->mode ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->uid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->gid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->size ) )
           return FALSE;
          
           } else {
           objp->mode = IXDR_GET_U_LONG(  buf );
           objp->uid = IXDR_GET_U_LONG(  buf );
           objp->gid = IXDR_GET_U_LONG(  buf );
           objp->size = IXDR_GET_U_LONG(  buf );
           }
           if (  !xdr_nfstime (  xdrs,   &objp->atime ) )
           return FALSE;
           if (  !xdr_nfstime (  xdrs,   &objp->mtime ) )
           return FALSE;
           return TRUE;
           }
          
           if (  !xdr_u_int (  xdrs,   &objp->mode ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->uid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->gid ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->size ) )
           return FALSE;
           if (  !xdr_nfstime (  xdrs,   &objp->atime ) )
           return FALSE;
           if (  !xdr_nfstime (  xdrs,   &objp->mtime ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     248  xdr_filename (  XDR *xdrs,   filename *objp )
          {
           if (  !xdr_string (  xdrs,   objp,   NFS_MAXNAMLEN ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     256  xdr_nfspath (  XDR *xdrs,   nfspath *objp )
          {
           if (  !xdr_string (  xdrs,   objp,   NFS_MAXPATHLEN ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     264  xdr_attrstat (  XDR *xdrs,   attrstat *objp )
          {
           if (  !xdr_nfsstat (  xdrs,   &objp->status ) )
           return FALSE;
           switch (  objp->status ) {
           case NFS_OK:
           if (  !xdr_fattr (  xdrs,   &objp->attrstat_u.attributes ) )
           return FALSE;
           break;
           default:
           break;
           }
           return TRUE;
          }
          
          bool_t
     280  xdr_sattrargs (  XDR *xdrs,   sattrargs *objp )
          {
           if (  !xdr_nfs_fh (  xdrs,   &objp->file ) )
           return FALSE;
           if (  !xdr_sattr (  xdrs,   &objp->attributes ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     290  xdr_diropargs (  XDR *xdrs,   diropargs *objp )
          {
           if (  !xdr_nfs_fh (  xdrs,   &objp->dir ) )
           return FALSE;
           if (  !xdr_filename (  xdrs,   &objp->name ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     300  xdr_diropokres (  XDR *xdrs,   diropokres *objp )
          {
           if (  !xdr_nfs_fh (  xdrs,   &objp->file ) )
           return FALSE;
           if (  !xdr_fattr (  xdrs,   &objp->attributes ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     310  xdr_diropres (  XDR *xdrs,   diropres *objp )
          {
           if (  !xdr_nfsstat (  xdrs,   &objp->status ) )
           return FALSE;
           switch (  objp->status ) {
           case NFS_OK:
           if (  !xdr_diropokres (  xdrs,   &objp->diropres_u.diropres ) )
           return FALSE;
           break;
           default:
           break;
           }
           return TRUE;
          }
          
          bool_t
     326  xdr_readlinkres (  XDR *xdrs,   readlinkres *objp )
          {
           if (  !xdr_nfsstat (  xdrs,   &objp->status ) )
           return FALSE;
           switch (  objp->status ) {
           case NFS_OK:
           if (  !xdr_nfspath (  xdrs,   &objp->readlinkres_u.data ) )
           return FALSE;
           break;
           default:
           break;
           }
           return TRUE;
          }
          
          bool_t
     342  xdr_readargs (  XDR *xdrs,   readargs *objp )
          {
           if (  !xdr_nfs_fh (  xdrs,   &objp->file ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->offset ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->count ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->totalcount ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     356  xdr_readokres (  XDR *xdrs,   readokres *objp )
          {
           if (  !xdr_fattr (  xdrs,   &objp->attributes ) )
           return FALSE;
           if (  !xdr_bytes (  xdrs,   (  char ** )&objp->data.data_val,   (  u_int * ) &objp->data.data_len,   NFS_MAXDATA ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     366  xdr_readres (  XDR *xdrs,   readres *objp )
          {
           if (  !xdr_nfsstat (  xdrs,   &objp->status ) )
           return FALSE;
           switch (  objp->status ) {
           case NFS_OK:
           if (  !xdr_readokres (  xdrs,   &objp->readres_u.reply ) )
           return FALSE;
           break;
           default:
           break;
           }
           return TRUE;
          }
          
          bool_t
     382  xdr_writeargs (  XDR *xdrs,   writeargs *objp )
          {
           register int32_t *buf;
          
          
           if (  xdrs->x_op == XDR_ENCODE ) {
           if (  !xdr_nfs_fh (  xdrs,   &objp->file ) )
           return FALSE;
           buf = XDR_INLINE (  xdrs,   3 * BYTES_PER_XDR_UNIT );
           if (  buf == NULL ) {
           if (  !xdr_u_int (  xdrs,   &objp->beginoffset ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->offset ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->totalcount ) )
           return FALSE;
          
           } else {
           IXDR_PUT_U_LONG(  buf,   objp->beginoffset );
           IXDR_PUT_U_LONG(  buf,   objp->offset );
           IXDR_PUT_U_LONG(  buf,   objp->totalcount );
           }
           if (  !xdr_bytes (  xdrs,   (  char ** )&objp->data.data_val,   (  u_int * ) &objp->data.data_len,   NFS_MAXDATA ) )
           return FALSE;
           return TRUE;
           } else if (  xdrs->x_op == XDR_DECODE ) {
           if (  !xdr_nfs_fh (  xdrs,   &objp->file ) )
           return FALSE;
           buf = XDR_INLINE (  xdrs,   3 * BYTES_PER_XDR_UNIT );
           if (  buf == NULL ) {
           if (  !xdr_u_int (  xdrs,   &objp->beginoffset ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->offset ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->totalcount ) )
           return FALSE;
          
           } else {
           objp->beginoffset = IXDR_GET_U_LONG(  buf );
           objp->offset = IXDR_GET_U_LONG(  buf );
           objp->totalcount = IXDR_GET_U_LONG(  buf );
           }
           if (  !xdr_bytes (  xdrs,   (  char ** )&objp->data.data_val,   (  u_int * ) &objp->data.data_len,   NFS_MAXDATA ) )
           return FALSE;
           return TRUE;
           }
          
           if (  !xdr_nfs_fh (  xdrs,   &objp->file ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->beginoffset ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->offset ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->totalcount ) )
           return FALSE;
           if (  !xdr_bytes (  xdrs,   (  char ** )&objp->data.data_val,   (  u_int * ) &objp->data.data_len,   NFS_MAXDATA ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     443  xdr_createargs (  XDR *xdrs,   createargs *objp )
          {
           if (  !xdr_diropargs (  xdrs,   &objp->where ) )
           return FALSE;
           if (  !xdr_sattr (  xdrs,   &objp->attributes ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     453  xdr_renameargs (  XDR *xdrs,   renameargs *objp )
          {
           if (  !xdr_diropargs (  xdrs,   &objp->from ) )
           return FALSE;
           if (  !xdr_diropargs (  xdrs,   &objp->to ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     463  xdr_linkargs (  XDR *xdrs,   linkargs *objp )
          {
           if (  !xdr_nfs_fh (  xdrs,   &objp->from ) )
           return FALSE;
           if (  !xdr_diropargs (  xdrs,   &objp->to ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     473  xdr_symlinkargs (  XDR *xdrs,   symlinkargs *objp )
          {
           if (  !xdr_diropargs (  xdrs,   &objp->from ) )
           return FALSE;
           if (  !xdr_nfspath (  xdrs,   &objp->to ) )
           return FALSE;
           if (  !xdr_sattr (  xdrs,   &objp->attributes ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     485  xdr_nfscookie (  XDR *xdrs,   nfscookie *objp )
          {
           if (  !xdr_opaque (  xdrs,   objp->data,   NFS_COOKIESIZE ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     493  xdr_readdirargs (  XDR *xdrs,   readdirargs *objp )
          {
           if (  !xdr_nfs_fh (  xdrs,   &objp->dir ) )
           return FALSE;
           if (  !xdr_nfscookie (  xdrs,   &objp->cookie ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->count ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     505  xdr_entry (  XDR *xdrs,   entry *objp )
          {
           if (  !xdr_u_int (  xdrs,   &objp->fileid ) )
           return FALSE;
           if (  !xdr_filename (  xdrs,   &objp->name ) )
           return FALSE;
           if (  !xdr_nfscookie (  xdrs,   &objp->cookie ) )
           return FALSE;
           if (  !xdr_pointer (  xdrs,   (  char ** )&objp->nextentry,   sizeof (  entry ),   (  xdrproc_t ) xdr_entry ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     519  xdr_dirlist (  XDR *xdrs,   dirlist *objp )
          {
           if (  !xdr_pointer (  xdrs,   (  char ** )&objp->entries,   sizeof (  entry ),   (  xdrproc_t ) xdr_entry ) )
           return FALSE;
           if (  !xdr_bool (  xdrs,   &objp->eof ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     529  xdr_readdirres (  XDR *xdrs,   readdirres *objp )
          {
           if (  !xdr_nfsstat (  xdrs,   &objp->status ) )
           return FALSE;
           switch (  objp->status ) {
           case NFS_OK:
           if (  !xdr_dirlist (  xdrs,   &objp->readdirres_u.reply ) )
           return FALSE;
           break;
           default:
           break;
           }
           return TRUE;
          }
          
          bool_t
     545  xdr_statfsokres (  XDR *xdrs,   statfsokres *objp )
          {
           register int32_t *buf;
          
          
           if (  xdrs->x_op == XDR_ENCODE ) {
           buf = XDR_INLINE (  xdrs,   5 * BYTES_PER_XDR_UNIT );
           if (  buf == NULL ) {
           if (  !xdr_u_int (  xdrs,   &objp->tsize ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->bsize ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->blocks ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->bfree ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->bavail ) )
           return FALSE;
           } else {
           IXDR_PUT_U_LONG(  buf,   objp->tsize );
           IXDR_PUT_U_LONG(  buf,   objp->bsize );
           IXDR_PUT_U_LONG(  buf,   objp->blocks );
           IXDR_PUT_U_LONG(  buf,   objp->bfree );
           IXDR_PUT_U_LONG(  buf,   objp->bavail );
           }
           return TRUE;
           } else if (  xdrs->x_op == XDR_DECODE ) {
           buf = XDR_INLINE (  xdrs,   5 * BYTES_PER_XDR_UNIT );
           if (  buf == NULL ) {
           if (  !xdr_u_int (  xdrs,   &objp->tsize ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->bsize ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->blocks ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->bfree ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->bavail ) )
           return FALSE;
           } else {
           objp->tsize = IXDR_GET_U_LONG(  buf );
           objp->bsize = IXDR_GET_U_LONG(  buf );
           objp->blocks = IXDR_GET_U_LONG(  buf );
           objp->bfree = IXDR_GET_U_LONG(  buf );
           objp->bavail = IXDR_GET_U_LONG(  buf );
           }
           return TRUE;
           }
          
           if (  !xdr_u_int (  xdrs,   &objp->tsize ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->bsize ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->blocks ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->bfree ) )
           return FALSE;
           if (  !xdr_u_int (  xdrs,   &objp->bavail ) )
           return FALSE;
           return TRUE;
          }
          
          bool_t
     608  xdr_statfsres (  XDR *xdrs,   statfsres *objp )
          {
           if (  !xdr_nfsstat (  xdrs,   &objp->status ) )
           return FALSE;
           switch (  objp->status ) {
           case NFS_OK:
           if (  !xdr_statfsokres (  xdrs,   &objp->statfsres_u.reply ) )
           return FALSE;
           break;
           default:
           break;
           }
           return TRUE;
          }

libfs/src/nfsclient/src/cexphelp.c

       1  #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <librtemsNfs.h>
          #include <cexpHelp.h>
       7  CEXP_HELP_TAB_BEGIN(  rtemsNfs )
           HELP(  
          "Mount a remote filesystem (  NFS ). The mount point (  must not be a NFS dir )\n"
          "is created on the fly if not existing already.\n"
          "uid/gid to use may be specified:\n"
          " hostspec: [uid.gid@]hostname_or_ipaddr\n"
           ,   int,   nfsMount,   (  char *hostspec,   char *exportdir,   char *mntpoint )
            ),  
           HELP(  
          "Print all currently mounted NFS directories to open file handle.\n"
          "Pass f = 0 to print to stdout\n"
           ,   int,   nfsMountsShow,   (  FILE *f )
            ),  
          CEXP_HELP_TAB_END

libfs/src/nfsclient/src/dirutils.c

       1  /* $Id: dirutils.c,  v 1.5 2010/05/29 02:31:09 ralf Exp $ */
          
          /* very crude and basic fs utilities for testing the NFS */
          
          /* Till Straumann,   <strauman@slac.stanford.edu>,   10/2002 */
          
          /*
           * Authorship
           * ----------
           * This software (  NFS-2 client implementation for RTEMS ) was created by
           * Till Straumann <strauman@slac.stanford.edu>,   2002-2007,  
           * Stanford Linear Accelerator Center,   Stanford University.
           *
           * Acknowledgement of sponsorship
           * ------------------------------
           * The NFS-2 client implementation for RTEMS was produced by
           * the Stanford Linear Accelerator Center,   Stanford University,  
           * under Contract DE-AC03-76SFO0515 with the Department of Energy.
           *
           * Government disclaimer of liability
           * ----------------------------------
           * Neither the United States nor the United States Department of Energy,  
           * nor any of their employees,   makes any warranty,   express or implied,   or
           * assumes any legal liability or responsibility for the accuracy,  
           * completeness,   or usefulness of any data,   apparatus,   product,   or process
           * disclosed,   or represents that its use would not infringe privately owned
           * rights.
           *
           * Stanford disclaimer of liability
           * --------------------------------
           * Stanford University makes no representations or warranties,   express or
           * implied,   nor assumes any liability for the use of this software.
           *
           * Stanford disclaimer of copyright
           * --------------------------------
           * Stanford University,   owner of the copyright,   hereby disclaims its
           * copyright and all other rights in this software. Hence,   anyone may
           * freely use it for any purpose without restriction.
           *
           * Maintenance of notices
           * ----------------------
           * In the interest of clarity regarding the origin and status of this
           * SLAC software,   this and all the preceding Stanford University notices
           * are to remain affixed to any copy or derivative of this software made
           * or distributed by the recipient and are to be affixed to any copy of
           * software made or distributed by the recipient that contains a copy or
           * derivative of this software.
           *
           * ------------------ SLAC Software Notices,   Set 4 OTT.002a,   2004 FEB 03
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef __vxworks
          #include <vxWorks.h>
          #endif
          #include <stdio.h>
          #include <dirent.h>
          #include <unistd.h>
          #include <string.h>
          #include <fcntl.h>
          #include <sys/stat.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <limits.h> /* PATH_MAX */
          
          #include <inttypes.h> /* PRI* */
          
          #if SIZEOF_MODE_T == 8
          #define PRIomode_t PRIo64
          #elif SIZEOF_MODE_T == 4
          #define PRIomode_t PRIo32
          #else
          #error "unsupport size of mode_t"
          #endif
          
          #if SIZEOF_OFF_T == 8
          #define PRIdoff_t PRIo64
          #elif SIZEOF_OFF_T == 4
          #define PRIdoff_t PRIo32
          #else
          #error "unsupported size of off_t"
          #endif
          
          #ifdef HAVE_CEXP
          #include <cexpHelp.h>
          #endif
          
          #ifndef __vxworks
          int
      93  pwd(  void )
          {
          char buf[PATH_MAX];
          
           if (   !getcwd(  buf,  PATH_MAX ) ) {
           perror(  "getcwd" );
           return -1;
           } else {
           printf(  "%s\n",  buf );
           }
           return 0;
          }
          
          static int
     107  ls_r(  char *path,   char *chpt,   char *name,   struct stat *buf )
          {
          char *t;
           sprintf(  chpt,   "/%s",   name );
           if (  lstat(  path,  buf ) ) {
           fprintf(  stderr,  "stat(  %s ): %s\n",   path,   strerror(  errno ) );
           return -1;
           }
           switch (   buf->st_mode & S_IFMT  ) {
           case S_IFSOCK:
           case S_IFIFO: t = "|"; break;
          
           default:
           case S_IFREG:
           case S_IFBLK:
           case S_IFCHR:
           t = ""; break;
           case S_IFDIR:
           t = "/"; break;
           case S_IFLNK:
           t = "@"; break;
           }
          
           printf(  "%10li,   %10" PRIdoff_t "b,   %5i.%-5i 0%04" PRIomode_t " %s%s\n",  
           buf->st_ino,  
           buf->st_size,  
           buf->st_uid,  
           buf->st_gid,  
           buf->st_mode & ~S_IFMT,  
           name,  
           t );
           *chpt = 0;
           return 0;
          }
          
          int
     143  ls(  char *dir,   char *opts )
          {
          struct dirent *de;
          char path[PATH_MAX+1];
          char *chpt;
          DIR *dp = 0;
          int rval = -1;
          struct stat buf;
          
           if (   !dir  )
           dir = ".";
          
           strncpy(  path,   dir,   PATH_MAX );
           path[PATH_MAX] = 0;
           chpt = path+strlen(  path );
          
           if (   !(  dp=opendir(  dir ) )  ) {
           perror(  "opendir" );
           goto cleanup;
           }
          
           while (   (  de = readdir(  dp ) )  ) {
           ls_r(  path,   chpt,   de->d_name,   &buf );
           }
          
           rval = 0;
          
          cleanup:
           if (  dp )
           closedir(  dp );
           return rval;
          }
          #endif
          
          #if 0
     178   fprintf(  stderr,   "usage: cp(  ""from"",  [""to""[,  ""-f""]]\n" );
     179   fprintf(  stderr,   " ""to""==NULL -> stdout\n" );
     180   fprintf(  stderr,   " ""-f"" -> overwrite existing file\n" );
          #endif
          
          int
     184  cp(  char *from,   char *to,   char *opts )
          {
          struct stat st;
          int rval = -1;
          int fd = -1;
          FILE *fst = 0;
          FILE *tst = 0;
          int flags = O_CREAT | O_WRONLY | O_TRUNC | O_EXCL;
          
           if (  from ) {
          
           if (  (  fd=open(  from,  O_RDONLY,  0 ) ) < 0 ) {
           fprintf(  stderr,  
           "Opening %s for reading: %s\n",  
           from,  
           strerror(  errno ) );
           goto cleanup;
           }
          
           if (  fstat(  fd,   &st ) ) {
           fprintf(  stderr,  
           "rstat(  %s ): %s\n",  
           from,  
           strerror(  errno ) );
           goto cleanup;
           }
          
          
           if (  !S_ISREG(  st.st_mode ) ) {
           fprintf(  stderr,  "Refuse to copy a non-regular file\n" );
           errno = EINVAL;
           goto cleanup;
           }
           /* Now create a stream -- I experienced occasional weirdness
           * when circumventing the streams attached to fildno(  stdin )
           * by reading/writing to the underlying fd's directly ->
           * for now we always go through buffered I/O...
           */
           if (   !(  fst=fdopen(  fd,  "r" ) )  ) {
           fprintf(  stderr,  
           "Opening input stream [fdopen(   )] failed: %s\n",  
           strerror(  errno ) );
           goto cleanup;
           }
           /* at this point,   we have a stream and don't need 'fd' anymore */
           fd = -1;
          
           } else {
           fst = stdin;
           st.st_mode = 0644;
           }
          
           if (  opts && strchr(  opts,  'f' ) )
           flags &= ~ O_EXCL;
          
           if (  to ) {
           if (   (  fd=open(  to,  flags,  st.st_mode ) ) < 0  ) {
           fprintf(  stderr,  
           "Opening %s for writing: %s\n",  
           to,  
           strerror(  errno ) );
           goto cleanup;
           }
           if (   !(  tst=fdopen(  fd,   "w" ) )  ) {
           fprintf(  stderr,  
           "Opening output stream [fdopen(   )] failed: %s\n",  
           strerror(  errno ) );
           goto cleanup;
           }
           /* at this point we have a stream and don't need 'fd' anymore */
           fd = -1;
           } else {
           tst = stdout;
           }
          
           /* clear old errors */
           clearerr(  fst );
           clearerr(  tst );
          
           /* use macro versions on register vars; stdio is already buffered,  
           * there's nothing to be gained by reading/writing blocks into
           * a secondary buffer...
           */
           {
           register int ch;
           register FILE *f = fst;
           register FILE *t = tst;
           while (   EOF != (  ch = getc(  f ) ) && EOF != putc(  ch,   t )  )
           /* nothing else */;
           }
          
           if (   ferror(  fst )  ) {
           fprintf(  stderr,  "Read error: %s\n",  strerror(  errno ) );
           goto cleanup;
           }
           if (   ferror(  tst )  ) {
           fprintf(  stderr,  "Write error: %s\n",  strerror(  errno ) );
           goto cleanup;
           }
          
           rval = 0;
          
          cleanup:
          
           if (   fd >= 0  )
           close(  fd );
          
           if (   fst  ) {
           if (   from  )
           fclose(  fst );
           else
           clearerr(  fst );
           }
           if (   tst  ) {
           if (   to  )
           fclose(  tst );
           else {
           /* flush stdout */
           fflush(  tst );
           clearerr(  tst );
           }
           }
          
           return rval;
          }
          
          int
     311  ln(  char *to,   char *name,   char *opts )
          {
           if (  !to ) {
           fprintf(  stderr,  "ln: need 'to' argument\n" );
           return -1;
           }
           if (  !name ) {
           if (   !(  name = strrchr(  to,  '/' ) )  ) {
           fprintf(  stderr,  
           "ln: 'unable to link %s to %s\n",  
           to,  to );
           return -1;
           }
           name++;
           }
           if (  opts || strchr(  opts,  's' ) ) {
           if (  symlink(  name,  to ) ) {
           fprintf(  stderr,  "symlink: %s\n",  strerror(  errno ) );
           return -1;
           }
           } else {
           if (  link(  name,  to ) ) {
           fprintf(  stderr,  "hardlink: %s\n",  strerror(  errno ) );
           return -1;
           }
           }
           return 0;
          }
          
          int
     341  rm(  char *path )
          {
           return unlink(  path );
          }
          
          int
     347  cd(  char *path )
          {
           return chdir(  path );
          }
          
          #ifdef HAVE_CEXP
          static CexpHelpTabRec _cexpHelpTabDirutils[] __attribute__(  (  unused ) ) = {
     354   HELP(  
          "copy a file: cp(  ""from"",  [""to""[,  ""-f""]] )\n\
           from = NULL <-- stdin\n\
           to = NULL --> stdout\n\
           option -f: overwrite existing file\n",  
           int,  
           cp,   (  char *from,   char *to,   char *options )
            ),  
           HELP(  
          "list a directory: ls(  [""dir""] )\n",  
           int,  
           ls,   (  char *dir )
            ),  
           HELP(  
          "remove a file\n",  
           int,  
           rm,   (  char *path )
            ),  
           HELP(  
          "change the working directory\n",  
           int,  
           cd,   (  char *path )
            ),  
           HELP(  
          "create a link: ln(  ""to"",  ""name"",  ""[-s]""\n\
           -s creates a symlink\n",  
           int,  
           ln,   (  char *to,   char *name,   char *options )
            ),  
           HELP(  "",  ,  0,   )
          };
          #endif

libfs/src/nfsclient/src/nfs.c

          /* $Id: nfs.c,  v 1.26 2010/08/25 09:37:48 sh Exp $ */
          
          /* NFS client implementation for RTEMS; hooks into the RTEMS filesystem */
          
          /* Author: Till Straumann <strauman@slac.stanford.edu> 2002 */
          
          /* Hacked on by others. */
          
          /*
           * Authorship
           * ----------
           * This software (  NFS-2 client implementation for RTEMS ) was created by
           * Till Straumann <strauman@slac.stanford.edu>,   2002-2007,  
           * Stanford Linear Accelerator Center,   Stanford University.
           *
           * Acknowledgement of sponsorship
           * ------------------------------
           * The NFS-2 client implementation for RTEMS was produced by
           * the Stanford Linear Accelerator Center,   Stanford University,  
           * under Contract DE-AC03-76SFO0515 with the Department of Energy.
           *
           * Government disclaimer of liability
           * ----------------------------------
           * Neither the United States nor the United States Department of Energy,  
           * nor any of their employees,   makes any warranty,   express or implied,   or
           * assumes any legal liability or responsibility for the accuracy,  
           * completeness,   or usefulness of any data,   apparatus,   product,   or process
           * disclosed,   or represents that its use would not infringe privately owned
           * rights.
           *
           * Stanford disclaimer of liability
           * --------------------------------
           * Stanford University makes no representations or warranties,   express or
           * implied,   nor assumes any liability for the use of this software.
           *
           * Stanford disclaimer of copyright
           * --------------------------------
           * Stanford University,   owner of the copyright,   hereby disclaims its
           * copyright and all other rights in this software. Hence,   anyone may
           * freely use it for any purpose without restriction.
           *
           * Maintenance of notices
           * ----------------------
           * In the interest of clarity regarding the origin and status of this
           * SLAC software,   this and all the preceding Stanford University notices
           * are to remain affixed to any copy or derivative of this software made
           * or distributed by the recipient and are to be affixed to any copy of
           * software made or distributed by the recipient that contains a copy or
           * derivative of this software.
           *
           * ------------------ SLAC Software Notices,   Set 4 OTT.002a,   2004 FEB 03
           */
          
          #ifdef HAVE_CONFIG_H
          #include <config.h>
          #endif
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          #include <string.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <assert.h>
          #include <sys/stat.h>
          #include <dirent.h>
          #include <netdb.h>
          #include <ctype.h>
          #include <netinet/in.h>
          #include <arpa/inet.h>
          
          #include <nfs_prot.h>
          #include <mount_prot.h>
          
          #include "rpcio.h"
          
          /* Configurable parameters */
          
          /* Estimated average length of a filename (  including terminating 0 ).
           * This was calculated by doing
           *
           * find <some root> -print -exec basename '{}' \; > feil
           * wc feil
           *
           * AVG_NAMLEN = (  num_chars + num_lines )/num_lines
           */
          #define CONFIG_AVG_NAMLEN 10
          
          #define CONFIG_NFS_SMALL_XACT_SIZE 800 /* size of RPC arguments for non-write ops */
          /* lifetime of NFS attributes in a NfsNode;
           * the time is in seconds and the lifetime is
           * infinite if the symbol is #undef
           */
          #define CONFIG_ATTR_LIFETIME 10/*secs*/
          
          /*
           * The 'st_blksize' (  stat(  2 ) ) value this nfs
           * client should report. If set to zero then the server's fattr data
           * is passed throught which is not necessary optimal.
           * Newlib's stdio uses 'st_blksize' (  if built with HAVE_BLKSIZE defined )
           * to size the default buffer.
           * Due to the overhead of NFS it is probably better to use the maximum
           * size of an NFS read request (  8k ) rather than the optimal block
           * size on the server.
           * This value can be overridden at run-time by setting the global
           * variable 'nfsStBlksize'.
           * Thanks to Steven Johnson <sjohnson@sakuraindustries.com> for helping
           * working on this issue.
           */
          #define DEFAULT_NFS_ST_BLKSIZE NFS_MAXDATA
          
          /* dont change this without changing the maximal write size */
          #define CONFIG_NFS_BIG_XACT_SIZE UDPMSGSIZE /* dont change this */
          
          /* The real values for these are specified further down */
          #define NFSCALL_TIMEOUT (  &_nfscalltimeout )
          #define MNTCALL_TIMEOUT (  &_nfscalltimeout )
          static struct timeval _nfscalltimeout = { 10,   0 }; /* {secs,   us } */
          
          /* More or less fixed constants; in particular,   NFS3 is not supported */
          #define DELIM '/'
          #define HOSTDELIM ':'
          #define UPDIR ".."
          #define UIDSEP '@'
          #define NFS_VERSION_2 NFS_VERSION
          
          /* we use a dynamically assigned major number */
          #define NFS_MAJOR (  nfsGlob.nfs_major )
          
          
          /* NOTE: RTEMS (  ss-20020301 ) uses a 'short st_ino' type :-(   but the
           * NFS fileid is 32 bit. [Later versions of RTEMS have fixed this;
           * nfsInit(   ) issues a warning if you run a version with 'short st_ino'.]
           *
           * As a workarount,   we merge the upper 16bits of the fileid into the
           * minor device no. Hence,   it is still possible to uniquely identify
           * a file by looking at its device number (  major = nfs,   minor = part
           * of the fileid + our 'nfs-id' identifier ).
           *
           * This has an impact on performance,   as e.g. getcwd(   ) stats(   ) all
           * directory entries when it believes it has crossed a mount point
           * (  a.st_dev != b.st_dev ).
           *
           * OTOH,   it also might cause node comparison failure! E.g. 'getcwd(   )'
           * assumes that two nodes residing in the same directory must be located
           * on the same device and hence compares 'st_ino' only.
           * If two files in the same directory have the same inode number
           * modulo 2^16,   they will be considered equal (  although their device
           * number doesn't match - getcwd doesn't look at it ).
           *
           * Other software might or might not be affected.
           *
           * The only clean solution to this problem is bumping up the size of
           * 'ino_t' at least to 'long'.
           * Note that this requires _all_ software (  libraries etc. ) to be
           * recompiled.
           */
          
          #define NFS_MAKE_DEV_T_INO_HACK(  node ) \
           rtems_filesystem_make_dev_t(   NFS_MAJOR,   \
           (  (  (  rtems_device_minor_number )(  (  node )->nfs->id ) )<<16 ) | (  (  (  rtems_device_minor_number )SERP_ATTR(  (  node ) ).fileid ) >> 16 )  )
          
          /* use our 'nfs id' and the server's fsid for the minor device number
           * this should be fairly unique
           */
          #define NFS_MAKE_DEV_T(  node ) \
           rtems_filesystem_make_dev_t(   NFS_MAJOR,   \
           (  (  (  rtems_device_minor_number )(  (  node )->nfs->id ) )<<16 ) | (  SERP_ATTR(  (  node ) ).fsid & (  (  (  rtems_device_minor_number )1<<16 )-1 ) )  )
          
          #define DIRENT_HEADER_SIZE (   sizeof(  struct dirent ) - \
           sizeof(   (  (  struct dirent * )0 )->d_name  )  )
          
          
          /* debugging flags */
          #define DEBUG_COUNT_NODES (  1<<0 )
          #define DEBUG_TRACK_NODES (  1<<1 )
          #define DEBUG_EVALPATH (  1<<2 )
          #define DEBUG_READDIR (  1<<3 )
          #define DEBUG_SYSCALLS (  1<<4 )
          
          /* #define DEBUG (   DEBUG_SYSCALLS | DEBUG_COUNT_NODES  ) */
          
          #ifdef DEBUG
          #define STATIC
          #else
          #define STATIC static
          #endif
          
          #define MUTEX_ATTRIBUTES (  RTEMS_LOCAL | \
           RTEMS_PRIORITY | \
           RTEMS_INHERIT_PRIORITY | \
           RTEMS_BINARY_SEMAPHORE )
          
          #define LOCK(  s ) do { \
           rtems_semaphore_obtain(  (  s ),   \
           RTEMS_WAIT,   \
           RTEMS_NO_TIMEOUT ); \
           } while (  0 )
          
          #define UNLOCK(  s ) do { rtems_semaphore_release(  (  s ) ); \
           } while (  0 )
          
          /*****************************************
     205   Types with Associated XDR Routines
           *****************************************/
          
          /* a string buffer with a maximal length.
           * If the buffer pointer is NULL,   it is updated
           * with an appropriately allocated area.
           */
          typedef struct strbuf {
           char *buf;
           u_int max;
          } strbuf;
          
          static bool_t
          xdr_strbuf(  XDR *xdrs,   strbuf *obj )
          {
           return xdr_string(  xdrs,   &obj->buf,   obj->max );
     221  }
          
          /* Read 'readlink' results into a 'strbuf'.
           * This is convenient as it avoids
           * one extra step of copying / lenght
           * checking.
           */
          typedef struct readlinkres_strbuf {
           nfsstat status;
           strbuf strbuf;
          } readlinkres_strbuf;
          
          static bool_t
          xdr_readlinkres_strbuf(  XDR *xdrs,   readlinkres_strbuf *objp )
          {
           if (   !xdr_nfsstat(  xdrs,   &objp->status )  )
           return FALSE;
          
           if (   NFS_OK == objp->status  ) {
           if (   !xdr_string(  xdrs,   &objp->strbuf.buf,   objp->strbuf.max )  )
           return FALSE;
           }
           return TRUE;
          }
          
          
          /* DirInfoRec is used instead of dirresargs
           * to convert recursion into iteration. The
           * 'rpcgen'erated xdr_dirresargs ends up
           * doing nested calls when unpacking the
           * 'next' pointers.
           */
          
     254  typedef struct DirInfoRec_ {
           readdirargs readdirargs;
           /* clone of the 'readdirres' fields;
           * the cookie is put into the readdirargs above
           */
           nfsstat status;
           char *buf,   *ptr;
           int len;
           bool_t eofreached;
          } DirInfoRec,   *DirInfo;
          
          /* this deals with one entry / record */
          static bool_t
          xdr_dir_info_entry(  XDR *xdrs,   DirInfo di )
          {
          union {
           char nambuf[NFS_MAXNAMLEN+1];
           nfscookie cookie;
          } dummy;
          struct dirent *pde = (  struct dirent * )di->ptr;
          u_int fileid;
          char *name;
          register int nlen = 0,  len,  naligned = 0;
          nfscookie *pcookie;
          
           len = di->len;
          
           if (   !xdr_u_int(  xdrs,   &fileid )  )
           return FALSE;
          
           /* we must pass the address of a char* */
           name = (  len > NFS_MAXNAMLEN ) ? pde->d_name : dummy.nambuf;
          
           if (   !xdr_filename(  xdrs,   &name )  ) {
           return FALSE;
           }
          
           if (  len >= 0 ) {
           nlen = strlen(  name );
           naligned = nlen + 1 /* string delimiter */ + 3 /* alignment */;
           naligned &= ~3;
           len -= naligned;
           }
          
           /* if the cookie goes into the DirInfo,   we hope this doesn't fail
           * - the caller ends up with an invalid readdirargs cookie otherwise...
           */
           pcookie = (  len >= 0 ) ? &di->readdirargs.cookie : &dummy.cookie;
           if (   !xdr_nfscookie(  xdrs,   pcookie )  ) {
           return FALSE;
           }
          
           di->len = len;
           /* adjust the buffer pointer */
           if (  len >= 0 ) {
           pde->d_ino = fileid;
           pde->d_namlen = nlen;
     311   pde->d_off = di->ptr - di->buf;
           if (  name == dummy.nambuf ) {
           memcpy(  pde->d_name,   dummy.nambuf,   nlen + 1 );
           }
           pde->d_reclen = DIRENT_HEADER_SIZE + naligned;
           di->ptr += pde->d_reclen;
           }
          
           return TRUE;
          }
          
          /* this routine loops over all entries */
          static bool_t
          xdr_dir_info(  XDR *xdrs,   DirInfo di )
          {
          DirInfo dip;
          
           if (   !xdr_nfsstat(  xdrs,   &di->status )  )
           return FALSE;
          
           if (   NFS_OK != di->status  )
           return TRUE;
          
           dip = di;
          
           while (  dip ) {
           /* reserve space for the dirent 'header' - we assume it's word aligned! */
          #ifdef DEBUG
           assert(   DIRENT_HEADER_SIZE % 4 == 0  );
          #endif
           dip->len -= DIRENT_HEADER_SIZE;
          
           /* we pass a 0 size - size is unused since
           * we always pass a non-NULL pointer
           */
           if (   !xdr_pointer(  xdrs,   (  void* )&dip,   0 /* size */,   (  xdrproc_t )xdr_dir_info_entry )  )
           return FALSE;
           }
          
           if (   ! xdr_bool(  xdrs,   &di->eofreached )  )
           return FALSE;
          
           /* if everything fits into the XDR buffer but not the user's buffer,  
           * they must resume reading from where xdr_dir_info_entry(   ) started
           * skipping and 'eofreached' needs to be adjusted
           */
           if (   di->len < 0 && di->eofreached  )
           di->eofreached = FALSE;
          
           return TRUE;
          }
          
          
          /* a type better suited for node operations
           * than diropres.
           * fattr and fhs are swapped so parts of this
           * structure may be used as a diroparg which
           * is practical when looking up paths.
           */
          
          /* Macro for accessing serporid fields
           */
          #define SERP_ARGS(  node ) (  (  node )->serporid.serporid_u.serporid.arg_u )
          #define SERP_ATTR(  node ) (  (  node )->serporid.serporid_u.serporid.attributes )
          #define SERP_FILE(  node ) (  (  node )->serporid.serporid_u.serporid.file )
          
          
          typedef struct serporidok {
           fattr attributes;
           nfs_fh file;
           union {
           struct {
           filename name;
           } diroparg;
           struct {
           sattr attributes;
           } sattrarg;
           struct {
           uint32_t offset;
           uint32_t count;
           uint32_t totalcount;
           } readarg;
           struct {
           uint32_t beginoffset;
           uint32_t offset;
           uint32_t totalcount;
           struct {
           uint32_t data_len;
           char* data_val;
           } data;
           } writearg;
           struct {
           filename name;
           sattr attributes;
           } createarg;
           struct {
           filename name;
           diropargs to;
           } renamearg;
           struct {
           diropargs to;
           } linkarg;
           struct {
           filename name;
           nfspath to;
           sattr attributes;
           } symlinkarg;
           struct {
           nfscookie cookie;
           uint32_t count;
           } readdirarg;
           } arg_u;
          } serporidok;
          
          typedef struct serporid {
           nfsstat status;
           union {
           serporidok serporid;
           } serporid_u;
          } serporid;
          
          /* an XDR routine to encode/decode the inverted diropres
     433   * into an nfsnodestat;
           *
           * NOTE: this routine only acts on
           * - 'serporid.status'
           * - 'serporid.file'
           * - 'serporid.attributes'
           * and leaves the 'arg_u' alone.
           *
           * The idea is that a 'diropres' is read into 'serporid'
           * which can then be used as an argument to subsequent
     443   * NFS-RPCs (  after filling in the node's arg_u ).
           */
          static bool_t
          xdr_serporidok(  XDR *xdrs,   serporidok *objp )
          {
           if (  !xdr_nfs_fh (  xdrs,   &objp->file ) )
           return FALSE;
           if (  !xdr_fattr (  xdrs,   &objp->attributes ) )
           return FALSE;
           return TRUE;
          }
          
          static bool_t
          xdr_serporid(  XDR *xdrs,   serporid *objp )
          {
           if (  !xdr_nfsstat (  xdrs,   &objp->status ) )
           return FALSE;
           switch (  objp->status ) {
           case NFS_OK:
           if (  !xdr_serporidok(  xdrs,   &objp->serporid_u.serporid ) )
           return FALSE;
           break;
           default:
           break;
           }
           return TRUE;
          }
     470  
          /*****************************************
           Data Structures and Types
           *****************************************/
          
          /* 'time(   )' hack with less overhead; */
          
          /* assume reading a long word is atomic */
          #define READ_LONG_IS_ATOMIC
          
          typedef uint32_t TimeStamp;
          
          static inline TimeStamp
          nowSeconds(  void )
          {
           rtems_interval rval;
           rtems_clock_get_seconds_since_epoch(   &rval  );
           return rval;
          }
          
          
          /* Per mounted FS structure */
          typedef struct NfsRec_ {
           /* the NFS server we're talking to.
           */
           RpcUdpServer server;
           /* statistics; how many NfsNodes are
           * currently alive.
           */
           volatile int nodesInUse;
          #if DEBUG & DEBUG_COUNT_NODES
           /* statistics; how many 'NfsNode.str'
           * strings are currently allocated.
           */
           volatile int stringsInUse;
          #endif
           /* A small number who uniquely
           * identifies a mounted NFS within
           * this driver (  i.e. this NfsRec ).
           * Each time a NFS is mounted,   the
           * global ID counter is incremented
           * and its value is assigned to the
           * newly created NfsRec.
           */
           u_short id;
           /* Our RTEMS filesystem mt_entry
           */
           rtems_filesystem_mount_table_entry_t *mt_entry;
           /* Next NfsRec on a linked list who
           * is anchored at nfsGlob
           */
           struct NfsRec_ *next;
           /* Who we pretend we are
           */
           u_long uid,  gid;
          } NfsRec,   *Nfs;
          
          typedef struct NfsNodeRec_ {
           /* This holds this node's attributes
           * (  stats ) and its nfs filehandle.
           * It also contains room for nfs rpc
           * arguments.
           */
           serporid serporid;
           /* The arguments we used when doing
           * the 'lookup' call for this node.
           * We need this information (  especially
           * the directory FH ) for performing
           * certain operations on this
           * node (  in particular: for unlinking
           * it from a parent directory )
           */
           diropargs args;
           /* FS this node belongs to
           */
           Nfs nfs;
           /* A buffer for the string the
           * args.name points to.
           * We need this because args.name might
           * temporarily point to strings on the
           * stack. Duplicates are allocated from
     551   * the heap and attached to 'str' so
           * they can be released as appropriate.
           */
           char *str;
           /* A timestamp for the stats
           */
     557   TimeStamp age;
          } NfsNodeRec,   *NfsNode;
          
          /*****************************************
           Forward Declarations
           *****************************************/
          
          static int nfs_readlink(  
           rtems_filesystem_location_info_t *loc,   /* IN */
           char *buf,   /* OUT */
           size_t len
           );
          
          static int updateAttr(  NfsNode node,   int force );
          
          /* Mask bits when setting attributes.
           * Only the 'arg' fields with their
           * corresponding bit set in the mask
           * will be used. The others are left
           * unchanged.
           * The 'TOUCH' bits instruct nfs_sattr(   )
           * to update the respective time
     579   * fields to the current time
           */
          #define SATTR_MODE (  1<<0 )
          #define SATTR_UID (  1<<1 )
          #define SATTR_GID (  1<<2 )
          #define SATTR_SIZE (  1<<3 )
          #define SATTR_ATIME (  1<<4 )
          #define SATTR_TOUCHA (  1<<5 )
          #define SATTR_MTIME (  1<<6 )
     588  #define SATTR_TOUCHM (  1<<7 )
          #define SATTR_TOUCH (  SATTR_TOUCHM | SATTR_TOUCHA )
          
     591  static int
          nfs_sattr(  NfsNode node,   sattr *arg,   u_long mask );
          
          extern struct _rtems_filesystem_operations_table nfs_fs_ops;
          static struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers;
          static struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers;
          static struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers;
          static rtems_driver_address_table drvNfs;
          
          int
          nfsMountsShow(  FILE* );
          
          rtems_status_code
          rtems_filesystem_resolve_location(  char *buf,   int len,   rtems_filesystem_location_info_t *loc );
     605  
          
          /*****************************************
           Inline Routines
           *****************************************/
          
          
          /* * * * * * * * * * * * * * * * * *
           Trivial Operations on a NfsNode
           * * * * * * * * * * * * * * * * * */
          
     616  /* determine if a location 'l' is an NFS root node */
          static inline int
          locIsRoot(  rtems_filesystem_location_info_t *l )
          {
          NfsNode me = (  NfsNode ) l->node_access;
          NfsNode r;
           r = (  NfsNode )l->mt_entry->mt_fs_root.node_access;
           return SERP_ATTR(  r ).fileid == SERP_ATTR(  me ).fileid &&
           SERP_ATTR(  r ).fsid == SERP_ATTR(  me ).fsid;
          }
          
     627  /* determine if a location 'l' is an NFS node */
          static inline int
          locIsNfs(  rtems_filesystem_location_info_t *l )
          {
           return l->ops == &nfs_fs_ops;
          }
          
          /* determine if two locations refer to the
           * same entity. We know that 'nfsloc' is a
           * location inside nfs. However,   we needn't
           * know anything about 'anyloc'.
           */
          static inline int
          locAreEqual(  
           rtems_filesystem_location_info_t *nfsloc,  
           rtems_filesystem_location_info_t *anyloc
           )
          {
          NfsNode na = (  NfsNode ) nfsloc->node_access;
          NfsNode nb;
          
           if (  !locIsNfs(  anyloc ) )
           return 0;
          
           nb = (  NfsNode ) anyloc->node_access;
          
           if (  na->nfs != nb->nfs )
           return 0;
          
           updateAttr(  nb,   0 );
          
           return SERP_ATTR(  na ).fileid == SERP_ATTR(  nb ).fileid &&
           SERP_ATTR(  na ).fsid == SERP_ATTR(  nb ).fsid;
          }
          
          
          
          /*****************************************
           Global Variables
           *****************************************/
          
          /* These are (  except for MAXNAMLEN/MAXPATHLEN ) copied from IMFS */
          
          static rtems_filesystem_limits_and_options_t
          nfs_limits_and_options = {
           5,   /* link_max */
           6,   /* max_canon */
           7,   /* max_input */
           NFS_MAXNAMLEN,   /* name_max */
           NFS_MAXPATHLEN,   /* path_max */
           2,   /* pipe_buf */
           1,   /* posix_async_io */
           2,   /* posix_chown_restrictions */
           3,   /* posix_no_trunc */
           4,   /* posix_prio_io */
           5,   /* posix_sync_io */
           6 /* posix_vdisable */
          };
          
          /* size of an encoded 'entry' object */
          static int dirres_entry_size;
          
          /* Global stuff and statistics */
          static struct nfsstats {
           /* A lock for protecting the
           * linked ist of mounted NFS
           * and the num_mounted_fs field
           */
           rtems_id llock;
           /* A lock for protecting misc
           * stuff within the driver.
           * The lock must only be held
           * for short periods of time.
           */
           rtems_id lock;
           /* Our major number as assigned
           * by RTEMS
           */
           rtems_device_major_number nfs_major;
           /* The number of currently
           * mounted NFS
           */
           int num_mounted_fs;
           /* A list of the currently
           * mounted NFS
           */
           struct NfsRec_ *mounted_fs;
           /* A counter for allocating
           * unique IDs to each mounted
           * NFS.
           * Assume we are not going to
           * do more than 16k mounts
           * during the system lifetime
           */
           u_short fs_ids;
          } nfsGlob = {0,   0,   0,   0,   0,   0};
          
          /*
           * Global variable to tune the 'st_blksize' (  stat(  2 ) ) value this nfs
           * client should report.
           * size on the server.
           */
          #ifndef DEFAULT_NFS_ST_BLKSIZE
          #define DEFAULT_NFS_ST_BLKSIZE NFS_MAXDATA
          #endif
          int nfsStBlksize = DEFAULT_NFS_ST_BLKSIZE;
          
          /* Two pools of RPC transactions;
           * One with small send buffers
           * the other with a big one.
           * The actual size of the small
           * buffer is configurable (  see top ).
           *
           * Note: The RX buffers are always
           * big
           */
          static RpcUdpXactPool smallPool = 0;
          static RpcUdpXactPool bigPool = 0;
          
          
          /*****************************************
           Implementation
           *****************************************/
          
          /* Create a Nfs object. This is
           * per-mounted NFS information.
           *
           * ARGS: The Nfs server handle.
           *
           * RETURNS: Nfs on success,  
           * NULL on failure with
           * errno set
           *
           * NOTE: The submitted server
           * object is 'owned' by
           * this Nfs and will be
           * destroyed by nfsDestroy(   )
           */
          static Nfs
          nfsCreate(  RpcUdpServer server )
          {
          Nfs rval = calloc(  1,  sizeof(  *rval ) );
          
           if (  rval ) {
           rval->server = server;
           LOCK(  nfsGlob.llock );
           rval->next = nfsGlob.mounted_fs;
           nfsGlob.mounted_fs = rval;
           UNLOCK(  nfsGlob.llock );
           } else {
           errno = ENOMEM;
           }
           return rval;
          }
          
          /* Destroy an Nfs object and
           * its associated server
           */
          static void
          nfsDestroy(  Nfs nfs )
          {
          register Nfs prev;
           if (  !nfs )
           return;
          
           LOCK(  nfsGlob.llock );
           if (  nfs == nfsGlob.mounted_fs )
           nfsGlob.mounted_fs = nfs->next;
           else {
           for (  prev = nfsGlob.mounted_fs;
           prev && prev->next != nfs;
           prev = prev->next )
           /* nothing else to do */;
           assert(   prev  );
           prev->next = nfs->next;
           }
           UNLOCK(  nfsGlob.llock );
          
           nfs->next = 0; /* paranoia */
           rpcUdpServerDestroy(  nfs->server );
           free(  nfs );
          }
          
          /*
           * Create a Node. The node will
           * be associated with a particular
           * mounted NFS identified by 'nfs'
           * Optionally,   a NFS file handle
           * may be copied into this node.
           *
           * ARGS: nfs of the NFS this node
           * belongs to.
           * NFS file handle identifying
           * this node.
           * RETURNS: node on success,  
           * NULL on failure with errno
           * set.
           *
           * NOTE: The caller of this routine
           * is responsible for copying
           * a NFS file handle if she
           * choses to pass a NULL fh.
           *
           * The driver code assumes the
           * a node always has a valid
           * NFS filehandle and file
           * attributes (  unless the latter
           * are aged ).
           */
          static NfsNode
          nfsNodeCreate(  Nfs nfs,   fhandle *fh )
          {
          NfsNode rval = malloc(  sizeof(  *rval ) );
          unsigned long flags;
          
          #if DEBUG & DEBUG_TRACK_NODES
           fprintf(  stderr,  "NFS: creating a node\n" );
          #endif
          
           if (  rval ) {
           if (  fh )
           memcpy(   &SERP_FILE(  rval ),   fh,   sizeof(  *fh )  );
           rtems_interrupt_disable(  flags );
           nfs->nodesInUse++;
           rtems_interrupt_enable(  flags );
           rval->nfs = nfs;
           rval->str = 0;
           } else {
           errno = ENOMEM;
           }
          
           return rval;
          }
          
          /* destroy a node */
          static void
          nfsNodeDestroy(  NfsNode node )
          {
          unsigned long flags;
          
          #if DEBUG & DEBUG_TRACK_NODES
           fprintf(  stderr,  "NFS: destroying a node\n" );
          #endif
          #if 0
           if (  !node )
           return;
           /* this probably does nothing... */
           xdr_free(  xdr_serporid,   &node->serporid );
          #endif
          
           rtems_interrupt_disable(  flags );
           node->nfs->nodesInUse--;
          #if DEBUG & DEBUG_COUNT_NODES
           if (  node->str )
           node->nfs->stringsInUse--;
          #endif
           rtems_interrupt_enable(  flags );
          
           if (  node->str )
           free(  node->str );
          
           free(  node );
          }
          
          /* Clone a given node (  AKA copy constructor ),  
           * i.e. create an exact copy.
           *
           * ARGS: node to clone
           * RETURNS: new node on success
           * NULL on failure with errno set.
           *
           * NOTE: a string attached to 'str'
           * is cloned as well. Outdated
           * attributes (  of the new copy
           * only ) will be refreshed
           * (  if unsuccessful,   this could
           * be a reason for failure to
           * clone a node ).
           */
          static NfsNode
          nfsNodeClone(  NfsNode node )
          {
          NfsNode rval = nfsNodeCreate(  node->nfs,   0 );
          
           if (  rval ) {
           *rval = *node;
          
           /* must clone the string also */
           if (  node->str ) {
           rval->args.name = rval->str = strdup(  node->str );
           if (  !rval->str ) {
           errno = ENOMEM;
           nfsNodeDestroy(  rval );
           return 0;
           }
          #if DEBUG & DEBUG_COUNT_NODES
           { unsigned long flags;
           rtems_interrupt_disable(  flags );
           node->nfs->stringsInUse++;
           rtems_interrupt_enable(  flags );
           }
          #endif
           }
          
           /* possibly update the stats */
           if (  updateAttr(  rval,   0 /* only if necessary */ ) ) {
           nfsNodeDestroy(  rval );
           return 0;
           }
           }
           return rval;
          }
          
          /* Initialize the driver.
           *
           * ARGS: depth of the small and big
           * transaction pools,   i.e. how
           * many transactions (  buffers )
           * should always be kept around.
           *
           * (  If more transactions are needed,  
           * they are created and destroyed
           * on the fly ).
           */
          void
          nfsInit(  int smallPoolDepth,   int bigPoolDepth )
          {
          static int initialised = 0;
          entry dummy;
          rtems_status_code status;
          
           if (  initialised )
           return;
          
           initialised = 1;
          
           fprintf(  stderr,  
           "RTEMS-NFS $Release$,   " \
           "Till Straumann,   Stanford/SLAC/SSRL 2002,   " \
           "See LICENSE file for licensing info.\n" );
          
           /* Get a major number */
          
           if (  RTEMS_SUCCESSFUL != rtems_io_register_driver(  0,   &drvNfs,   &nfsGlob.nfs_major ) ) {
           fprintf(  stderr,  "Registering NFS driver failed - %s\n",   strerror(  errno ) );
           return;
           }
          
           if (  0==smallPoolDepth )
           smallPoolDepth = 20;
           if (  0==bigPoolDepth )
           bigPoolDepth = 10;
          
           /* it's crucial to zero out the 'next' pointer
           * because it terminates the xdr_entry recursion
           *
           * we also must make the filename some non-zero
           * char pointer!
           */
          
           memset(  &dummy,   0,   sizeof(  dummy ) );
          
           dummy.nextentry = 0;
           dummy.name = "somename"; /* guess average length of a filename */
           dirres_entry_size = xdr_sizeof(  (  xdrproc_t )xdr_entry,   &dummy );
          
           smallPool = rpcUdpXactPoolCreate(  
           NFS_PROGRAM,  
           NFS_VERSION_2,  
           CONFIG_NFS_SMALL_XACT_SIZE,  
           smallPoolDepth );
           assert(   smallPool  );
          
           bigPool = rpcUdpXactPoolCreate(  
           NFS_PROGRAM,  
           NFS_VERSION_2,  
           CONFIG_NFS_BIG_XACT_SIZE,  
           bigPoolDepth );
           assert(   bigPool  );
          
           status = rtems_semaphore_create(  
           rtems_build_name(  'N',  'F',  'S',  'l' ),  
           1,  
           MUTEX_ATTRIBUTES,  
           0,  
           &nfsGlob.llock );
           assert(   status == RTEMS_SUCCESSFUL  );
           status = rtems_semaphore_create(  
           rtems_build_name(  'N',  'F',  'S',  'm' ),  
           1,  
           MUTEX_ATTRIBUTES,  
           0,  
           &nfsGlob.lock );
           assert(   status == RTEMS_SUCCESSFUL  );
          
           if (  sizeof(  ino_t ) < sizeof(  u_int ) ) {
           fprintf(  stderr,  
           "WARNING: Using 'short st_ino' hits performance and may fail to access/find correct files\n" );
           fprintf(  stderr,  
           "you should fix newlib's sys/stat.h - for now I'll enable a hack...\n" );
          
           }
          }
          
          /* Driver cleanup code
           */
          int
          nfsCleanup(  void )
          {
          rtems_id l;
          int refuse;
          
           if (  !nfsGlob.llock ) {
           /* registering the driver failed - let them still cleanup */
           return 0;
           }
          
           LOCK(  nfsGlob.llock );
           if (   (  refuse = nfsGlob.num_mounted_fs )  ) {
           fprintf(  stderr,  "Refuse to unload NFS; %i filesystems still mounted.\n",  
           refuse );
           nfsMountsShow(  stderr );
           /* yes,   printing is slow - but since you try to unload the driver,  
           * you assume nobody is using NFS,   so what if they have to wait?
           */
           UNLOCK(  nfsGlob.llock );
           return -1;
           }
          
           rtems_semaphore_delete(  nfsGlob.lock );
           nfsGlob.lock = 0;
          
           /* hold the lock while cleaning up... */
          
           rpcUdpXactPoolDestroy(  smallPool );
           rpcUdpXactPoolDestroy(  bigPool );
           l = nfsGlob.llock;
           rtems_io_unregister_driver(  nfsGlob.nfs_major );
          
           rtems_semaphore_delete(  l );
           nfsGlob.llock = 0;
           return 0;
          }
          
          /* NFS RPC wrapper.
           *
           * ARGS: srvr the NFS server we want to call
           * proc the NFSPROC_xx we want to invoke
           * xargs xdr routine to wrap the arguments
           * pargs pointer to the argument object
           * xres xdr routine to unwrap the results
           * pres pointer to the result object
           *
           * RETURNS: 0 on success,   -1 on error with errno set.
           *
           * NOTE: the caller assumes that errno is set to
           * a nonzero value if this routine returns
           * an error (  nonzero return value ).
           *
           * This routine prints RPC error messages to
           * stderr.
           */
          STATIC int
          nfscall(  
           RpcUdpServer srvr,  
           int proc,  
           xdrproc_t xargs,  
           void * pargs,  
           xdrproc_t xres,  
           void * pres )
          {
          RpcUdpXact xact;
          enum clnt_stat stat;
          RpcUdpXactPool pool;
          int rval = -1;
          
          
           switch (  proc ) {
           case NFSPROC_SYMLINK:
           case NFSPROC_WRITE:
           pool = bigPool; break;
           default: pool = smallPool; break;
           }
          
           xact = rpcUdpXactPoolGet(  pool,   XactGetCreate );
          
           if (   !xact  ) {
           errno = ENOMEM;
           return -1;
           }
          
           if (   RPC_SUCCESS != (  stat=rpcUdpSend(  
           xact,  
           srvr,  
           NFSCALL_TIMEOUT,  
           proc,  
           xres,  
           pres,  
           xargs,  
           pargs,  
           0 ) ) ||
           RPC_SUCCESS != (  stat=rpcUdpRcv(  xact ) )  ) {
          
           fprintf(  stderr,  
           "NFS (  proc %i ) - %s\n",  
           proc,  
           clnt_sperrno(  stat ) );
          
           switch (  stat ) {
           /* TODO: this is probably not complete and/or fully accurate */
           case RPC_CANTENCODEARGS : errno = EINVAL; break;
           case RPC_AUTHERROR : errno = EPERM; break;
          
           case RPC_CANTSEND :
           case RPC_CANTRECV : /* hope they have errno set */
           case RPC_SYSTEMERROR : break;
          
           default : errno = EIO; break;
           }
           } else {
           rval = 0;
           }
          
           /* release the transaction back into the pool */
           rpcUdpXactPoolPut(  xact );
          
           if (  rval && !errno )
           errno = EIO;
          
           return rval;
          }
          
          /* Check the 'age' of a node's stats
           * and read the attributes from the server
           * if necessary.
           *
           * ARGS: node node to update
           * force enforce updating ignoring
           * the timestamp/age
           *
           * RETURNS: 0 on success,  
           * -1 on failure with errno set
           */
          
          static int
          updateAttr(  NfsNode node,   int force )
          {
          
           if (  force
          #ifdef CONFIG_ATTR_LIFETIME
           || (  nowSeconds(   ) - node->age > CONFIG_ATTR_LIFETIME )
          #endif
            ) {
           if (   nfscall(  node->nfs->server,  
           NFSPROC_GETATTR,  
           (  xdrproc_t )xdr_nfs_fh,   &SERP_FILE(  node ),  
           (  xdrproc_t )xdr_attrstat,   &node->serporid )  )
           return -1;
          
           if (   NFS_OK != node->serporid.status  ) {
           errno = node->serporid.status;
           return -1;
           }
          
           node->age = nowSeconds(   );
           }
          
           return 0;
          }
          
          /*
           * IP address helper.
           *
           * initialize a sockaddr_in from a
           * [<uid>'.'<gid>'@']<host>':'<path>" string and let
           * pPath point to the <path> part; retrieve the optional
           * uid/gids
           *
           * ARGS: see description above
           *
           * RETURNS: 0 on success,  
           * -1 on failure with errno set
           */
          static int
          buildIpAddr(  u_long *puid,   u_long *pgid,  
           char **pHost,   struct sockaddr_in *psa,  
           char **pPath )
          {
          struct hostent *h;
          char host[64];
          char *chpt = *pPath;
          char *path;
          int len;
          
           if (   !chpt  ) {
           errno = EINVAL;
           return -1;
           }
          
           /* look for the optional uid/gid */
           if (   (  chpt = strchr(  chpt,   UIDSEP ) )  ) {
           if (   2 != sscanf(  *pPath,  "%li.%li",  puid,  pgid )  ) {
           errno = EINVAL;
           return -1;
           }
           chpt++;
           } else {
           *puid = RPCIOD_DEFAULT_ID;
           *pgid = RPCIOD_DEFAULT_ID;
           chpt = *pPath;
           }
           if (   pHost  )
           *pHost = chpt;
          
           /* split the device name which is in the form
           *
           * <host> ':' <path>
           *
           * into its components using a local buffer
           */
          
           if (   !(  path = strchr(  chpt,   HOSTDELIM ) ) ||
           (  len = path - chpt ) >= sizeof(  host ) - 1  ) {
           errno = EINVAL;
           return -1;
           }
           /* point to path beyond ':' */
           path++;
          
           strncpy(  host,   chpt,   len );
           host[len]=0;
          
           /* BEGIN OF NON-THREAD SAFE REGION */
          
           h = gethostbyname(  host );
          
           if (   !h  ) {
           errno = EINVAL;
           return -1;
           }
          
           memcpy(  &psa->sin_addr,   h->h_addr,   sizeof (  struct in_addr ) );
          
           /* END OF NON-THREAD SAFE REGION */
          
           psa->sin_family = AF_INET;
           psa->sin_port = 0;
           *pPath = path;
           return 0;
          }
          
          /* wrapper similar to nfscall.
           * However,   since it is not used
           * very often,   the simpler and less
           * efficient rpcUdpCallRp API is used.
           *
           * ARGS: see 'nfscall(   )' above
           *
           * RETURNS: RPC status
           */
          static enum clnt_stat
          mntcall(  
           struct sockaddr_in *psrvr,  
           int proc,  
           xdrproc_t xargs,  
           void * pargs,  
           xdrproc_t xres,  
           void * pres,  
           u_long uid,  
           u_long gid )
          {
          #ifdef MOUNT_V1_PORT
          int retry;
          #endif
          enum clnt_stat stat = RPC_FAILED;
          
          #ifdef MOUNT_V1_PORT
           /* if the portmapper fails,   retry a fixed port */
           for (  retry = 1,   psrvr->sin_port = 0,   stat = RPC_FAILED;
           retry >= 0 && stat;
           stat && (  psrvr->sin_port = htons(  MOUNT_V1_PORT ) ),   retry--  )
          #endif
           stat = rpcUdpCallRp(  
           psrvr,  
           MOUNTPROG,  
           MOUNTVERS,  
           proc,  
           xargs,  
           pargs,  
           xres,  
           pres,  
           uid,  
           gid,  
           MNTCALL_TIMEOUT
            );
           return stat;
          }
          
          /*****************************************
           RTEMS File System Operations for NFS
           *****************************************/
          
          #if 0 /* for reference */
          
          struct rtems_filesystem_location_info_tt
          {
           void *node_access;
           rtems_filesystem_file_handlers_r *handlers;
           rtems_filesystem_operations_table *ops;
           rtems_filesystem_mount_table_entry_t *mt_entry;
          };
          
          #endif
          
          /*
           * Evaluate a path letting 'pathloc' travel along.
           *
           * The important semantics of this operation are:
           *
           * If this routine returns -1,   the caller assumes
           * pathloc to be _invalid_ and hence it will not
           * invoke rtems_filesystem_freenode(   ) on it.
           *
           * OTOH,   if evalpath returns 0,  
           * rtems_filesystem_freenode(   ) will eventually be
           * called which results in our freeing the associated
           * NfsNode attached to node_access.
           *
           * Therefore,   this routine will _always_ allocate
           * a NfsNode and pass it out to *pathloc (  provided
           * that the evaluation succeeds ).
           *
           * However,   if the evaluation finds that it has to
           * step across FS boundaries (  mount point or a symlink
           * pointing outside ),   the NfsNode is destroyed
           * before passing control to the new FS' evalpath_h(   )
           *
           */
          
          union nfs_evalpath_arg {
           int i;
           const char **c;
           };
          
          STATIC int nfs_do_evalpath(  
           const char *pathname,   /* IN */
           int pathnamelen,   /* IN */
           union nfs_evalpath_arg *arg,  
           rtems_filesystem_location_info_t *pathloc,   /* IN/OUT */
           int forMake
           )
          {
          char *del = 0,   *part;
          int e = 0;
          NfsNode node = pathloc->node_access;
          char *p = malloc(  MAXPATHLEN+1 );
          Nfs nfs = (  Nfs )pathloc->mt_entry->fs_info;
          RpcUdpServer server = nfs->server;
          unsigned long flags;
          #if DEBUG & DEBUG_COUNT_NODES
          unsigned long niu,  siu;
          #endif
          
           if (   !p  ) {
           e = ENOMEM;
           goto cleanup;
           }
           memset(  p,   0,   MAXPATHLEN+1 );
           memcpy(  p,   pathname,   pathnamelen );
          
           LOCK(  nfsGlob.lock );
           node = nfsNodeClone(  node );
           UNLOCK(  nfsGlob.lock );
          
           /* from here on,   the NFS is protected from being unmounted
           * since the node refcount is > 1
           */
          
           /* clone the node */
           if (   !node  ) {
           /* nodeClone sets errno */
           pathloc->node_access = 0;
           if (   ! (  e = errno )  ) {
           /* if we have no node,   e must not be zero! */
           e = ENOMEM;
           }
           goto cleanup;
           }
          
           pathloc->node_access = node;
          
           /* Special case: the RTEMS filesystem code
           * may emit '..' on a regular file node to
           * find the parent directory :-(  .
           * (  eval.c: rtems_filesystem_evaluate_parent(   ) )
           * Try to catch this case here:
           */
           if (   NFDIR != SERP_ATTR(  node ).type && '.'==*p && '.'==*(  p+1 )  ) {
           for (   part = p+2; '/'==*part; part++  )
           /* skip trailing '/' */;
           if (   !*part  ) {
           /* this is it; back out dir and let them look up the dir itself... */
           memcpy(   &SERP_FILE(  node ),  
           &node->args.dir,  
           sizeof(  node->args.dir ) );
           *(  p+1 )=0;
           }
           }
          
           for (  part=p; part && *part; part=del ) {
          
           if (   NFLNK == SERP_ATTR(  node ).type  ) {
           /* follow midpath link */
           char *b = malloc(  NFS_MAXPATHLEN+1 );
           int l;
          
           if (  !b ) {
           e = ENOMEM;
           goto cleanup;
           }
           if (  nfs_readlink(  pathloc,   b,   NFS_MAXPATHLEN+1 ) ) {
           free(  b );
           e = errno;
           goto cleanup;
           }
          
           /* prepend the link value to the rest of the path */
           if (   (  l=strlen(  b ) ) + strlen(  part ) + 1 > NFS_MAXPATHLEN  ) {
           free(  b );
           e = EINVAL;
           goto cleanup;
           }
           /* swap string buffers and reset delimiter */
           b[l++] = DELIM;
           strcpy(  b+l,  part );
           part = b;
           b = p;
           p = del = part;
          
           free(  b );
          
           /* back up the directory filehandle (  only necessary
           * if we don't back out to the root
           */
           if (  ! (  DELIM == *part )  ) {
           memcpy(   &SERP_FILE(  node ),  
           &node->args.dir,  
           sizeof(  node->args.dir ) );
          
           if (  updateAttr(  node,   1 /* force */ ) ) {
           e = errno;
           goto cleanup;
           }
           }
           }
          
           /* find delimiter and eat /// sequences
           * (  only if we don't restart at the root )
           */
           if (   DELIM != *part && (  del = strchr(  part,   DELIM ) ) ) {
           do {
           *del++=0;
           } while (  DELIM==*del );
           }
          
           /* refuse to backup over the root */
           if (   0==strcmp(  part,  UPDIR )
           && locAreEqual(  pathloc,   &rtems_filesystem_root )  ) {
           part++;
           }
          
           /* cross mountpoint upwards */
           if (   (  0==strcmp(  part,  UPDIR ) && locIsRoot(  pathloc ) ) /* cross mountpoint up */
           || DELIM == *part /* link starts at root */
            ) {
           int rval;
          
          #if DEBUG & DEBUG_EVALPATH
           fprintf(  stderr,  
           "Crossing mountpoint upwards\n" );
          #endif
          
           if (  DELIM == *part ) {
           *pathloc = rtems_filesystem_root;
           } else {
           *pathloc = pathloc->mt_entry->mt_point_node;
           /* re-append the rest of the path */
           if (  del )
           while (   0 == *--del  )
           *del = DELIM;
           }
          
           nfsNodeDestroy(  node );
          
          #if DEBUG & DEBUG_EVALPATH
           fprintf(  stderr,  
           "Re-evaluating '%s'\n",  
           part );
          #endif
          
           if (  forMake )
           rval = pathloc->ops->evalformake_h(  part,   pathloc,   arg->c );
           else
           rval = pathloc->ops->evalpath_h(  part,   strlen(  part ),   arg->i,   pathloc );
          
           free(  p );
           return rval;
           }
          
           /* lookup one element */
           SERP_ARGS(  node ).diroparg.name = part;
          
           /* remember args / directory fh */
           memcpy(   &node->args,   &SERP_FILE(  node ),   sizeof(  node->args ) );
          
           /* don't lookup the item we want to create */
           if (   forMake && (  !del || !*del )  )
           break;
          
          #if DEBUG & DEBUG_EVALPATH
           fprintf(  stderr,  "Looking up '%s'\n",  part );
          #endif
          
           if (   nfscall(  server,  
           NFSPROC_LOOKUP,  
           (  xdrproc_t )xdr_diropargs,   &SERP_FILE(  node ),  
           (  xdrproc_t )xdr_serporid,   &node->serporid ) ||
           NFS_OK != (  errno=node->serporid.status )  ) {
           e = errno;
           goto cleanup;
           }
           node->age = nowSeconds(   );
          
          #if DEBUG & DEBUG_EVALPATH
           if (  NFLNK == SERP_ATTR(  node ).type && del ) {
           fprintf(  stderr,  
           "Following midpath link '%s'\n",  
           part );
           }
          #endif
          
           }
          
           if (  forMake ) {
           /* remember the name - do this _before_ copying
           * the name to local storage; the caller expects a
           * pointer into pathloc
           */
           assert(   node->args.name  );
          
           *(  const char** )arg = pathname + (  node->args.name - p );
          
          #if 0
           /* restore the directory node */
          
           memcpy(   &SERP_FILE(  node ),  
           &node->args.dir,  
           sizeof(  node->args.dir ) );
          
           if (   (  nfscall(  nfs->server,  
           NFSPROC_GETATTR,  
           (  xdrproc_t )xdr_nfs_fh,   &SERP_FILE(  node ),  
           (  xdrproc_t )xdr_attrstat,   &node->serporid ) && !errno && (  errno = EIO ) ) ||
           (  NFS_OK != (  errno=node->serporid.status )  )  ) {
           goto cleanup;
           }
          #endif
           }
          
           if (  locIsRoot(  pathloc ) ) {
          
           /* stupid filesystem code has no 'op' for comparing nodes
           * but just compares the 'node_access' pointers.
           * Luckily,   this is only done for comparing the root nodes.
           * Hence,   we never give them a copy of the root but always
           * the root itself.
           */
           pathloc->node_access = pathloc->mt_entry->mt_fs_root.node_access;
           /* increment the 'in use' counter since we return one more
           * reference to the root node
           */
           rtems_interrupt_disable(  flags );
           nfs->nodesInUse++;
           rtems_interrupt_enable(  flags );
           nfsNodeDestroy(  node );
          
          
           } else {
           switch (  SERP_ATTR(  node ).type ) {
           case NFDIR: pathloc->handlers = &nfs_dir_file_handlers; break;
           case NFREG: pathloc->handlers = &nfs_file_file_handlers; break;
           case NFLNK: pathloc->handlers = &nfs_link_file_handlers; break;
           default: pathloc->handlers = &rtems_filesystem_handlers_default; break;
           }
           pathloc->node_access = node;
          
           /* remember the name of this directory entry */
          
           if (  node->args.name ) {
           if (  node->str ) {
          #if DEBUG & DEBUG_COUNT_NODES
           rtems_interrupt_disable(  flags );
           nfs->stringsInUse--;
           rtems_interrupt_enable(  flags );
          #endif
           free(  node->str );
           }
           node->args.name = node->str = strdup(  node->args.name );
           if (  !node->str ) {
           e = ENOMEM;
           goto cleanup;
           }
          
          #if DEBUG & DEBUG_COUNT_NODES
           rtems_interrupt_disable(  flags );
           nfs->stringsInUse++;
           rtems_interrupt_enable(  flags );
          #endif
           }
          
           }
           node = 0;
          
           e = 0;
          
          cleanup:
           free(  p );
          #if DEBUG & DEBUG_COUNT_NODES
           /* cache counters; nfs may be unmounted by other thread after the last
           * node is destroyed
           */
           niu = nfs->nodesInUse;
           siu = nfs->stringsInUse;
          #endif
           if (  node ) {
           nfsNodeDestroy(  node );
           pathloc->node_access = 0;
           }
          #if DEBUG & DEBUG_COUNT_NODES
           fprintf(  stderr,  
           "leaving evalpath,   in use count is %i nodes,   %i strings\n",  
           niu,  siu );
          #endif
           if (  e ) {
          #if DEBUG & DEBUG_EVALPATH
           perror(  "Evalpath" );
          #endif
           rtems_set_errno_and_return_minus_one(  e );
           } else {
           return 0;
           }
          }
          
          /* MANDATORY; may set errno=ENOSYS and return -1 */
          static int nfs_evalformake(  
           const char *path,   /* IN */
           rtems_filesystem_location_info_t *pathloc,   /* IN/OUT */
           const char **pname /* OUT */
           )
          {
           union nfs_evalpath_arg args;
           args.c = pname;
          
           return nfs_do_evalpath(  path,   strlen(  path ),   &args,   pathloc,   1 /*forMake*/ );
          }
          
          static int nfs_evalpath(  
           const char *path,   /* IN */
           size_t pathlen,   /* IN */
           int flags,   /* IN */
           rtems_filesystem_location_info_t *pathloc /* IN/OUT */
           )
          {
           union nfs_evalpath_arg args;
           args.i = flags;
           return nfs_do_evalpath(  path,   pathlen,   &args,   pathloc,   0 /*not forMake*/ );
          }
          
          
          /* create a hard link */
          
          static int nfs_link(  
           rtems_filesystem_location_info_t *to_loc,   /* IN */
           rtems_filesystem_location_info_t *parent_loc,   /* IN */
           const char *name /* IN */
           )
          {
          NfsNode pNode;
          nfsstat status;
          NfsNode tNode = to_loc->node_access;
          
          #if DEBUG & DEBUG_SYSCALLS
           fprintf(  stderr,  "Creating link '%s'\n",  name );
          #endif
          
           if (   !locIsNfs(  parent_loc )  ) {
           errno = EXDEV;
           return -1;
           }
          
           pNode = parent_loc->node_access;
           if (   tNode->nfs != pNode->nfs  ) {
           errno = EXDEV;
           return -1;
           }
           memcpy(  &SERP_ARGS(  tNode ).linkarg.to.dir,  
           &SERP_FILE(  pNode ),  
           sizeof(  SERP_FILE(  pNode ) ) );
          
           SERP_ARGS(  tNode ).linkarg.to.name = (  filename )name;
          
           if (   nfscall(  tNode->nfs->server,  
           NFSPROC_LINK,  
           (  xdrproc_t )xdr_linkargs,   &SERP_FILE(  tNode ),  
           (  xdrproc_t )xdr_nfsstat,   &status )
           || (  NFS_OK != (  errno = status ) )
            ) {
          #if DEBUG & DEBUG_SYSCALLS
           perror(  "nfs_link" );
          #endif
           return -1;
           }
          
           return 0;
          
          }
          
          static int nfs_do_unlink(  
           rtems_filesystem_location_info_t *parent_loc,  /* IN */
           rtems_filesystem_location_info_t *loc,   /* IN */
           int proc
           )
          {
          nfsstat status;
          NfsNode node = loc->node_access;
          Nfs nfs = node->nfs;
          #if DEBUG & DEBUG_SYSCALLS
          char *name = NFSPROC_REMOVE == proc ?
           "nfs_unlink" : "nfs_rmdir";
          #endif
          
           /* The FS generics have determined that pathloc is _not_
           * a directory. Hence we may assume that the parent
           * is in our NFS.
           */
          
          #if DEBUG & DEBUG_SYSCALLS
           assert(   node->args.name == node->str && node->str  );
          
           fprintf(  stderr,  "%s '%s'\n",   name,   node->args.name );
          #endif
          
           if (   nfscall(  nfs->server,  
           proc,  
           (  xdrproc_t )xdr_diropargs,   &node->args,  
           (  xdrproc_t )xdr_nfsstat,   &status )
           || (  NFS_OK != (  errno = status ) )
            ) {
          #if DEBUG & DEBUG_SYSCALLS
           perror(  name );
          #endif
           return -1;
           }
          
           return 0;
          }
          
          static int nfs_unlink(  
           rtems_filesystem_location_info_t *parent_loc,   /* IN */
           rtems_filesystem_location_info_t *loc /* IN */
           )
          {
           return nfs_do_unlink(  parent_loc,   loc,   NFSPROC_REMOVE );
          }
          
          static int nfs_chown(  
           rtems_filesystem_location_info_t *pathloc,   /* IN */
           uid_t owner,   /* IN */
           gid_t group /* IN */
           )
          {
          sattr arg;
          
           arg.uid = owner;
           arg.gid = group;
          
           return nfs_sattr(  pathloc->node_access,   &arg,   SATTR_UID | SATTR_GID );
          
          }
          
          /* Cleanup the FS private info attached to pathloc->node_access */
          static int nfs_freenode(  
           rtems_filesystem_location_info_t *pathloc /* IN */
           )
          {
          Nfs nfs = (  (  NfsNode )pathloc->node_access )->nfs;
          
          #if DEBUG & DEBUG_COUNT_NODES
           /* print counts at entry where they are > 0 so 'nfs' is safe from being destroyed
           * and there's no race condition
           */
           fprintf(  stderr,  
           "entering freenode,   in use count is %i nodes,   %i strings\n",  
           nfs->nodesInUse,  
           nfs->stringsInUse );
          #endif
          
           /* never destroy the root node; it is released by the unmount
           * code
           */
           if (  locIsRoot(  pathloc ) ) {
           unsigned long flags;
           /* just adjust the references to the root node but
           * don't really release it
           */
           rtems_interrupt_disable(  flags );
           nfs->nodesInUse--;
           rtems_interrupt_enable(  flags );
           } else {
           nfsNodeDestroy(  pathloc->node_access );
           pathloc->node_access = 0;
           }
           return 0;
          }
          
          /* NOTE/TODO: mounting on top of NFS is not currently supported
           *
           * Challenge: stateless protocol. It would be possible to
           * delete mount points on the server. We would need some sort
           * of a 'garbage collector' looking for dead/unreachable
           * mount points and unmounting them.
           * Also,   the path evaluation routine would have to check
           * for crossing mount points. Crossing over from one NFS
           * into another NFS could probably handled iteratively
           * rather than by recursion.
           */
          
          int rtems_nfs_initialize(  
           rtems_filesystem_mount_table_entry_t *mt_entry,  
           const void *data
           )
          {
          char *host;
          struct sockaddr_in saddr;
          enum clnt_stat stat;
          fhstatus fhstat;
          u_long uid,  gid;
          #ifdef NFS_V2_PORT
          int retry;
          #endif
          Nfs nfs = 0;
          NfsNode rootNode = 0;
          RpcUdpServer nfsServer = 0;
          int e = -1;
          char *path = mt_entry->dev;
          
           if (  rpcUdpInit (   ) < 0 ) {
           fprintf (  stderr,   "error: initialising RPC\n" );
           return -1;
           }
          
           nfsInit(  0,   0 );
          
          #if 0
           printf(  "Trying to mount %s on %s\n",  path,  mntpoint );
          #endif
          
           if (   buildIpAddr(  &uid,   &gid,   &host,   &saddr,   &path )  )
           return -1;
          
          #ifdef NFS_V2_PORT
           /* if the portmapper fails,   retry a fixed port */
           for (  retry = 1,   saddr.sin_port = 0,   stat = RPC_FAILED;
           retry >= 0 && stat;
           stat && (  saddr.sin_port = htons(  NFS_V2_PORT ) ),   retry--  )
          #endif
           stat = rpcUdpServerCreate(  
           &saddr,  
           NFS_PROGRAM,  
           NFS_VERSION_2,  
           uid,  
           gid,  
           &nfsServer
            );
          
           if (   RPC_SUCCESS != stat  ) {
           fprintf(  stderr,  
           "Unable to contact NFS server - invalid port? (  %s )\n",  
           clnt_sperrno(  stat ) );
           e = EPROTONOSUPPORT;
           goto cleanup;
           }
          
          
           /* first,   try to ping the NFS server by
           * calling the NULL proc.
           */
           if (   nfscall(  nfsServer,  
           NFSPROC_NULL,  
           (  xdrproc_t )xdr_void,   0,  
           (  xdrproc_t )xdr_void,   0 )  ) {
          
           fputs(  "NFS Ping ",  stderr );
           fwrite(  host,   1,   path-host-1,   stderr );
           fprintf(  stderr,  " failed: %s\n",   strerror(  errno ) );
          
           e = errno ? errno : EIO;
           goto cleanup;
           }
          
           /* that seemed to work - we now try the
           * actual mount
           */
          
           /* reuse server address but let the mntcall(   )
           * search for the mountd's port
           */
           saddr.sin_port = 0;
          
           stat = mntcall(   &saddr,  
           MOUNTPROC_MNT,  
           (  xdrproc_t )xdr_dirpath,  
           &path,  
           (  xdrproc_t )xdr_fhstatus,  
           &fhstat,  
           uid,  
           gid  );
          
           if (  stat ) {
           fprintf(  stderr,  "MOUNT -- %s\n",  clnt_sperrno(  stat ) );
           if (   e<=0  )
           e = EIO;
           goto cleanup;
           } else if (  NFS_OK != (  e=fhstat.fhs_status ) ) {
           fprintf(  stderr,  "MOUNT: %s\n",  strerror(  e ) );
           goto cleanup;
           }
          
           nfs = nfsCreate(  nfsServer );
           assert(   nfs  );
           nfsServer = 0;
          
           nfs->uid = uid;
           nfs->gid = gid;
          
           /* that seemed to work - we now create the root node
           * and we also must obtain the root node attributes
           */
           rootNode = nfsNodeCreate(  nfs,   &fhstat.fhstatus_u.fhs_fhandle );
           assert(   rootNode  );
          
           if (   updateAttr(  rootNode,   1 /* force */ )  ) {
           e = errno;
           goto cleanup;
           }
          
           /* looks good so far */
          
           mt_entry->mt_fs_root.node_access = rootNode;
          
           rootNode = 0;
          
           mt_entry->mt_fs_root.ops = &nfs_fs_ops;
           mt_entry->mt_fs_root.handlers = &nfs_dir_file_handlers;
           mt_entry->pathconf_limits_and_options = nfs_limits_and_options;
          
           LOCK(  nfsGlob.llock );
           nfsGlob.num_mounted_fs++;
           /* allocate a new ID for this FS */
           nfs->id = nfsGlob.fs_ids++;
           UNLOCK(  nfsGlob.llock );
          
           mt_entry->fs_info = nfs;
           nfs->mt_entry = mt_entry;
           nfs = 0;
          
           e = 0;
          
          cleanup:
           if (  nfs )
           nfsDestroy(  nfs );
           if (  nfsServer )
           rpcUdpServerDestroy(  nfsServer );
           if (  rootNode )
           nfsNodeDestroy(  rootNode );
           if (  e )
           rtems_set_errno_and_return_minus_one(  e );
           else
           return 0;
          }
          
          /* This op is called when they try to unmount THIS fs */
          STATIC int nfs_fsunmount_me(  
           rtems_filesystem_mount_table_entry_t *mt_entry /* in */
           )
          {
          enum clnt_stat stat;
          struct sockaddr_in saddr;
          char *path = mt_entry->dev;
          int nodesInUse;
          u_long uid,  gid;
          int status;
          
          LOCK(  nfsGlob.llock );
           nodesInUse = (  (  Nfs )mt_entry->fs_info )->nodesInUse;
          
           if (  nodesInUse > 1 /* one ref to the root node used by us */ ) {
           UNLOCK(  nfsGlob.llock );
           fprintf(  stderr,  
           "Refuse to unmount; there are still %i nodes in use (  1 used by us )\n",  
           nodesInUse );
           rtems_set_errno_and_return_minus_one(  EBUSY );
           }
          
           status = buildIpAddr(  &uid,   &gid,   0,   &saddr,   &path );
           assert(   !status  );
          
           stat = mntcall(   &saddr,  
           MOUNTPROC_UMNT,  
           (  xdrproc_t )xdr_dirpath,   &path,  
           (  xdrproc_t )xdr_void,   0,  
           uid,  
           gid
            );
          
           if (  stat ) {
           UNLOCK(  nfsGlob.llock );
           fprintf(  stderr,  "NFS UMOUNT -- %s\n",   clnt_sperrno(  stat ) );
           errno = EIO;
           return -1;
           }
          
           nfsNodeDestroy(  mt_entry->mt_fs_root.node_access );
           mt_entry->mt_fs_root.node_access = 0;
          
           nfsDestroy(  mt_entry->fs_info );
           mt_entry->fs_info = 0;
          
           nfsGlob.num_mounted_fs--;
          UNLOCK(  nfsGlob.llock );
          
           return 0;
          }
          
          /* OPTIONAL; may be NULL - BUT: CAUTION; mount(   ) doesn't check
           * for this handler to be present - a fs bug
           * //NOTE: (  10/25/2002 ) patch submitted and probably applied
           */
          static rtems_filesystem_node_types_t nfs_node_type(  
           rtems_filesystem_location_info_t *pathloc /* in */
           )
          {
          NfsNode node = pathloc->node_access;
          
           if (  updateAttr(  node,   0 /* only if old */ ) )
           return -1;
          
           switch(   SERP_ATTR(  node ).type  ) {
           default:
           /* rtems has no value for 'unknown';
           */
           case NFNON:
           case NFSOCK:
           case NFBAD:
           case NFFIFO:
           break;
          
          
           case NFREG: return RTEMS_FILESYSTEM_MEMORY_FILE;
           case NFDIR: return RTEMS_FILESYSTEM_DIRECTORY;
          
           case NFBLK:
           case NFCHR: return RTEMS_FILESYSTEM_DEVICE;
          
           case NFLNK: return RTEMS_FILESYSTEM_SYM_LINK;
           }
           return -1;
          }
          
          static int nfs_mknod(  
           const char *path,   /* IN */
           mode_t mode,   /* IN */
           dev_t dev,   /* IN */
           rtems_filesystem_location_info_t *pathloc /* IN/OUT */
           )
          {
          
          struct timeval now;
          diropres res;
          NfsNode node = pathloc->node_access;
          mode_t type = S_IFMT & mode;
          
           if (  type != S_IFDIR && type != S_IFREG )
           rtems_set_errno_and_return_minus_one(  ENOTSUP );
          
          #if DEBUG & DEBUG_SYSCALLS
           fprintf(  stderr,  "nfs_mknod: creating %s\n",   path );
          #endif
          
           rtems_clock_get_tod_timeval(  &now );
          
           SERP_ARGS(  node ).createarg.name = (  filename )path;
           SERP_ARGS(  node ).createarg.attributes.mode = mode;
           /* TODO: either use our uid or use the Nfs credentials */
           SERP_ARGS(  node ).createarg.attributes.uid = 0;
           SERP_ARGS(  node ).createarg.attributes.gid = 0;
           SERP_ARGS(  node ).createarg.attributes.size = 0;
           SERP_ARGS(  node ).createarg.attributes.atime.seconds = now.tv_sec;
           SERP_ARGS(  node ).createarg.attributes.atime.useconds = now.tv_usec;
           SERP_ARGS(  node ).createarg.attributes.mtime.seconds = now.tv_sec;
           SERP_ARGS(  node ).createarg.attributes.mtime.useconds = now.tv_usec;
          
           if (   nfscall(   node->nfs->server,  
           NFSPROC_CREATE,  
           (  xdrproc_t )xdr_createargs,   &SERP_FILE(  node ),  
           (  xdrproc_t )xdr_diropres,   &res )
           || (  NFS_OK != (  errno = res.status ) )  ) {
          #if DEBUG & DEBUG_SYSCALLS
           perror(  "nfs_mknod" );
          #endif
           return -1;
           }
          
           return 0;
          }
          
          static int nfs_utime(  
           rtems_filesystem_location_info_t *pathloc,   /* IN */
           time_t actime,   /* IN */
           time_t modtime /* IN */
           )
          {
          sattr arg;
          
           /* TODO: add rtems EPOCH - UNIX EPOCH seconds */
           arg.atime.seconds = actime;
           arg.atime.useconds = 0;
           arg.mtime.seconds = modtime;
           arg.mtime.useconds = 0;
          
           return nfs_sattr(  pathloc->node_access,   &arg,   SATTR_ATIME | SATTR_MTIME );
          }
          
          static int nfs_symlink(  
           rtems_filesystem_location_info_t *loc,   /* IN */
           const char *link_name,   /* IN */
           const char *node_name
           )
          {
          struct timeval now;
          nfsstat status;
          NfsNode node = loc->node_access;
          
          
          #if DEBUG & DEBUG_SYSCALLS
           fprintf(  stderr,  "nfs_symlink: creating %s -> %s\n",   link_name,   node_name );
          #endif
          
           rtems_clock_get_tod_timeval(  &now );
          
           SERP_ARGS(  node ).symlinkarg.name = (  filename )link_name;
           SERP_ARGS(  node ).symlinkarg.to = (  nfspath ) node_name;
          
           SERP_ARGS(  node ).symlinkarg.attributes.mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
           /* TODO */
           SERP_ARGS(  node ).symlinkarg.attributes.uid = 0;
           SERP_ARGS(  node ).symlinkarg.attributes.gid = 0;
           SERP_ARGS(  node ).symlinkarg.attributes.size = 0;
           SERP_ARGS(  node ).symlinkarg.attributes.atime.seconds = now.tv_sec;
           SERP_ARGS(  node ).symlinkarg.attributes.atime.useconds = now.tv_usec;
           SERP_ARGS(  node ).symlinkarg.attributes.mtime.seconds = now.tv_sec;
           SERP_ARGS(  node ).symlinkarg.attributes.mtime.useconds = now.tv_usec;
          
           if (   nfscall(   node->nfs->server,  
           NFSPROC_SYMLINK,  
           (  xdrproc_t )xdr_symlinkargs,   &SERP_FILE(  node ),  
           (  xdrproc_t )xdr_nfsstat,   &status )
           || (  NFS_OK != (  errno = status ) )  ) {
          #if DEBUG & DEBUG_SYSCALLS
           perror(  "nfs_symlink" );
          #endif
           return -1;
           }
          
           return 0;
          }
          
          static int nfs_do_readlink(  
           rtems_filesystem_location_info_t *loc,   /* IN */
           strbuf *psbuf /* IN/OUT */
           )
          {
          NfsNode node = loc->node_access;
          Nfs nfs = node->nfs;
          readlinkres_strbuf rr;
          int wasAlloced;
          int rval;
          
           rr.strbuf = *psbuf;
          
           wasAlloced = (  0 == psbuf->buf );
          
           if (   (  rval = nfscall(  nfs->server,  
           NFSPROC_READLINK,  
           (  xdrproc_t )xdr_nfs_fh,   &SERP_FILE(  node ),  
           (  xdrproc_t )xdr_readlinkres_strbuf,   &rr ) )  ) {
           if (  wasAlloced )
           xdr_free(   (  xdrproc_t )xdr_strbuf,   (  caddr_t )&rr.strbuf  );
           }
          
          
           if (  NFS_OK != rr.status ) {
           if (  wasAlloced )
           xdr_free(   (  xdrproc_t )xdr_strbuf,   (  caddr_t )&rr.strbuf  );
           rtems_set_errno_and_return_minus_one(  rr.status );
           }
          
           *psbuf = rr.strbuf;
          
           return 0;
          }
          
          static int nfs_readlink(  
           rtems_filesystem_location_info_t *loc,   /* IN */
           char *buf,   /* OUT */
           size_t len
           )
          {
          strbuf sbuf;
           sbuf.buf = buf;
           sbuf.max = len;
          
           return nfs_do_readlink(  loc,   &sbuf );
          }
          
          /* The semantics of this routine are:
           *
           * The caller submits a valid pathloc,   i.e. it has
           * an NfsNode attached to node_access.
           * On return,   pathloc points to the target node which
           * may or may not be an NFS node.
           * Hence,   the original NFS node is released in either
           * case:
           * - link evaluation fails; pathloc points to no valid node
           * - link evaluation success; pathloc points to a new valid
           * node. If it's an NFS node,   a new NfsNode will be attached
           * to node_access...
           */
          
          #define LINKVAL_BUFLEN (  MAXPATHLEN+1 )
          #define RVAL_ERR_BUT_DONT_FREENODE (  -1 )
          #define RVAL_ERR_AND_DO_FREENODE (   1 )
          #define RVAL_OK (   0 )
          
          static int nfs_eval_link(  
           rtems_filesystem_location_info_t *pathloc,   /* IN/OUT */
           int flags /* IN */
           )
          {
          rtems_filesystem_node_types_t type;
          char *buf = malloc(  LINKVAL_BUFLEN );
          int rval = RVAL_ERR_AND_DO_FREENODE;
          
           if (  !buf ) {
           errno = ENOMEM;
           goto cleanup;
           }
          
           /* in this loop,   we must not use NFS specific ops as we might
           * step out of our FS during the process...
           * This algorithm should actually be performed by the
           * generic's evaluate_path routine :-(  
           *
           * Unfortunately,   there is no way of finding the
           * directory node who contains 'pathloc',   however :-(  
           */
           do {
           /* assume the generics have verified 'pathloc' to be
           * a link...
           */
           if (   !pathloc->ops->readlink_h  ) {
           errno = ENOTSUP;
           goto cleanup;
           }
          
           if (   pathloc->ops->readlink_h(  pathloc,   buf,   LINKVAL_BUFLEN )  ) {
           goto cleanup;
           }
          
          #if DEBUG & DEBUG_EVALPATH
           fprintf(  stderr,   "link value is '%s'\n",   buf );
          #endif
          
           /* is the link value an absolute path ? */
           if (   DELIM != *buf  ) {
           /* NO; a relative path */
          
           /* we must backup to the link's directory - we
           * know only how to do that for NFS,   however.
           * In this special case,   we can avoid recursion.
           * Otherwise (  i.e. if the link is on another FS ),  
           * we must step into its eval_link_h(   ).
           */
           if (  locIsNfs(  pathloc ) ) {
           NfsNode node = pathloc->node_access;
           int err;
          
           memcpy(   &SERP_FILE(  node ),  
           &node->args.dir,  
           sizeof(  node->args.dir )  );
          
           if (  updateAttr(  node,   1 /* force */ ) )
           goto cleanup;
          
           if (  SERP_ATTR(  node ).type != NFDIR ) {
           errno = ENOTDIR;
           goto cleanup;
           }
          
           pathloc->handlers = &nfs_dir_file_handlers;
          
           err = nfs_evalpath(  buf,   strlen(  buf ),   flags,   pathloc );
          
           /* according to its semantics,  
           * nfs_evalpath cloned the node attached
           * to pathloc. Hence we have to
           * release the old one (  referring to
           * the link; the new clone has been
           * updated and refers to the link _value_ ).
           */
           nfsNodeDestroy(  node );
          
           if (  err ) {
           /* nfs_evalpath has set errno;
           * pathloc->node_access has no
           * valid node attached in this case
           */
           rval = RVAL_ERR_BUT_DONT_FREENODE;
           goto cleanup;
           }
          
           } else {
           if (   ! pathloc->ops->eval_link_h  ) {
           errno = ENOTSUP;
           goto cleanup;
           }
           if (  !pathloc->ops->eval_link_h(  pathloc,   flags ) ) {
           /* FS is responsible for freeing its pathloc->node_access
           * if necessary
           */
           rval = RVAL_ERR_BUT_DONT_FREENODE;
           goto cleanup;
           }
           }
           } else {
           /* link points to an absolute path '/xxx' */
          
           /* release this node; filesystem_evaluate_path(   ) will
           * lookup a new one.
           */
           rtems_filesystem_freenode(  pathloc );
          
           if (  rtems_filesystem_evaluate_path(  buf,   strlen(  buf ),   flags,   pathloc,   1 ) ) {
           /* If evalpath fails then there is no valid node
           * attached to pathloc; hence we must not attempt
           * to free the node
           */
           rval = RVAL_ERR_BUT_DONT_FREENODE;
           goto cleanup;
           }
           }
          
           if (   !pathloc->ops->node_type_h  ) {
           errno = ENOTSUP;
           goto cleanup;
           }
          
           type = pathloc->ops->node_type_h(  pathloc );
          
          
           /* I dont know what to do about hard links */
           } while (   RTEMS_FILESYSTEM_SYM_LINK == type  );
          
           rval = RVAL_OK;
          
          cleanup:
          
           free(  buf );
          
           if (  RVAL_ERR_AND_DO_FREENODE == rval ) {
           rtems_filesystem_freenode(  pathloc );
           return -1;
           }
          
           return rval;
          }
          
          
          struct _rtems_filesystem_operations_table nfs_fs_ops = {
           nfs_evalpath,   /* MANDATORY */
           nfs_evalformake,   /* MANDATORY; may set errno=ENOSYS and return -1 */
           nfs_link,   /* OPTIONAL; may be defaulted */
           nfs_unlink,   /* OPTIONAL; may be defaulted */
           nfs_node_type,   /* OPTIONAL; may be defaulted; BUG in mount - no test!! */
           nfs_mknod,   /* OPTIONAL; may be defaulted */
           nfs_chown,   /* OPTIONAL; may be defaulted */
           nfs_freenode,   /* OPTIONAL; may be defaulted; (  release node_access ) */
           rtems_filesystem_default_mount,  
           rtems_nfs_initialize,   /* OPTIONAL; may be defaulted -- not used anymore */
           rtems_filesystem_default_unmount,  
           nfs_fsunmount_me,   /* OPTIONAL; may be defaulted */
           nfs_utime,   /* OPTIONAL; may be defaulted */
           nfs_eval_link,   /* OPTIONAL; may be defaulted */
           nfs_symlink,   /* OPTIONAL; may be defaulted */
           nfs_readlink,   /* OPTIONAL; may be defaulted */
           rtems_filesystem_default_rename,   /* OPTIONAL; may be defaulted */
           rtems_filesystem_default_statvfs /* OPTIONAL; may be defaulted */
          
          };
          
          /*****************************************
           File Handlers
          
           NOTE: the FS generics expect a FS'
           evalpath_h(   ) to switch the
           pathloc->handlers according
           to the pathloc/node's file
           type.
           We currently have 'file' and
           'directory' handlers and very
           few 'symlink' handlers.
          
           The handlers for each type are
           implemented or #defined ZERO
           in a 'nfs_file_xxx',  
           'nfs_dir_xxx',   'nfs_link_xxx'
           sequence below this point.
          
           In some cases,   a common handler,  
           can be used for all file types.
           It is then simply called
           'nfs_xxx'.
           *****************************************/
          
          /* stateless NFS protocol makes this trivial */
          static int nfs_file_open(  
           rtems_libio_t *iop,  
           const char *pathname,  
           uint32_t flag,  
           uint32_t mode
           )
          {
           return 0;
          }
          
          /* reading directories is not stateless; we must
           * remember the last 'read' position,   i.e.
           * the server 'cookie'. We do manage this information
           * attached to the pathinfo.node_access_2.
           */
          static int nfs_dir_open(  
           rtems_libio_t *iop,  
           const char *pathname,  
           uint32_t flag,  
           uint32_t mode
           )
          {
          NfsNode node = iop->pathinfo.node_access;
          DirInfo di;
          
           /* create a readdirargs object and copy the file handle;
           * attach to the pathinfo.node_access_2
           */
          
           di = (  DirInfo ) malloc(  sizeof(  *di ) );
           iop->pathinfo.node_access_2 = di;
          
           if (   !di  ) {
           errno = ENOMEM;
           return -1;
           }
          
           memcpy(   &di->readdirargs.dir,  
           &SERP_FILE(  node ),  
           sizeof(  di->readdirargs.dir )  );
          
           /* rewind cookie */
           memset(   &di->readdirargs.cookie,  
           0,  
           sizeof(  di->readdirargs.cookie )  );
          
           di->eofreached = FALSE;
          
           return 0;
          }
          
          static int nfs_file_close(  
           rtems_libio_t *iop
           )
          {
           return 0;
          }
          
          static int nfs_dir_close(  
           rtems_libio_t *iop
           )
          {
           free(  iop->pathinfo.node_access_2 );
           iop->pathinfo.node_access_2 = 0;
           return 0;
          }
          
          static ssize_t nfs_file_read(  
           rtems_libio_t *iop,  
           void *buffer,  
           size_t count
           )
          {
          readres rr;
          NfsNode node = iop->pathinfo.node_access;
          Nfs nfs = node->nfs;
          
           if (  count > NFS_MAXDATA )
           count = NFS_MAXDATA;
          
           SERP_ARGS(  node ).readarg.offset = iop->offset;
           SERP_ARGS(  node ).readarg.count = count;
           SERP_ARGS(  node ).readarg.totalcount = UINT32_C(  0xdeadbeef );
          
           rr.readres_u.reply.data.data_val = buffer;
          
           if (   nfscall(   nfs->server,  
           NFSPROC_READ,  
           (  xdrproc_t )xdr_readargs,   &SERP_FILE(  node ),  
           (  xdrproc_t )xdr_readres,   &rr )  ) {
           return -1;
           }
          
          
           if (  NFS_OK != rr.status ) {
           rtems_set_errno_and_return_minus_one(  rr.status );
           }
          
          #if DEBUG & DEBUG_SYSCALLS
           fprintf(  stderr,  
           "Read %i (  asked for %i ) bytes from offset %i to 0x%08x\n",  
           rr.readres_u.reply.data.data_len,  
           count,  
           iop->offset,  
           rr.readres_u.reply.data.data_val );
          #endif
          
          
           return rr.readres_u.reply.data.data_len;
          }
          
          /* this is called by readdir(   ) / getdents(   ) */
          static ssize_t nfs_dir_read(  
           rtems_libio_t *iop,  
           void *buffer,  
           size_t count
           )
          {
          DirInfo di = iop->pathinfo.node_access_2;
          RpcUdpServer server = (  (  Nfs )iop->pathinfo.mt_entry->fs_info )->server;
          
           if (   di->eofreached  )
           return 0;
          
           di->ptr = di->buf = buffer;
          
           /* align + round down the buffer */
           count &= ~ (  DIRENT_HEADER_SIZE - 1 );
           di->len = count;
          
          #if 0
           /* now estimate the number of entries we should ask for */
           count /= DIRENT_HEADER_SIZE + CONFIG_AVG_NAMLEN;
          
           /* estimate the encoded size that might take up */
           count *= dirres_entry_size + CONFIG_AVG_NAMLEN;
          #else
           /* integer arithmetics are better done the other way round */
           count *= dirres_entry_size + CONFIG_AVG_NAMLEN;
           count /= DIRENT_HEADER_SIZE + CONFIG_AVG_NAMLEN;
          #endif
          
           if (  count > NFS_MAXDATA )
           count = NFS_MAXDATA;
          
           di->readdirargs.count = count;
          
          #if DEBUG & DEBUG_READDIR
           fprintf(  stderr,  
           "Readdir: asking for %i XDR bytes,   buffer is %i\n",  
           count,   di->len );
          #endif
          
           if (   nfscall(  
           server,  
           NFSPROC_READDIR,  
           (  xdrproc_t )xdr_readdirargs,   &di->readdirargs,  
           (  xdrproc_t )xdr_dir_info,   di )  ) {
           return -1;
           }
          
          
           if (  NFS_OK != di->status ) {
           rtems_set_errno_and_return_minus_one(  di->status );
           }
          
           return (  char* )di->ptr - (  char* )buffer;
          }
          
          static ssize_t nfs_file_write(  
           rtems_libio_t *iop,  
           const void *buffer,  
           size_t count
           )
          {
          NfsNode node = iop->pathinfo.node_access;
          Nfs nfs = node->nfs;
          int e;
          
           if (  count > NFS_MAXDATA )
           count = NFS_MAXDATA;
          
          
           SERP_ARGS(  node ).writearg.beginoffset = UINT32_C(  0xdeadbeef );
           if (   LIBIO_FLAGS_APPEND & iop->flags  ) {
           if (   updateAttr(  node,   0 )  ) {
           return -1;
           }
           SERP_ARGS(  node ).writearg.offset = SERP_ATTR(  node ).size;
           } else {
           SERP_ARGS(  node ).writearg.offset = iop->offset;
           }
           SERP_ARGS(  node ).writearg.totalcount = UINT32_C(  0xdeadbeef );
           SERP_ARGS(  node ).writearg.data.data_len = count;
           SERP_ARGS(  node ).writearg.data.data_val = (  void* )buffer;
          
           /* write XDR buffer size will be chosen by nfscall based
           * on the PROC specifier
           */
          
           if (   nfscall(   nfs->server,  
           NFSPROC_WRITE,  
           (  xdrproc_t )xdr_writeargs,   &SERP_FILE(  node ),  
           (  xdrproc_t )xdr_attrstat,   &node->serporid )  ) {
           return -1;
           }
          
          
           if (  NFS_OK != (  e=node->serporid.status )  ) {
           /* try at least to recover the current attributes */
           updateAttr(  node,   1 /* force */ );
           rtems_set_errno_and_return_minus_one(  e );
           }
          
           node->age = nowSeconds(   );
          
           return count;
          }
          
          static rtems_off64_t nfs_file_lseek(  
           rtems_libio_t *iop,  
           rtems_off64_t length,  
           int whence
           )
          {
          #if DEBUG & DEBUG_SYSCALLS
           fprintf(  stderr,  
           "lseek to %i (  length %i,   whence %i )\n",  
           iop->offset,  
           length,  
           whence );
          #endif
           if (   SEEK_END == whence  ) {
           /* rtems (  4.6.2 ) libcsupport code 'lseek' uses iop->size to
           * compute the offset. We don't want to track the file size
           * by updating 'iop->size' constantly.
           * Since lseek is the only place using iop->size,   we work
           * around this by tweaking the offset here...
           */
           NfsNode node = iop->pathinfo.node_access;
           fattr *fa = &SERP_ATTR(  node );
          
           if (  updateAttr(  node,   0 /* only if old */ ) ) {
           return -1;
           }
           iop->offset = fa->size;
           }
          
           /* this is particularly easy :- ) */
           return iop->offset;
          }
          
          static rtems_off64_t nfs_dir_lseek(  
           rtems_libio_t *iop,  
           rtems_off64_t length,  
           int whence
           )
          {
          DirInfo di = iop->pathinfo.node_access_2;
          
           /* we don't support anything other than
           * rewinding
           */
           if (  SEEK_SET != whence || 0 != length ) {
           errno = ENOTSUP;
           return -1;
           }
          
           /* rewind cookie */
           memset(   &di->readdirargs.cookie,  
           0,  
           sizeof(  di->readdirargs.cookie )  );
          
           di->eofreached = FALSE;
          
           return iop->offset;
          }
          
          #if 0 /* structure types for reference */
          struct fattr {
           ftype type;
           u_int mode;
           u_int nlink;
           u_int uid;
           u_int gid;
           u_int size;
           u_int blocksize;
           u_int rdev;
           u_int blocks;
           u_int fsid;
           u_int fileid;
           nfstime atime;
           nfstime mtime;
           nfstime ctime;
          };
          
          struct stat
          {
           dev_t st_dev;
           ino_t st_ino;
           mode_t st_mode;
           nlink_t st_nlink;
           uid_t st_uid;
           gid_t st_gid;
           dev_t st_rdev;
           rtems_off64_t st_size;
           /* SysV/sco doesn't have the rest... But Solaris,   eabi does. */
          #if defined(  __svr4__ ) && !defined(  __PPC__ ) && !defined(  __sun__ )
           time_t st_atime;
           time_t st_mtime;
           time_t st_ctime;
          #else
           time_t st_atime;
           long st_spare1;
           time_t st_mtime;
           long st_spare2;
           time_t st_ctime;
           long st_spare3;
           long st_blksize;
           long st_blocks;
           long st_spare4[2];
          #endif
          };
          #endif
          
          /* common for file/dir/link */
          static int nfs_fstat(  
           rtems_filesystem_location_info_t *loc,  
           struct stat *buf
           )
          {
          NfsNode node = loc->node_access;
          fattr *fa = &SERP_ATTR(  node );
          
           if (  updateAttr(  node,   0 /* only if old */ ) ) {
           return -1;
           }
          
          /* done by caller
           memset(  buf,   0,   sizeof(  *buf ) );
           */
          
           /* translate */
          
           /* one of the branches hopefully is optimized away */
           if (  sizeof(  ino_t ) < sizeof(  u_int ) ) {
           buf->st_dev = NFS_MAKE_DEV_T_INO_HACK(  (  NfsNode )loc->node_access );
           } else {
           buf->st_dev = NFS_MAKE_DEV_T(  (  NfsNode )loc->node_access );
           }
           buf->st_mode = fa->mode;
           buf->st_nlink = fa->nlink;
           buf->st_uid = fa->uid;
           buf->st_gid = fa->gid;
           buf->st_size = fa->size;
           /* Set to "preferred size" of this NFS client implementation */
           buf->st_blksize = nfsStBlksize ? nfsStBlksize : fa->blocksize;
           buf->st_rdev = fa->rdev;
           buf->st_blocks = fa->blocks;
           buf->st_ino = fa->fileid;
           buf->st_atime = fa->atime.seconds;
           buf->st_mtime = fa->mtime.seconds;
           buf->st_ctime = fa->ctime.seconds;
          
          #if 0 /* NFS should return the modes */
           switch(  fa->type ) {
           default:
           case NFNON:
           case NFBAD:
           break;
          
           case NFSOCK: buf->st_mode |= S_IFSOCK; break;
           case NFFIFO: buf->st_mode |= S_IFIFO; break;
           case NFREG : buf->st_mode |= S_IFREG; break;
           case NFDIR : buf->st_mode |= S_IFDIR; break;
           case NFBLK : buf->st_mode |= S_IFBLK; break;
           case NFCHR : buf->st_mode |= S_IFCHR; break;
           case NFLNK : buf->st_mode |= S_IFLNK; break;
           }
          #endif
          
           return 0;
          }
          
          /* a helper which does the real work for
           * a couple of handlers (  such as chmod,  
           * ftruncate or utime )
           */
          static int
          nfs_sattr(  NfsNode node,   sattr *arg,   u_long mask )
          {
          
          struct timeval now;
          nfstime nfsnow,   t;
          int e;
          u_int mode;
          
           if (  updateAttr(  node,   0 /* only if old */ ) )
           return -1;
          
           rtems_clock_get_tod_timeval(  &now );
          
           /* TODO: add rtems EPOCH - UNIX EPOCH seconds */
           nfsnow.seconds = now.tv_sec;
           nfsnow.useconds = now.tv_usec;
          
           /* merge permission bits into existing type bits */
           mode = SERP_ATTR(  node ).mode;
           if (  mask & SATTR_MODE ) {
           mode &= S_IFMT;
           mode |= arg->mode & ~S_IFMT;
           } else {
           mode = -1;
           }
           SERP_ARGS(  node ).sattrarg.attributes.mode = mode;
          
           SERP_ARGS(  node ).sattrarg.attributes.uid =
           (  mask & SATTR_UID ) ? arg->uid : -1;
          
           SERP_ARGS(  node ).sattrarg.attributes.gid =
           (  mask & SATTR_GID ) ? arg->gid : -1;
          
           SERP_ARGS(  node ).sattrarg.attributes.size =
           (  mask & SATTR_SIZE ) ? arg->size : -1;
          
           if (  mask & SATTR_ATIME )
           t = arg->atime;
           else if (  mask & SATTR_TOUCHA )
           t = nfsnow;
           else
           t.seconds = t.useconds = -1;
           SERP_ARGS(  node ).sattrarg.attributes.atime = t;
          
           if (  mask & SATTR_ATIME )
           t = arg->mtime;
           else if (  mask & SATTR_TOUCHA )
           t = nfsnow;
           else
           t.seconds = t.useconds = -1;
           SERP_ARGS(  node ).sattrarg.attributes.mtime = t;
          
           node->serporid.status = NFS_OK;
          
           if (   nfscall(   node->nfs->server,  
           NFSPROC_SETATTR,  
           (  xdrproc_t )xdr_sattrargs,   &SERP_FILE(  node ),  
           (  xdrproc_t )xdr_attrstat,   &node->serporid )  ) {
          #if DEBUG & DEBUG_SYSCALLS
           fprintf(  stderr,  
           "nfs_sattr (  mask 0x%08x ): %s",  
           mask,  
           strerror(  errno ) );
          #endif
           return -1;
           }
          
           if (  NFS_OK != (  e=node->serporid.status )  ) {
          #if DEBUG & DEBUG_SYSCALLS
           fprintf(  stderr,  "nfs_sattr: %s\n",  strerror(  e ) );
          #endif
           /* try at least to recover the current attributes */
           updateAttr(  node,   1 /* force */ );
           rtems_set_errno_and_return_minus_one(  e );
           }
          
           node->age = nowSeconds(   );
          
           return 0;
          }
          
          
          /* common for file/dir/link */
          static int nfs_fchmod(  
           rtems_filesystem_location_info_t *loc,  
           mode_t mode
           )
          {
          sattr arg;
          
           arg.mode = mode;
           return nfs_sattr(  loc->node_access,   &arg,   SATTR_MODE );
          
          }
          
          /* just set the size attribute to 'length'
           * the server will take care of the rest :- )
           */
          static int nfs_file_ftruncate(  
           rtems_libio_t *iop,  
           rtems_off64_t length
           )
          {
          sattr arg;
          
           arg.size = length;
           /* must not modify any other attribute; if we are not the owner
           * of the file or directory but only have write access changing
           * any attribute besides 'size' will fail...
           */
           return nfs_sattr(  iop->pathinfo.node_access,  
           &arg,  
           SATTR_SIZE );
          }
          
          /* files and symlinks are removed
           * by the common nfs_unlink(   ) routine.
           * NFS has a different NFSPROC_RMDIR
           * call,   though...
           */
          static int nfs_dir_rmnod(  
           rtems_filesystem_location_info_t *parentpathloc,   /* IN */
           rtems_filesystem_location_info_t *pathloc /* IN */
           )
          {
           return nfs_do_unlink(  parentpathloc,   pathloc,   NFSPROC_RMDIR );
          }
          
          /* the file handlers table */
          static
          struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers = {
           nfs_file_open,   /* OPTIONAL; may be defaulted */
           nfs_file_close,   /* OPTIONAL; may be defaulted */
           nfs_file_read,   /* OPTIONAL; may be defaulted */
           nfs_file_write,   /* OPTIONAL; may be defaulted */
           rtems_filesystem_default_ioctl,  
           nfs_file_lseek,   /* OPTIONAL; may be defaulted */
           nfs_fstat,   /* OPTIONAL; may be defaulted */
           nfs_fchmod,   /* OPTIONAL; may be defaulted */
           nfs_file_ftruncate,   /* OPTIONAL; may be defaulted */
           rtems_filesystem_default_fpathconf,  
           rtems_filesystem_default_fsync,  
           rtems_filesystem_default_fdatasync,  
           rtems_filesystem_default_fcntl,  
           nfs_unlink,   /* OPTIONAL; may be defaulted */
          };
          
          /* the directory handlers table */
          static
          struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers = {
           nfs_dir_open,   /* OPTIONAL; may be defaulted */
           nfs_dir_close,   /* OPTIONAL; may be defaulted */
           nfs_dir_read,   /* OPTIONAL; may be defaulted */
           rtems_filesystem_default_write,  
           rtems_filesystem_default_ioctl,  
           nfs_dir_lseek,   /* OPTIONAL; may be defaulted */
           nfs_fstat,   /* OPTIONAL; may be defaulted */
           nfs_fchmod,   /* OPTIONAL; may be defaulted */
           rtems_filesystem_default_ftruncate,  
           rtems_filesystem_default_fpathconf,  
           rtems_filesystem_default_fsync,  
           rtems_filesystem_default_fdatasync,  
           rtems_filesystem_default_fcntl,  
           nfs_dir_rmnod,   /* OPTIONAL; may be defaulted */
          };
          
          /* the link handlers table */
          static
          struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers = {
           rtems_filesystem_default_open,  
           rtems_filesystem_default_close,  
           rtems_filesystem_default_read,  
           rtems_filesystem_default_write,  
           rtems_filesystem_default_ioctl,  
           rtems_filesystem_default_lseek,  
           nfs_fstat,   /* OPTIONAL; may be defaulted */
           nfs_fchmod,   /* OPTIONAL; may be defaulted */
           rtems_filesystem_default_ftruncate,  
           rtems_filesystem_default_fpathconf,  
           rtems_filesystem_default_fsync,  
           rtems_filesystem_default_fdatasync,  
           rtems_filesystem_default_fcntl,  
           nfs_unlink,   /* OPTIONAL; may be defaulted */
          };
          
          /* we need a dummy driver entry table to get a
           * major number from the system
           */
          static
          rtems_device_driver nfs_initialize(  
           rtems_device_major_number major,  
           rtems_device_minor_number minor,  
           void *arg
           )
          {
           /* we don't really use this routine because
           * we cannot supply an argument (  contrary
           * to what the 'arg' parameter suggests - it
           * is always set to 0 by the generics :-(   )
           * and because we don't want the user to
           * have to deal with the major number (  which
           * OTOH is something WE are interested in. The
           * only reason for using this API was getting
           * a major number,   after all ).
           *
           * Something must be present,   however,   to
           * reserve a slot in the driver table.
           */
           return RTEMS_SUCCESSFUL;
          }
          
          static rtems_driver_address_table drvNfs = {
           nfs_initialize,  
           0,   /* open */
           0,   /* close */
           0,   /* read */
           0,   /* write */
           0 /* control */
          };
          
          /* Dump a list of the currently mounted NFS to a file */
          int
          nfsMountsShow(  FILE *f )
          {
          char *mntpt = 0;
          Nfs nfs;
          
           if (  !f )
           f = stdout;
          
           if (   !(  mntpt=malloc(  MAXPATHLEN ) )  ) {
           fprintf(  stderr,  "nfsMountsShow(   ): no memory\n" );
           return -1;
           }
          
           fprintf(  f,  "Currently Mounted NFS:\n" );
          
           LOCK(  nfsGlob.llock );
          
           for (  nfs = nfsGlob.mounted_fs; nfs; nfs=nfs->next ) {
           fprintf(  f,  "%s on ",   nfs->mt_entry->dev );
           if (  rtems_filesystem_resolve_location(  mntpt,   MAXPATHLEN,   &nfs->mt_entry->mt_fs_root ) )
           fprintf(  f,  "<UNABLE TO LOOKUP MOUNTPOINT>\n" );
           else
           fprintf(  f,  "%s\n",  mntpt );
           }
          
           UNLOCK(  nfsGlob.llock );
          
           free(  mntpt );
           return 0;
          }
          
          #if 0
          CCJ_REMOVE_MOUNT
          /* convenience wrapper
           *
           * NOTE: this routine calls NON-REENTRANT
           * gethostbyname(   ) if the host is
           * not in 'dot' notation.
           */
          int
          nfsMount(  char *uidhost,   char *path,   char *mntpoint )
          {
          struct stat st;
          int devl;
          char *host;
          int rval = -1;
          char *dev = 0;
          
           if (  !uidhost || !path || !mntpoint ) {
           fprintf(  stderr,  "usage: nfsMount(  ""[uid.gid@]host"",  ""path"",  ""mountpoint"" )\n" );
           nfsMountsShow(  stderr );
           return -1;
           }
          
           if (   !(  dev = malloc(  (  devl=strlen(  uidhost ) + 20 + strlen(  path )+1 ) ) )  ) {
           fprintf(  stderr,  "nfsMount: out of memory\n" );
           return -1;
           }
          
           /* Try to create the mount point if nonexistent */
           if (  stat(  mntpoint,   &st ) ) {
           if (  ENOENT != errno ) {
           perror(  "nfsMount trying to create mount point - stat failed" );
           goto cleanup;
           } else if (  mkdir(  mntpoint,  0777 ) ) {
           perror(  "nfsMount trying to create mount point" );
           goto cleanup;
           }
           }
          
           if (   !(  host=strchr(  uidhost,  UIDSEP ) )  ) {
           host = uidhost;
           } else {
           host++;
           }
          
           if (  isdigit(  (  unsigned char )*host ) ) {
           /* avoid using gethostbyname */
           sprintf(  dev,  "%s:%s",  uidhost,  path );
           } else {
           struct hostent *h;
          
           /* copy the uid part (  hostname will be
           * overwritten )
           */
           strcpy(  dev,   uidhost );
          
           /* NOTE NOTE NOTE: gethostbyname is NOT
           * thread safe. This is UGLY
           */
          
          /* BEGIN OF NON-THREAD SAFE REGION */
          
           h = gethostbyname(  host );
          
           if (   !h ||
           !inet_ntop(   AF_INET,  
           (  struct in_addr* )h->h_addr_list[0],  
           dev + (  host - uidhost ),  
           devl - (  host - uidhost )  )
            ) {
           fprintf(  stderr,  "nfsMount: host '%s' not found\n",  host );
           goto cleanup;
           }
          
          /* END OF NON-THREAD SAFE REGION */
          
           /* append ':<path>' */
           strcat(  dev,  ":" );
           strcat(  dev,  path );
           }
          
           printf(  "Trying to mount %s on %s\n",  dev,  mntpoint );
          
           if (  mount(  dev,  
           mntpoint,  
           "nfs",  
           RTEMS_FILESYSTEM_READ_WRITE,  
           NULL ) ) {
           perror(  "nfsMount - mount" );
           goto cleanup;
           }
          
           rval = 0;
          
          cleanup:
           free(  dev );
           return rval;
          }
          #endif
          
          /* HERE COMES A REALLY UGLY HACK */
          
          /* This is stupid; it is _very_ hard to find the path
           * leading to a rtems_filesystem_location_info_t node :-(  
           * The only easy way is making the location the current
           * directory and issue a getcwd(   ).
           * However,   since we don't want to tamper with the
           * current directory,   we must create a separate
           * task to do the job for us - sigh.
           */
          
          typedef struct ResolvePathArgRec_ {
           rtems_filesystem_location_info_t *loc; /* IN: location to resolve */
           char *buf; /* IN/OUT: buffer where to put the path */
           int len; /* IN: buffer length */
           rtems_id sync; /* IN: synchronization */
           rtems_status_code status; /* OUT: result */
          } ResolvePathArgRec,   *ResolvePathArg;
          
          static void
          resolve_path(  rtems_task_argument arg )
          {
          ResolvePathArg rpa = (  ResolvePathArg )arg;
          rtems_filesystem_location_info_t old;
          
           /* IMPORTANT: let the helper task have its own libio environment (  i.e. cwd ) */
           if (  RTEMS_SUCCESSFUL == (  rpa->status = rtems_libio_set_private_env(   ) ) ) {
          
           old = rtems_filesystem_current;
          
           rtems_filesystem_current = *(  rpa->loc );
          
           if (   !getcwd(  rpa->buf,   rpa->len )  )
           rpa->status = RTEMS_UNSATISFIED;
          
           /* must restore the cwd because 'freenode' will be called on it */
           rtems_filesystem_current = old;
           }
           rtems_semaphore_release(  rpa->sync );
           rtems_task_delete(  RTEMS_SELF );
          }
          
          
          /* a utility routine to find the path leading to a
           * rtems_filesystem_location_info_t node
           *
           * INPUT: 'loc' and a buffer 'buf' (  length 'len' ) to hold the
           * path.
           * OUTPUT: path copied into 'buf'
           *
           * RETURNS: 0 on success,   RTEMS error code on error.
           */
          rtems_status_code
          rtems_filesystem_resolve_location(  char *buf,   int len,   rtems_filesystem_location_info_t *loc )
          {
          ResolvePathArgRec arg;
          rtems_id tid = 0;
          rtems_task_priority pri;
          rtems_status_code status;
          
           arg.loc = loc;
           arg.buf = buf;
           arg.len = len;
           arg.sync = 0;
          
           status = rtems_semaphore_create(  
           rtems_build_name(  'r',  'e',  's',  's' ),  
           0,  
           RTEMS_SIMPLE_BINARY_SEMAPHORE,  
           0,  
           &arg.sync );
          
           if (  RTEMS_SUCCESSFUL != status )
           goto cleanup;
          
           rtems_task_set_priority(  RTEMS_SELF,   RTEMS_CURRENT_PRIORITY,   &pri );
          
           status = rtems_task_create(  
           rtems_build_name(  'r',  'e',  's',  's' ),  
           pri,  
           RTEMS_MINIMUM_STACK_SIZE + 50000,  
           RTEMS_DEFAULT_MODES,  
           RTEMS_DEFAULT_ATTRIBUTES,  
           &tid );
          
           if (  RTEMS_SUCCESSFUL != status )
           goto cleanup;
          
           status = rtems_task_start(  tid,   resolve_path,   (  rtems_task_argument )&arg );
          
           if (  RTEMS_SUCCESSFUL != status ) {
           rtems_task_delete(  tid );
           goto cleanup;
           }
          
          
           /* synchronize with the helper task */
           rtems_semaphore_obtain(  arg.sync,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
          
           status = arg.status;
          
          cleanup:
           if (  arg.sync )
           rtems_semaphore_delete(  arg.sync );
          
           return status;
          }
          
          int
          nfsSetTimeout(  uint32_t timeout_ms )
          {
          rtems_interrupt_level k;
          uint32_t s,  us;
          
           if (   timeout_ms > 100000  ) {
           /* out of range */
           return -1;
           }
          
           s = timeout_ms/1000;
           us = (  timeout_ms % 1000 ) * 1000;
          
           rtems_interrupt_disable(  k );
           _nfscalltimeout.tv_sec = s;
           _nfscalltimeout.tv_usec = us;
           rtems_interrupt_enable(  k );
          
           return 0;
          }
          
          uint32_t
          nfsGetTimeout(   void  )
          {
          rtems_interrupt_level k;
          uint32_t s,  us;
           rtems_interrupt_disable(  k );
           s = _nfscalltimeout.tv_sec;
           us = _nfscalltimeout.tv_usec;
           rtems_interrupt_enable(  k );
           return s*1000 + us/1000;
          }

libfs/src/nfsclient/src/nfs.modini.c

       1  #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include "librtemsNfs.h"
          
          /* CEXP dynamic loader support */
          
          void
      10  _cexpModuleInitialize(  void *mod )
          {
          #if defined(  DEBUG )
           /* print load address (  in case we crash while initializing ) */
          unsigned lr;
           __asm__ __volatile__(  
           " bl thisis_loaded_at \n"
           "thisis_loaded_at: \n"
           " mflr %0 \n"
           : "=r"(  lr ) ::"lr" );
           printf(  "thisis_loaded_at: 0x%08x\n",  lr );
          #endif
           nfsInit(  0,  0 );
          }
          
          int
      26  _cexpModuleFinalize(  void *mod )
          {
           return nfsCleanup(   );
          }
          
          

libfs/src/nfsclient/src/nfsTest.c

       1  /* $Id: nfsTest.c,  v 1.4 2010/03/27 04:04:39 ccj Exp $ */
          
          /* Test program for evaluating NFS read throughput */
          
          /* Author: Till Straumann <strauman@slac.stanford.edu>,   2006 */
          
          /* This test code allows for evaluating NFS read performance
           * under various scenarios:
           * - synchronous reads with various buffer sizes (  select
           * 'num_readers' == 0,   see below ).
           * - pseudo 'read-ahead' using multiple threads that issue
           * NFS reads from the same file (  but from different offsets )
           * in parallel.
           * Rationale: each NFS read request is synchronous,   i.e.,   the
           * caller sends a request to the server and waits for the
           * reply to come back. Performance enhancement can be expected
           * by requesting multiple blocks in parallel rather than
           * sequentially.
           *
           * rtems_interval
           * nfsTestRead(  char *file_name,   int chunk_size,   int num_readers );
           *
           * 1 ) creates 'num_readers' threads,   each opening 'file_name' for
           * reading on a separate file descriptor.
           * 2 ) creates message queues for communicating with reader threads
           *
           * 3 ) read file using nfsTestReadBigbuf(   ) until EOF is reached
           *
           * 4 ) releases resources.
           *
           * RETURNS: Time elapsed during step 3 in ms. This is measured
           * using the system clock so make sure the test file
           * is big enough.
           *
           * nfsTestReadBigbuf(   ) synchronously reads a block of
           * 'num_readers * chunk_size' (  which may be bigger than
           * the UDP limit of 8k ) using 'num_reader' threads to
           * retrieve the various pieces of the big block in parallel.
           * This speeds up things since several RPC calls can
           * be in the works at once.
           *
           * NOTES:
           * - if 'num_readers' == 0 this corresponds to an 'ordinary'
           * NFS read. 'num_readers' == 1 schedules a single reader
           * thread (  == ordinary NFS read + message passing overhead ).
           * - no actual processing on the data is done; they are simply
           * thrown away. A real,   performance-critical application could
           * pipeline 'reader' and 'cruncher' threads.
           * - read is not completely asynchronous; synchronization is still
           * performed at 'big block' boundaries (  num_readers * chunk_size ).
           */
          
          /*
           * Authorship
           * ----------
           * This software (  NFS-2 client implementation for RTEMS ) was created by
           * Till Straumann <strauman@slac.stanford.edu>,   2002-2007,  
           * Stanford Linear Accelerator Center,   Stanford University.
           *
           * Acknowledgement of sponsorship
           * ------------------------------
           * The NFS-2 client implementation for RTEMS was produced by
           * the Stanford Linear Accelerator Center,   Stanford University,  
           * under Contract DE-AC03-76SFO0515 with the Department of Energy.
           *
           * Government disclaimer of liability
           * ----------------------------------
           * Neither the United States nor the United States Department of Energy,  
           * nor any of their employees,   makes any warranty,   express or implied,   or
           * assumes any legal liability or responsibility for the accuracy,  
           * completeness,   or usefulness of any data,   apparatus,   product,   or process
           * disclosed,   or represents that its use would not infringe privately owned
           * rights.
           *
           * Stanford disclaimer of liability
           * --------------------------------
           * Stanford University makes no representations or warranties,   express or
           * implied,   nor assumes any liability for the use of this software.
           *
           * Stanford disclaimer of copyright
           * --------------------------------
           * Stanford University,   owner of the copyright,   hereby disclaims its
           * copyright and all other rights in this software. Hence,   anyone may
           * freely use it for any purpose without restriction.
           *
           * Maintenance of notices
           * ----------------------
           * In the interest of clarity regarding the origin and status of this
           * SLAC software,   this and all the preceding Stanford University notices
           * are to remain affixed to any copy or derivative of this software made
           * or distributed by the recipient and are to be affixed to any copy of
           * software made or distributed by the recipient that contains a copy or
           * derivative of this software.
           *
           * ------------------ SLAC Software Notices,   Set 4 OTT.002a,   2004 FEB 03
           */
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/error.h>
          
          #include <fcntl.h>
          #include <stdlib.h>
          #include <stdio.h>
          
          unsigned nfsTestReaderPri = 80;
          
          struct nfsTestReq_ {
           unsigned offset; /* file offset */
           int size; /* IN: block size to read (  must be < 8192 ),   OUT: bytes actually read */
           void *buf; /* data buffer address */
          };
          
          /* Queue for sending requests to parallel reader tasks */
          rtems_id nfsTestRQ = 0;
          /* Queue to pickup replies from parallel reader tasks */
          rtems_id nfsTestAQ = 0;
          
          
          /* Reader task; opens its own file descriptor
           * and works on requests:
           * - obtain request from request queue.
           * - lseek to the requested file offset
           * - NFS read into buffer
           * - queue reply.
           *
           * Note that this implementation is very simple
           * - no full error checking.
           * - file is opened/closed by thread
           * it's main purpose is running quick tests.
           */
          static rtems_task
     135  nfsTestReader(  rtems_task_argument arg )
          {
          int fd = open(  (  char* )arg,  O_RDONLY );
          unsigned long s;
          struct nfsTestReq_ r;
          rtems_status_code sc;
          
           if (   fd < 0  ) {
           perror(  "nfsReader: opening file" );
           goto cleanup;
           }
           do {
           s = sizeof(  r );
           sc = rtems_message_queue_receive(  nfsTestRQ,   &r,   &s,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           if (   RTEMS_SUCCESSFUL != sc  ) {
           rtems_error(  sc,   "(  Error ) reading from message queue" );
           goto cleanup;
           }
           if (   !r.buf  ) {
           /* They send a NULL buffer as a shutdown request */
           break;
           }
          #ifdef DEBUG
           printf(  "Reader: reading offset %u,   size %i to %p ... ",  
           r.offset,   r.size,   r.buf );
          #endif
           /* seek to requested offset */
           lseek(  fd,   r.offset,   SEEK_SET );
           r.size = read(  fd,   r.buf,   r.size );
          #ifdef DEBUG
           printf(  "got %i\n",  r.size );
          #endif
           rtems_message_queue_send(  nfsTestAQ,   &r,   sizeof(  r ) );
           } while (  1 ) ;
          
          cleanup:
           if (   fd >= 0  )
           close(  fd );
           rtems_task_delete(  RTEMS_SELF );
          }
          
          
          /* helper to create and start a reader task */
          static rtems_id
     179  taskSpawn(  char *filenm,   int inst )
          {
          rtems_status_code sc;
          rtems_id tid;
          
           sc = rtems_task_create(  
           rtems_build_name(  'n',  't',  't',  '0'+inst ),  
           nfsTestReaderPri,  
           1400,  
           RTEMS_DEFAULT_MODES,  
           RTEMS_DEFAULT_ATTRIBUTES,  
           &tid );
           if (   RTEMS_SUCCESSFUL != sc  ) {
           rtems_error(  sc,  "(  Error ) Creating nfs reader task %i",  inst );
           return 0;
           }
          
           sc = rtems_task_start(  tid,   nfsTestReader,   (  rtems_task_argument )filenm );
           if (   RTEMS_SUCCESSFUL != sc  ) {
           rtems_error(  sc,  "(  Error ) Staritng nfs reader task %i",  inst );
           rtems_task_delete(  tid );
           return 0;
           }
          
           return tid;
          }
          
          /*
           * Read nrd*sz bytes into 'buf' from file offset 'off'
           * using 'nrd' parallel reader tasks to do the job.
           * This helper routine schedules 'nrd' requests to
           * the reader tasks and waits for all requests to
           * finish.
           *
           * RETURNS: number of bytes read or -1 (  error ).
           *
           * CAVEATS:
           * - assumes read requests always return 'sz' bytes
           * unless the end of file is reached.
           * THIS ASSUMPTION SHOULD NOT BE MADE WHEN WRITING
           * ANY 'REAL' CODE.
           */
          static int
     222  nfsTestReadBigbuf(  char *buf,   int off,   int sz,   int nrd )
          {
          int i,  rval=0;
          struct nfsTestReq_ r;
           r.buf = buf;
           r.size = sz;
           r.offset = off;
           /* send out parallel requests */
           for (  i=0; i<nrd; i++ ) {
           rtems_message_queue_send(  nfsTestRQ,   &r,   sizeof(  r ) );
           r.offset += sz;
           r.buf += sz;
           }
           /* wait for answers */
           for (  i=0; i<nrd; i++ ) {
           unsigned long s = sizeof(  r );
           rtems_message_queue_receive(  nfsTestAQ,   &r,   &s,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           if (   r.size < 0  ) {
           fprintf(  stderr,  "A reader failed\n" );
           rval = -1;
           } else {
           /* FIXME sanity checks:
           * - catch case where any-but-last read returns < sz
           */
           if (   rval >= 0  ) {
           rval += r.size;
           }
           }
           }
           return rval;
          }
          
          /* Main test routine
           *
           * Read file 'fname' usint 'nrd' parallel reader tasks,  
           * each operating on chunks of 'sz' bytes.
           *
           * RETURNS: time elapsed in milliseconds. This is measured
           * using the system clock. Hence,   for the result
           * to be meaningful,   the file must be big enough.
           *
           */
          rtems_interval
     265  nfsTestRead(  char *fnam,   int sz,   int nrd )
          {
          int i;
          unsigned off;
          rtems_interval now=-1,   then,   tickspsec;
          rtems_status_code sc;
          int fd=-1;
          char *buf=0;
          
           if (   nrd < 0  )
           nrd = 0;
          
           if (   sz < 0 || sz > 8192  ) {
           fprintf(  stderr,  "\n" );
           return -1;
           }
          
           nfsTestRQ = nfsTestAQ = 0;
          
           /* Allocate buffer */
           if (   ! (  buf=malloc(  sz*(  nrd ? nrd : 1 ) ) )  ) {
           perror(  "allocating buffer" );
           goto cleanup;
           }
          
           /* Don't bother proceeding if we can't open the file for reading */
           if (   (  fd=open(  fnam,  O_RDONLY ) ) < 0  ) {
           perror(  "opening file" );
           goto cleanup;
           }
           if (   nrd  ) {
           close(  fd ); fd = -1;
           }
          
           /* Create request queue */
           if (   nrd  ) {
           sc = rtems_message_queue_create(  
           rtems_build_name(  'n',  't',  'r',  'q' ),  
           nrd,  
           sizeof(  struct nfsTestReq_ ),  
           RTEMS_DEFAULT_ATTRIBUTES,  
           & nfsTestRQ  );
          
           if (   RTEMS_SUCCESSFUL != sc  ) {
           rtems_error(  sc,   "(  Error ) creating request queue" );
           nfsTestRQ = 0;
           goto cleanup;
           }
          
           /* Spawn reader tasks */
           for (   i=0; i<nrd; i++  ) {
           if (   ! taskSpawn(  fnam,   i )  )
           goto cleanup;
           }
          
           /* Create reply queue */
           sc = rtems_message_queue_create(  
           rtems_build_name(  'n',  't',  'a',  'q' ),  
           nrd,  
           sizeof(  struct nfsTestReq_ ),  
           RTEMS_DEFAULT_ATTRIBUTES,  
           & nfsTestAQ  );
          
           if (   RTEMS_SUCCESSFUL != sc  ) {
           rtems_error(  sc,   "(  Error ) creating reply queue" );
           nfsTestAQ = 0;
           goto cleanup;
           }
           }
          
           /* Timed main loop */
           then = rtems_clock_get_ticks_since_boot(   );
          
           if (   nrd  ) {
           off = 0;
           while (  (  i = nfsTestReadBigbuf(  buf,   off,   sz,   nrd ) ) > 0  ) {
          #ifdef DEBUG
           printf(  "bigbuf got %i\n",   i );
          #endif
           off += i;
           }
           } else {
           while (   (  i = read(  fd,   buf,   sz ) ) > 0  )
           /* nothing else to do */;
           if (   i < 0  ) {
           perror(  "reading" );
           goto cleanup;
           }
           }
          
           now = rtems_clock_get_ticks_since_boot(   );
           now = (  now-then )*1000;
           ticksspec = rtems_clock_get_ticks_per_second(   );
           now /= tickspsec; /* time in ms */
          
          cleanup:
           if (   fd >= 0  )
           close(  fd );
          
           if (   nfsTestRQ  ) {
           /* request tasks to shutdown by sending NULL buf request */
           struct nfsTestReq_ r;
           r.buf = 0;
           for (   i=0; i<nrd; i++  ) {
           rtems_message_queue_send(   nfsTestRQ,   &r,   sizeof(  r )  );
           }
           /* cheat: instead of proper synchronization with shutdown we simply
           * delay for a second...
           */
           rtems_task_wake_after(   tickspsec  );
           rtems_message_queue_delete(   nfsTestRQ  );
           }
           if (   nfsTestAQ  )
           rtems_message_queue_delete(   nfsTestAQ  );
           free(  buf );
           return now;
          }

libfs/src/nfsclient/src/rpcio.c

          /* $Id: rpcio.c,  v 1.14 2010/06/18 09:36:02 ralf Exp $ */
          
          /* RPC multiplexor for a multitasking environment */
          
          /* Author: Till Straumann <strauman@slac.stanford.edu>,   2002 */
          
          /* This code funnels arbitrary task's UDP/RPC requests
           * through one socket to arbitrary servers.
           * The replies are gathered and dispatched to the
           * requestors.
           * One task handles all the sending and receiving
           * work including retries.
           * It is up to the requestor,   however,   to do
           * the XDR encoding of the arguments / decoding
           * of the results (  except for the RPC header which
           * is handled by the daemon ).
           */
          
          /*
           * Authorship
           * ----------
           * This software (  NFS-2 client implementation for RTEMS ) was created by
           * Till Straumann <strauman@slac.stanford.edu>,   2002-2007,  
           * Stanford Linear Accelerator Center,   Stanford University.
           *
           * Acknowledgement of sponsorship
           * ------------------------------
           * The NFS-2 client implementation for RTEMS was produced by
           * the Stanford Linear Accelerator Center,   Stanford University,  
           * under Contract DE-AC03-76SFO0515 with the Department of Energy.
           *
           * Government disclaimer of liability
           * ----------------------------------
           * Neither the United States nor the United States Department of Energy,  
           * nor any of their employees,   makes any warranty,   express or implied,   or
           * assumes any legal liability or responsibility for the accuracy,  
           * completeness,   or usefulness of any data,   apparatus,   product,   or process
           * disclosed,   or represents that its use would not infringe privately owned
           * rights.
           *
           * Stanford disclaimer of liability
           * --------------------------------
           * Stanford University makes no representations or warranties,   express or
           * implied,   nor assumes any liability for the use of this software.
           *
           * Stanford disclaimer of copyright
           * --------------------------------
           * Stanford University,   owner of the copyright,   hereby disclaims its
           * copyright and all other rights in this software. Hence,   anyone may
           * freely use it for any purpose without restriction.
           *
           * Maintenance of notices
           * ----------------------
           * In the interest of clarity regarding the origin and status of this
           * SLAC software,   this and all the preceding Stanford University notices
           * are to remain affixed to any copy or derivative of this software made
           * or distributed by the recipient and are to be affixed to any copy of
           * software made or distributed by the recipient that contains a copy or
           * derivative of this software.
           *
           * ------------------ SLAC Software Notices,   Set 4 OTT.002a,   2004 FEB 03
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <rtems.h>
          #include <rtems/error.h>
          #include <rtems/rtems_bsdnet.h>
          #include <stdlib.h>
          #include <time.h>
          #include <rpc/rpc.h>
          #include <rpc/pmap_prot.h>
          #include <errno.h>
          #include <sys/ioctl.h>
          #include <assert.h>
          #include <stdio.h>
          #include <errno.h>
          #include <string.h>
          #include <netinet/in.h>
          #include <arpa/inet.h>
          
          #include "rpcio.h"
          
          /****************************************************************/
          /* CONFIGURABLE PARAMETERS */
          /****************************************************************/
          
          #define MBUF_RX /* If defined: use mbuf XDR stream for
           * decoding directly out of mbufs
           * Otherwise,   the regular 'recvfrom(   )'
           * interface will be used involving an
           * extra buffer allocation + copy step.
           */
          
          #define MBUF_TX /* If defined: avoid copying data when
           * sending. Instead,   use a wrapper to
           * 'sosend(   )' which will point an MBUF
           * directly to our buffer space.
           * Note that the BSD stack does not copy
           * data when fragmenting packets - it
           * merely uses an mbuf chain pointing
           * into different areas of the data.
           *
           * If undefined,   the regular 'sendto(   )'
           * interface is used.
           */
          
          #undef REJECT_SERVERIP_MISMATCH
           /* If defined,   RPC replies must come from the server
           * that was queried. Eric Norum has reported problems
           * with clustered NFS servers. So we disable this
           * reducing paranoia...
           */
          
          /* daemon task parameters */
          #define RPCIOD_STACK 10000
          #define RPCIOD_PRIO 100 /* *fallback* priority */
          
          /* depth of the message queue for sending
           * RPC requests to the daemon
           */
          #define RPCIOD_QDEPTH 20
          
          /* Maximum retry limit for retransmission */
          #define RPCIOD_RETX_CAP_S 3 /* seconds */
          
          /* Default timeout for RPC calls */
          #define RPCIOD_DEFAULT_TIMEOUT (  &_rpc_default_timeout )
          static struct timeval _rpc_default_timeout = { 10 /* secs */,   0 /* usecs */ };
          
          /* how many times should we try to resend a failed
           * transaction with refreshed AUTHs
           */
          #define RPCIOD_REFRESH 2
          
          /* Events we are using; the RPC_EVENT
           * MUST NOT be used by any application
           * thread doing RPC IO (  e.g. NFS )
           */
          #define RTEMS_RPC_EVENT RTEMS_EVENT_30 /* THE event used by RPCIO. Every task doing
           * RPC IO will receive this - hence it is
           * RESERVED
           */
          #define RPCIOD_RX_EVENT RTEMS_EVENT_1 /* Events the RPCIOD is using/waiting for */
          #define RPCIOD_TX_EVENT RTEMS_EVENT_2
          #define RPCIOD_KILL_EVENT RTEMS_EVENT_3 /* send to the daemon to kill it */
          
          #define LD_XACT_HASH 8 /* ld of the size of the transaction hash table */
          
          
          /* Debugging Flags */
          
          /* NOTE: defining DEBUG 0 leaves some 'assert(   )' paranoia checks
           * but produces no output
           */
          
          #define DEBUG_TRACE_XACT (  1<<0 )
          #define DEBUG_EVENTS (  1<<1 )
          #define DEBUG_MALLOC (  1<<2 )
          #define DEBUG_TIMEOUT (  1<<3 )
          #define DEBUG_PACKLOSS (  1<<4 ) /* This introduces random,   artificial packet losses to test retransmission */
          
          #define DEBUG_PACKLOSS_FRACT (  0xffffffff/10 )
          
          /* USE PARENTHESIS WHEN 'or'ing MULTIPLE FLAGS: (  DEBUG_XX | DEBUG_YY ) */
          #define DEBUG (  0 )
          
          /****************************************************************/
          /* END OF CONFIGURABLE SECTION */
          /****************************************************************/
          
          /* prevent rollover of our timers by readjusting the epoch on the fly */
          #if (  DEBUG ) & DEBUG_TIMEOUT
          #define RPCIOD_EPOCH_SECS 10
          #else
          #define RPCIOD_EPOCH_SECS 10000
          #endif
          
          #ifdef DEBUG
          #define ASSERT(  arg ) assert(  arg )
          #else
          #define ASSERT(  arg ) if (  arg )
          #endif
          
          /****************************************************************/
          /* MACROS */
          /****************************************************************/
          
          
          #define XACT_HASHS (  1<<(  LD_XACT_HASH ) ) /* the hash table size derived from the ld */
          #define XACT_HASH_MSK (  (  XACT_HASHS )-1 ) /* mask to extract the hash index from a RPC-XID */
          
          
          #define MU_LOCK(  mutex ) do { \
           assert(   \
           RTEMS_SUCCESSFUL == \
           rtems_semaphore_obtain(   \
           (  mutex ),   \
           RTEMS_WAIT,   \
           RTEMS_NO_TIMEOUT \
            )  ); \
           } while(  0 )
          
          #define MU_UNLOCK(  mutex ) do { \
           assert(   \
           RTEMS_SUCCESSFUL == \
           rtems_semaphore_release(   \
           (  mutex ) \
            )  ); \
           } while(  0 )
          
          #define MU_CREAT(  pmutex ) do { \
           assert(   \
           RTEMS_SUCCESSFUL == \
           rtems_semaphore_create(   \
           rtems_build_name(   \
           'R',  'P',  'C',  'l' \
            ),   \
           1,   \
           MUTEX_ATTRIBUTES,   \
           0,   \
           (  pmutex ) )  ); \
           } while (  0 )
          
          
          #define MU_DESTROY(  mutex ) do { \
           assert(   \
           RTEMS_SUCCESSFUL == \
           rtems_semaphore_delete(   \
           mutex \
            )  ); \
           } while (  0 )
          
          #define MUTEX_ATTRIBUTES (  RTEMS_LOCAL | \
           RTEMS_PRIORITY | \
           RTEMS_INHERIT_PRIORITY | \
           RTEMS_BINARY_SEMAPHORE )
          
          #define FIRST_ATTEMPT 0x88888888 /* some time that is never reached */
          
          /****************************************************************/
          /* TYPE DEFINITIONS */
          /****************************************************************/
          
          typedef rtems_interval TimeoutT;
          
          /* 100000th implementation of a doubly linked list;
           * since only one thread is looking at these,  
           * we need no locking
           */
          typedef struct ListNodeRec_ {
           struct ListNodeRec_ *next,   *prev;
          } ListNodeRec,   *ListNode;
          
          
          /* Structure representing an RPC server */
     261  typedef struct RpcUdpServerRec_ {
           RpcUdpServer next; /* linked list of all servers; protected by hlock */
           union {
           struct sockaddr_in sin;
           struct sockaddr sa;
           } addr;
           AUTH *auth;
           rtems_id authlock; /* must MUTEX the auth object - it's not clear
           * what is better:
           * 1 having one (  MUTEXed ) auth per server
           * who is shared among all transactions
     272   * using that server
           * 2 maintaining an AUTH per transaction
     274   * (  there are then other options: manage
           * XACT pools on a per-server basis instead
           * of associating a server with a XACT when
           * sending )
           * experience will show if the current (  1 )
           * approach has to be changed.
           */
           TimeoutT retry_period; /* dynamically adjusted retry period
           * (  based on packet roundtrip time )
           */
           /* STATISTICS */
           unsigned long retrans; /* how many retries were issued by this server */
           unsigned long requests; /* how many requests have been sent */
           unsigned long timeouts; /* how many requests have timed out */
           unsigned long errors; /* how many errors have occurred (  other than timeouts ) */
           char name[20]; /* server's address in IP 'dot' notation */
          } RpcUdpServerRec;
          
          typedef union RpcBufU_ {
           uint32_t xid;
           char buf[1];
          } RpcBufU,   *RpcBuf;
          
          /* RX Buffer implementation; this is either
           * an MBUF chain (  MBUF_RX configuration )
           * or a buffer allocated from the heap
           * where recvfrom copies the (  encoded ) reply
           * to. The XDR routines the copy/decode
           * it into the user's data structures.
           */
          #ifdef MBUF_RX
          typedef struct mbuf * RxBuf; /* an MBUF chain */
          static void bufFree(  struct mbuf **m );
          #define XID(  ibuf ) (  *(  mtod(  (  ibuf ),   u_long * ) ) )
          extern void xdrmbuf_create(  XDR *,   struct mbuf *,   enum xdr_op );
          #else
          typedef RpcBuf RxBuf;
          #define bufFree(  b ) do { MY_FREE(  *(  b ) ); *(  b )=0; } while(  0 )
          #define XID(  ibuf ) (  (  ibuf )->xid )
          #endif
          
          /* A RPC 'transaction' consisting
           * of server and requestor information,  
           * buffer space and an XDR object
           * (  for encoding arguments ).
           */
          typedef struct RpcUdpXactRec_ {
           ListNodeRec node; /* so we can put XACTs on a list */
           RpcUdpServer server; /* server this XACT goes to */
           long lifetime; /* during the lifetime,   retry attempts are made */
           long tolive; /* lifetime timer */
           struct rpc_err status; /* RPC reply error status */
           long age; /* age info; needed to manage retransmission */
           long trip; /* record round trip time in ticks */
           rtems_id requestor; /* the task waiting for this XACT to complete */
           RpcUdpXactPool pool; /* if this XACT belong to a pool,   this is it */
           XDR xdrs; /* argument encoder stream */
           int xdrpos; /* stream position after the (  permanent ) header */
     332   xdrproc_t xres; /* reply decoder proc - TODO needn't be here */
           caddr_t pres; /* reply decoded obj - TODO needn't be here */
          #ifndef MBUF_RX
     335   int ibufsize; /* size of the ibuf (  bytes ) */
          #endif
          #ifdef MBUF_TX
           int refcnt; /* mbuf external storage reference count */
     339  #endif
           int obufsize; /* size of the obuf (  bytes ) */
           RxBuf ibuf; /* pointer to input buffer assigned by daemon */
           RpcBufU obuf; /* output buffer (  encoded args ) APPENDED HERE */
          } RpcUdpXactRec;
          
          typedef struct RpcUdpXactPoolRec_ {
           rtems_id box;
           int prog;
     348   int version;
     349   int xactSize;
          } RpcUdpXactPoolRec;
          
          /* a global hash table where all 'living' transaction
           * objects are registered.
           * A number of bits in a transaction's XID maps 1:1 to
           * an index in this table. Hence,   the XACT matching
           * an RPC/UDP reply packet can quickly be found
           * The size of this table imposes a hard limit on the
           * number of all created transactions in the system.
           */
          static RpcUdpXact xactHashTbl[XACT_HASHS]={0};
          static u_long xidUpper [XACT_HASHS]={0};
          static unsigned xidHashSeed = 0 ;
          
          /* forward declarations */
          static RpcUdpXact
          sockRcv(  void );
          
          static void
          rpcio_daemon(  rtems_task_argument );
          
          #ifdef MBUF_TX
          ssize_t
          sendto_nocpy (  
           int s,  
           const void *buf,   size_t buflen,  
           int flags,  
           const struct sockaddr *toaddr,   int tolen,  
           void *closure,  
     379   void (  *freeproc )(  caddr_t,   u_int ),  
           void (  *refproc )(  caddr_t,   u_int )
           );
          static void paranoia_free(  caddr_t closure,   u_int size );
          static void paranoia_ref (  caddr_t closure,   u_int size );
          #define SENDTO sendto_nocpy
          #else
          #define SENDTO sendto
          #endif
          
          static RpcUdpServer rpcUdpServers = 0; /* linked list of all servers; protected by llock */
          
          static int ourSock = -1; /* the socket we are using for communication */
     392  static rtems_id rpciod = 0; /* task id of the RPC daemon */
          static rtems_id msgQ = 0; /* message queue where the daemon picks up
           * requests
           */
          #ifndef NDEBUG
          static rtems_id llock = 0; /* MUTEX protecting the server list */
          static rtems_id hlock = 0; /* MUTEX protecting the hash table and the list of servers */
          #endif
          static rtems_id fini = 0; /* a synchronization semaphore we use during
           * module cleanup / driver unloading
           */
          static rtems_interval ticksPerSec; /* cached system clock rate (  WHO IS ASSUMED NOT
           * TO CHANGE )
           */
     406  
          rtems_task_priority rpciodPriority = 0;
          
          #if (  DEBUG ) & DEBUG_MALLOC
          /* malloc wrappers for debugging */
          static int nibufs = 0;
          
          static inline void *MY_MALLOC(  int s )
          {
           if (  s ) {
           void *rval;
           MU_LOCK(  hlock );
           assert(  nibufs++ < 2000 );
           MU_UNLOCK(  hlock );
           assert(  (  rval = malloc(  s ) ) != 0 );
           return rval;
     422   }
           return 0;
          }
          
          static inline void *MY_CALLOC(  int n,   int s )
          {
           if (  s ) {
           void *rval;
           MU_LOCK(  hlock );
           assert(  nibufs++ < 2000 );
           MU_UNLOCK(  hlock );
     433   assert(  (  rval = calloc(  n,  s ) ) != 0 );
           return rval;
           }
           return 0;
          }
          
          
          static inline void MY_FREE(  void *p )
          {
           if (  p ) {
     443   MU_LOCK(  hlock );
           nibufs--;
           MU_UNLOCK(  hlock );
           free(  p );
           }
          }
          #else
          #define MY_MALLOC malloc
          #define MY_CALLOC calloc
          #define MY_FREE free
          #endif
          
          static inline bool_t
          locked_marshal(  RpcUdpServer s,   XDR *xdrs )
          {
          bool_t rval;
           MU_LOCK(  s->authlock );
           rval = AUTH_MARSHALL(  s->auth,   xdrs );
           MU_UNLOCK(  s->authlock );
           return rval;
          }
          
          /* Locked operations on a server's auth object */
          static inline bool_t
          locked_validate(  RpcUdpServer s,   struct opaque_auth *v )
          {
          bool_t rval;
           MU_LOCK(  s->authlock );
           rval = AUTH_VALIDATE(  s->auth,   v );
           MU_UNLOCK(  s->authlock );
           return rval;
          }
          
          static inline bool_t
          locked_refresh(  RpcUdpServer s )
          {
          bool_t rval;
           MU_LOCK(  s->authlock );
           rval = AUTH_REFRESH(  s->auth );
           MU_UNLOCK(  s->authlock );
           return rval;
          }
          
          /* Create a server object
           *
           */
          enum clnt_stat
          rpcUdpServerCreate(  
           struct sockaddr_in *paddr,  
           rpcprog_t prog,  
           rpcvers_t vers,  
           u_long uid,  
           u_long gid,  
           RpcUdpServer *psrv
            )
          {
          RpcUdpServer rval;
          u_short port;
          char hname[MAX_MACHINE_NAME + 1];
          int theuid,   thegid;
          int thegids[NGRPS];
          gid_t gids[NGROUPS];
          int len,  i;
          AUTH *auth;
          enum clnt_stat pmap_err;
          struct pmap pmaparg;
          
           if (   gethostname(  hname,   MAX_MACHINE_NAME )  ) {
           fprintf(  stderr,  
           "RPCIO - error: I have no hostname ?? (  %s )\n",  
           strerror(  errno ) );
           return RPC_UNKNOWNHOST;
           }
          
           if (   (  len = getgroups(  NGROUPS,   gids ) < 0  )  ) {
           fprintf(  stderr,  
           "RPCIO - error: I unable to get group ids (  %s )\n",  
           strerror(  errno ) );
           return RPC_FAILED;
           }
          
           if (   len > NGRPS  )
           len = NGRPS;
          
           for (  i=0; i<len; i++ )
           thegids[i] = (  int )gids[i];
          
           theuid = (  int ) (  (  RPCIOD_DEFAULT_ID == uid ) ? geteuid(   ) : uid );
           thegid = (  int ) (  (  RPCIOD_DEFAULT_ID == gid ) ? getegid(   ) : gid );
          
           if (   !(  auth = authunix_create(  hname,   theuid,   thegid,   len,   thegids ) )  ) {
           fprintf(  stderr,  
           "RPCIO - error: unable to create RPC AUTH\n" );
           return RPC_FAILED;
           }
          
           /* if they specified no port try to ask the portmapper */
           if (  !paddr->sin_port ) {
          
           paddr->sin_port = htons(  PMAPPORT );
          
           pmaparg.pm_prog = prog;
           pmaparg.pm_vers = vers;
           pmaparg.pm_prot = IPPROTO_UDP;
           pmaparg.pm_port = 0; /* not needed or used */
          
          
           /* dont use non-reentrant pmap_getport ! */
          
           pmap_err = rpcUdpCallRp(  
           paddr,  
           PMAPPROG,  
           PMAPVERS,  
           PMAPPROC_GETPORT,  
           xdr_pmap,  
           &pmaparg,  
           xdr_u_short,  
           &port,  
           uid,  
           gid,  
           0 );
          
           if (   RPC_SUCCESS != pmap_err  ) {
           paddr->sin_port = 0;
           return pmap_err;
           }
          
           paddr->sin_port = htons(  port );
           }
          
           if (  0==paddr->sin_port ) {
           return RPC_PROGNOTREGISTERED;
           }
          
           rval = (  RpcUdpServer )MY_MALLOC(  sizeof(  *rval ) );
           memset(  rval,   0,   sizeof(  *rval ) );
          
           if (  !inet_ntop(  AF_INET,   &paddr->sin_addr,   rval->name,   sizeof(  rval->name ) ) )
           sprintf(  rval->name,  "?.?.?.?" );
           rval->addr.sin = *paddr;
          
           /* start with a long retransmission interval - it
           * will be adapted dynamically
           */
           rval->retry_period = RPCIOD_RETX_CAP_S * ticksPerSec;
          
           rval->auth = auth;
          
           MU_CREAT(   &rval->authlock  );
          
           /* link into list */
           MU_LOCK(   llock  );
           rval->next = rpcUdpServers;
           rpcUdpServers = rval;
           MU_UNLOCK(   llock  );
          
           *psrv = rval;
           return RPC_SUCCESS;
          }
          
          void
          rpcUdpServerDestroy(  RpcUdpServer s )
          {
          RpcUdpServer prev;
           if (  !s )
           return;
           /* we should probably verify (  but how? ) that nobody
           * (  at least: no outstanding XACTs ) is using this
           * server;
           */
          
           /* remove from server list */
           MU_LOCK(  llock );
           prev = rpcUdpServers;
           if (   s == prev  ) {
           rpcUdpServers = s->next;
           } else {
           for (   ; prev ; prev = prev->next ) {
           if (  prev->next == s ) {
           prev->next = s->next;
           break;
           }
           }
           }
           MU_UNLOCK(  llock );
          
           /* MUST have found it */
           assert(  prev );
          
           auth_destroy(  s->auth );
          
           MU_DESTROY(  s->authlock );
           MY_FREE(  s );
          }
          
          int
          rpcUdpStats(  FILE *f )
          {
          RpcUdpServer s;
          
           if (  !f ) f = stdout;
          
           fprintf(  f,  "RPCIOD statistics:\n" );
          
           MU_LOCK(  llock );
           for (  s = rpcUdpServers; s; s=s->next ) {
           fprintf(  f,  "\nServer -- %s:\n",   s->name );
           fprintf(  f,  " requests sent: %10ld,   retransmitted: %10ld\n",  
           s->requests,   s->retrans );
           fprintf(  f,  " timed out: %10ld,   send errors: %10ld\n",  
           s->timeouts,   s->errors );
           fprintf(  f,  " current retransmission interval: %dms\n",  
           (  unsigned )(  s->retry_period * 1000 / ticksPerSec )  );
           }
           MU_UNLOCK(  llock );
          
           return 0;
          }
          
          RpcUdpXact
          rpcUdpXactCreate(  
           u_long program,  
           u_long version,  
           u_long size
            )
          {
          RpcUdpXact rval=0;
          struct rpc_msg header;
          register int i,  j;
          
           if (  !size )
           size = UDPMSGSIZE;
           /* word align */
           size = (  size + 3 ) & ~3;
          
           rval = (  RpcUdpXact )MY_CALLOC(  1,  sizeof(  *rval ) - sizeof(  rval->obuf ) + size );
          
           if (  rval ) {
          
           header.rm_xid = 0;
           header.rm_direction = CALL;
           header.rm_call.cb_rpcvers = RPC_MSG_VERSION;
           header.rm_call.cb_prog = program;
           header.rm_call.cb_vers = version;
           xdrmem_create(  &(  rval->xdrs ),   rval->obuf.buf,   size,   XDR_ENCODE );
          
           if (  !xdr_callhdr(  &(  rval->xdrs ),   &header ) ) {
           MY_FREE(  rval );
           return 0;
           }
           /* pick a free table slot and initialize the XID */
           rval->obuf.xid = time(  0 ) ^ (  uintptr_t )rval;
           MU_LOCK(  hlock );
           rval->obuf.xid = (  xidHashSeed++ ^ (  (  uintptr_t )rval>>10 ) ) & XACT_HASH_MSK;
           i=j=(  rval->obuf.xid & XACT_HASH_MSK );
           if (  msgQ ) {
           /* if there's no message queue,   refuse to
           * give them transactions; we might be in the process to
           * go away...
           */
           do {
           i=(  i+1 ) & XACT_HASH_MSK; /* cheap modulo */
           if (  !xactHashTbl[i] ) {
          #if (  DEBUG ) & DEBUG_TRACE_XACT
           fprintf(  stderr,  "RPCIO: entering index %i,   val %x\n",  i,  rval );
          #endif
           xactHashTbl[i]=rval;
           j=-1;
           break;
           }
           } while (  i!=j );
           }
           MU_UNLOCK(  hlock );
           if (  i==j ) {
           XDR_DESTROY(  &rval->xdrs );
           MY_FREE(  rval );
           return 0;
           }
           rval->obuf.xid = xidUpper[i] | i;
           rval->xdrpos = XDR_GETPOS(  &(  rval->xdrs ) );
           rval->obufsize = size;
           }
           return rval;
          }
          
          void
          rpcUdpXactDestroy(  RpcUdpXact xact )
          {
          int i = xact->obuf.xid & XACT_HASH_MSK;
          
          #if (  DEBUG ) & DEBUG_TRACE_XACT
           fprintf(  stderr,  "RPCIO: removing index %i,   val %x\n",  i,  xact );
          #endif
          
           ASSERT(   xactHashTbl[i]==xact  );
          
           MU_LOCK(  hlock );
           xactHashTbl[i]=0;
           /* remember XID we used last time so we can avoid
           * reusing the same one (  incremented by rpcUdpSend routine )
           */
           xidUpper[i] = xact->obuf.xid & ~XACT_HASH_MSK;
           MU_UNLOCK(  hlock );
          
           bufFree(  &xact->ibuf );
          
           XDR_DESTROY(  &xact->xdrs );
           MY_FREE(  xact );
          }
          
          
          
          /* Send a transaction,   i.e. enqueue it to the
           * RPC daemon who will actually send it.
           */
          enum clnt_stat
          rpcUdpSend(  
           RpcUdpXact xact,  
           RpcUdpServer srvr,  
           struct timeval *timeout,  
           u_long proc,  
           xdrproc_t xres,   caddr_t pres,  
           xdrproc_t xargs,   caddr_t pargs,  
           ...
            )
          {
          register XDR *xdrs;
          unsigned long ms;
          va_list ap;
          
           va_start(  ap,  pargs );
          
           if (  !timeout )
           timeout = RPCIOD_DEFAULT_TIMEOUT;
          
           ms = 1000 * timeout->tv_sec + timeout->tv_usec/1000;
          
           /* round lifetime to closest # of ticks */
           xact->lifetime = (  ms * ticksPerSec + 500 ) / 1000;
           if (   0 == xact->lifetime  )
           xact->lifetime = 1;
          
          #if (  DEBUG ) & DEBUG_TIMEOUT
           {
           static int once=0;
           if (  !once++ ) {
           fprintf(  stderr,  
           "Initial lifetime: %i (  ticks )\n",  
           xact->lifetime );
           }
           }
          #endif
          
           xact->tolive = xact->lifetime;
          
           xact->xres = xres;
           xact->pres = pres;
           xact->server = srvr;
          
           xdrs = &xact->xdrs;
           xdrs->x_op = XDR_ENCODE;
           /* increment transaction ID */
           xact->obuf.xid += XACT_HASHS;
           XDR_SETPOS(  xdrs,   xact->xdrpos );
           if (   !XDR_PUTLONG(  xdrs,  (  long* )&proc ) || !locked_marshal(  srvr,   xdrs ) ||
           !xargs(  xdrs,   pargs )  ) {
           va_end(  ap );
           return(  xact->status.re_status=RPC_CANTENCODEARGS );
           }
           while (  (  xargs=va_arg(  ap,  xdrproc_t ) ) ) {
           if (  !xargs(  xdrs,   va_arg(  ap,  caddr_t ) ) )
           va_end(  ap );
           return(  xact->status.re_status=RPC_CANTENCODEARGS );
           }
          
           va_end(  ap );
          
           rtems_task_ident(  RTEMS_SELF,   RTEMS_WHO_AM_I,   &xact->requestor );
           if (   rtems_message_queue_send(   msgQ,   &xact,   sizeof(  xact ) )  ) {
           return RPC_CANTSEND;
           }
           /* wakeup the rpciod */
           ASSERT(   RTEMS_SUCCESSFUL==rtems_event_send(  rpciod,   RPCIOD_TX_EVENT )  );
          
           return RPC_SUCCESS;
          }
          
          /* Block for the RPC reply to an outstanding
           * transaction.
           * The caller is woken by the RPC daemon either
           * upon reception of the reply or on timeout.
           */
          enum clnt_stat
          rpcUdpRcv(  RpcUdpXact xact )
          {
          int refresh;
          XDR reply_xdrs;
          struct rpc_msg reply_msg;
          rtems_status_code status;
          rtems_event_set gotEvents;
          
           refresh = 0;
          
           do {
          
           /* block for the reply */
           status = rtems_event_receive(  
           RTEMS_RPC_EVENT,  
           RTEMS_WAIT | RTEMS_EVENT_ANY,  
           RTEMS_NO_TIMEOUT,  
           &gotEvents );
           ASSERT(   status == RTEMS_SUCCESSFUL  );
          
           if (  xact->status.re_status ) {
          #ifdef MBUF_RX
           /* add paranoia */
           ASSERT(   !xact->ibuf  );
          #endif
           return xact->status.re_status;
           }
          
          #ifdef MBUF_RX
           xdrmbuf_create(  &reply_xdrs,   xact->ibuf,   XDR_DECODE );
          #else
           xdrmem_create(  &reply_xdrs,   xact->ibuf->buf,   xact->ibufsize,   XDR_DECODE );
          #endif
          
           reply_msg.acpted_rply.ar_verf = _null_auth;
           reply_msg.acpted_rply.ar_results.where = xact->pres;
           reply_msg.acpted_rply.ar_results.proc = xact->xres;
          
           if (  xdr_replymsg(  &reply_xdrs,   &reply_msg ) ) {
           /* OK */
           _seterr_reply(  &reply_msg,   &xact->status );
           if (  RPC_SUCCESS == xact->status.re_status ) {
           if (   !locked_validate(  xact->server,  
           &reply_msg.acpted_rply.ar_verf )  ) {
           xact->status.re_status = RPC_AUTHERROR;
           xact->status.re_why = AUTH_INVALIDRESP;
           }
           if (  reply_msg.acpted_rply.ar_verf.oa_base ) {
           reply_xdrs.x_op = XDR_FREE;
           xdr_opaque_auth(  &reply_xdrs,   &reply_msg.acpted_rply.ar_verf );
           }
           refresh = 0;
           } else {
           /* should we try to refresh our credentials ? */
           if (   !refresh  ) {
           /* had never tried before */
           refresh = RPCIOD_REFRESH;
           }
           }
           } else {
           reply_xdrs.x_op = XDR_FREE;
           xdr_replymsg(  &reply_xdrs,   &reply_msg );
           xact->status.re_status = RPC_CANTDECODERES;
           }
           XDR_DESTROY(  &reply_xdrs );
          
           bufFree(  &xact->ibuf );
          
          #ifndef MBUF_RX
           xact->ibufsize = 0;
          #endif
          
           if (  refresh && locked_refresh(  xact->server ) ) {
           rtems_task_ident(  RTEMS_SELF,   RTEMS_WHO_AM_I,   &xact->requestor );
           if (   rtems_message_queue_send(  msgQ,   &xact,   sizeof(  xact ) )  ) {
           return RPC_CANTSEND;
           }
           /* wakeup the rpciod */
           fprintf(  stderr,  "RPCIO INFO: refreshing my AUTH\n" );
           ASSERT(   RTEMS_SUCCESSFUL==rtems_event_send(  rpciod,   RPCIOD_TX_EVENT )  );
           }
          
           } while (   0 && refresh-- > 0  );
          
           return xact->status.re_status;
          }
          
          
          /* On RTEMS,   I'm told to avoid select(   ); this seems to
           * be more efficient
           */
          static void
          rxWakeupCB(  struct socket *sock,   void *arg )
          {
           rtems_id *rpciod = (  rtems_id* ) arg;
           rtems_event_send(  *rpciod,   RPCIOD_RX_EVENT );
          }
          
          int
          rpcUdpInit(  void )
          {
          int s;
          rtems_status_code status;
          int noblock = 1;
          struct sockwakeup wkup;
          
           if (  ourSock < 0 ) {
           fprintf(  stderr,  "RTEMS-RPCIOD $Release$,   " \
           "Till Straumann,   Stanford/SLAC/SSRL 2002,   " \
           "See LICENSE file for licensing info.\n" );
          
           ourSock=socket(  AF_INET,   SOCK_DGRAM,   IPPROTO_UDP );
           if (  ourSock>=0 ) {
           bindresvport(  ourSock,  (  struct sockaddr_in* )0 );
           s = ioctl(  ourSock,   FIONBIO,   (  char* )&noblock );
           assert(   s == 0  );
           /* assume nobody tampers with the clock !! */
           ticksPerSec = rtems_clock_get_ticks_per_second(   );
           MU_CREAT(   &hlock  );
           MU_CREAT(   &llock  );
          
           if (   !rpciodPriority  ) {
           /* use configured networking priority */
           if (   ! (  rpciodPriority = rtems_bsdnet_config.network_task_priority )  )
           rpciodPriority = RPCIOD_PRIO; /* fallback value */
           }
          
           status = rtems_task_create(  
           rtems_build_name(  'R',  'P',  'C',  'd' ),  
           rpciodPriority,  
           RPCIOD_STACK,  
           RTEMS_DEFAULT_MODES,  
           /* fprintf saves/restores FP registers on PPC :-(   */
           RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,  
           &rpciod );
           assert(   status == RTEMS_SUCCESSFUL  );
          
           wkup.sw_pfn = rxWakeupCB;
           wkup.sw_arg = &rpciod;
           assert(   0==setsockopt(  ourSock,   SOL_SOCKET,   SO_RCVWAKEUP,   &wkup,   sizeof(  wkup ) )  );
           status = rtems_message_queue_create(  
           rtems_build_name(  'R',  'P',  'C',  'q' ),  
           RPCIOD_QDEPTH,  
           sizeof(  RpcUdpXact ),  
           RTEMS_DEFAULT_ATTRIBUTES,  
           &msgQ );
           assert(   status == RTEMS_SUCCESSFUL  );
           status = rtems_task_start(   rpciod,   rpcio_daemon,   0  );
           assert(   status == RTEMS_SUCCESSFUL  );
          
           } else {
           return -1;
           }
           }
           return 0;
          }
          
          int
          rpcUdpCleanup(  void )
          {
           rtems_semaphore_create(  
           rtems_build_name(  'R',  'P',  'C',  'f' ),  
           0,  
           RTEMS_DEFAULT_ATTRIBUTES,  
           0,  
           &fini );
           rtems_event_send(  rpciod,   RPCIOD_KILL_EVENT );
           /* synchronize with daemon */
           rtems_semaphore_obtain(  fini,   RTEMS_WAIT,   5*ticksPerSec );
           /* if the message queue is still there,   something went wrong */
           if (  !msgQ ) {
           rtems_task_delete(  rpciod );
           }
           rtems_semaphore_delete(  fini );
           return (  msgQ !=0 );
          }
          
          /* Another API - simpler but less efficient.
           * For each RPCall,   a server and a Xact
           * are created and destroyed on the fly.
           *
           * This should be used for infrequent calls
           * (  e.g. a NFS mount request ).
           *
           * This is roughly compatible with the original
           * clnt_call(   ) etc. API - but it uses our
           * daemon and is fully reentrant.
           */
          enum clnt_stat
          rpcUdpClntCreate(  
           struct sockaddr_in *psaddr,  
           rpcprog_t prog,  
           rpcvers_t vers,  
           u_long uid,  
           u_long gid,  
           RpcUdpClnt *pclnt
           )
          {
          RpcUdpXact x;
          RpcUdpServer s;
          enum clnt_stat err;
          
           if (   RPC_SUCCESS != (  err=rpcUdpServerCreate(  psaddr,   prog,   vers,   uid,   gid,   &s ) )  )
           return err;
          
           if (   !(  x=rpcUdpXactCreate(  prog,   vers,   UDPMSGSIZE ) )  ) {
           rpcUdpServerDestroy(  s );
           return RPC_FAILED;
           }
           /* TODO: could maintain a server cache */
          
           x->server = s;
          
           *pclnt = x;
          
           return RPC_SUCCESS;
          }
          
          void
          rpcUdpClntDestroy(  RpcUdpClnt xact )
          {
           rpcUdpServerDestroy(  xact->server );
           rpcUdpXactDestroy(  xact );
          }
          
          enum clnt_stat
          rpcUdpClntCall(  
           RpcUdpClnt xact,  
           u_long proc,  
           XdrProcT xargs,  
           CaddrT pargs,  
           XdrProcT xres,  
           CaddrT pres,  
           struct timeval *timeout
            )
          {
          enum clnt_stat stat;
          
           if (   (  stat = rpcUdpSend(  xact,   xact->server,   timeout,   proc,  
           xres,   pres,  
           xargs,   pargs,  
           0 ) )  ) {
           fprintf(  stderr,  "RPCIO Send failed: %i\n",  stat );
           return stat;
           }
           return rpcUdpRcv(  xact );
          }
          
          /* a yet simpler interface */
          enum clnt_stat
          rpcUdpCallRp(  
           struct sockaddr_in *psrvr,  
           u_long prog,  
           u_long vers,  
           u_long proc,  
           XdrProcT xargs,  
           CaddrT pargs,  
           XdrProcT xres,  
           CaddrT pres,  
           u_long uid,   /* RPCIO_DEFAULT_ID picks default */
           u_long gid,   /* RPCIO_DEFAULT_ID picks default */
           struct timeval *timeout /* NULL picks default */
           )
          {
          RpcUdpClnt clp;
          enum clnt_stat stat;
          
           stat = rpcUdpClntCreate(  
           psrvr,  
           prog,  
           vers,  
           uid,  
           gid,  
           &clp );
          
           if (   RPC_SUCCESS != stat  )
           return stat;
          
           stat = rpcUdpClntCall(  
           clp,  
           proc,  
           xargs,   pargs,  
           xres,   pres,  
           timeout );
          
           rpcUdpClntDestroy(  clp );
          
           return stat;
          }
          
          /* linked list primitives */
          static void
          nodeXtract(  ListNode n )
          {
           if (  n->prev )
           n->prev->next = n->next;
           if (  n->next )
           n->next->prev = n->prev;
           n->next = n->prev = 0;
          }
          
          static void
          nodeAppend(  ListNode l,   ListNode n )
          {
           if (   (  n->next = l->next )  )
           n->next->prev = n;
           l->next = n;
           n->prev = l;
          
          }
          
          /* this code does the work */
          static void
          rpcio_daemon(  rtems_task_argument arg )
          {
          rtems_status_code stat;
          RpcUdpXact xact;
          RpcUdpServer srv;
          rtems_interval next_retrans,   then,   unow;
          long now; /* need to do signed comparison with age! */
          rtems_event_set events;
          ListNode newList;
          size_t size;
          rtems_id q = 0;
          ListNodeRec listHead = {0,   0};
          unsigned long epoch = RPCIOD_EPOCH_SECS * ticksPerSec;
          unsigned long max_period = RPCIOD_RETX_CAP_S * ticksPerSec;
          rtems_status_code status;
          
          
           then = rtems_clock_get_ticks_since_boot(   );
          
           for (  next_retrans = epoch;; ) {
          
           if (   RTEMS_SUCCESSFUL !=
           (  stat = rtems_event_receive(  
           RPCIOD_RX_EVENT | RPCIOD_TX_EVENT | RPCIOD_KILL_EVENT,  
           RTEMS_WAIT | RTEMS_EVENT_ANY,  
           next_retrans,  
           &events ) )  ) {
           ASSERT(   RTEMS_TIMEOUT == stat  );
           events = 0;
           }
          
           if (  events & RPCIOD_KILL_EVENT ) {
           int i;
          
          #if (  DEBUG ) & DEBUG_EVENTS
           fprintf(  stderr,  "RPCIO: got KILL event\n" );
          #endif
          
           MU_LOCK(  hlock );
           for (  i=XACT_HASHS-1; i>=0; i-- ) {
           if (  xactHashTbl[i] ) {
           break;
           }
           }
           if (  i<0 ) {
           /* prevent them from creating and enqueueing more messages */
           q=msgQ;
           /* messages queued after we executed this assignment will fail */
           msgQ=0;
           }
           MU_UNLOCK(  hlock );
           if (  i>=0 ) {
           fprintf(  stderr,  "RPCIO There are still transactions circulating; I refuse to go away\n" );
           fprintf(  stderr,  "(  1st in slot %i )\n",  i );
           rtems_semaphore_release(  fini );
           } else {
           break;
           }
           }
          
           unow = rtems_clock_get_ticks_since_boot(   );
          
           /* measure everything relative to then to protect against
           * rollover
           */
           now = unow - then;
          
           /* NOTE: we don't lock the hash table while we are operating
           * on transactions; the paradigm is that we 'own' a particular
           * transaction (  and hence it's hash table slot ) from the
           * time the xact was put into the message queue until we
           * wake up the requestor.
           */
          
           if (  RPCIOD_RX_EVENT & events ) {
          
          #if (  DEBUG ) & DEBUG_EVENTS
           fprintf(  stderr,  "RPCIO: got RX event\n" );
          #endif
          
           while (  (  xact=sockRcv(   ) ) ) {
          
           /* extract from the retransmission list */
           nodeXtract(  &xact->node );
          
           /* change the ID - there might already be
           * a retransmission on the way. When it's
           * reply arrives we must not find it's ID
           * in the hashtable
           */
           xact->obuf.xid += XACT_HASHS;
          
           xact->status.re_status = RPC_SUCCESS;
          
           /* calculate roundtrip ticks */
           xact->trip = now - xact->trip;
          
           srv = xact->server;
          
           /* adjust the server's retry period */
           {
           register TimeoutT rtry = srv->retry_period;
           register TimeoutT trip = xact->trip;
          
           ASSERT(   trip >= 0  );
          
           if (   0==trip  )
           trip = 1;
          
           /* retry_new = 0.75*retry_old + 0.25 * 8 * roundrip */
           rtry = (  3*rtry + (  trip << 3 ) ) >> 2;
          
           if (   rtry > max_period  )
           rtry = max_period;
          
           srv->retry_period = rtry;
           }
          
           /* wakeup requestor */
           rtems_event_send(  xact->requestor,   RTEMS_RPC_EVENT );
           }
           }
          
           if (  RPCIOD_TX_EVENT & events ) {
          
          #if (  DEBUG ) & DEBUG_EVENTS
           fprintf(  stderr,  "RPCIO: got TX event\n" );
          #endif
          
           while (  RTEMS_SUCCESSFUL == rtems_message_queue_receive(  
           msgQ,  
           &xact,  
           &size,  
           RTEMS_NO_WAIT,  
           RTEMS_NO_TIMEOUT ) ) {
           /* put to the head of timeout q */
           nodeAppend(  &listHead,   &xact->node );
          
           xact->age = now;
           xact->trip = FIRST_ATTEMPT;
           }
           }
          
          
           /* work the timeout q */
           newList = 0;
           for (   xact=(  RpcUdpXact )listHead.next;
           xact && xact->age <= now;
           xact=(  RpcUdpXact )listHead.next  ) {
          
           /* extract from the list */
           nodeXtract(  &xact->node );
          
           srv = xact->server;
          
           if (  xact->tolive < 0 ) {
           /* this one timed out */
           xact->status.re_errno = ETIMEDOUT;
           xact->status.re_status = RPC_TIMEDOUT;
          
           srv->timeouts++;
          
           /* Change the ID - there might still be
           * a reply on the way. When it arrives we
           * must not find it's ID in the hash table
           *
           * Thanks to Steven Johnson for hunting this
           * one down.
           */
           xact->obuf.xid += XACT_HASHS;
          
          #if (  DEBUG ) & DEBUG_TIMEOUT
           fprintf(  stderr,  "RPCIO XACT timed out; waking up requestor\n" );
          #endif
           if (   rtems_event_send(  xact->requestor,   RTEMS_RPC_EVENT )  ) {
           rtems_panic(  "RPCIO PANIC file %s line: %i,   requestor id was 0x%08x",  
           __FILE__,  
           __LINE__,  
           xact->requestor );
           }
          
           } else {
           int len;
          
           len = (  int )XDR_GETPOS(  &xact->xdrs );
          
          #ifdef MBUF_TX
           xact->refcnt = 1; /* sendto itself */
          #endif
           if (   len != SENDTO(   ourSock,  
           xact->obuf.buf,  
           len,  
           0,  
           &srv->addr.sa,  
           sizeof(  srv->addr.sin )
          #ifdef MBUF_TX
           ,   xact,  
           paranoia_free,  
           paranoia_ref
          #endif
            )  ) {
          
           xact->status.re_errno = errno;
           xact->status.re_status = RPC_CANTSEND;
           srv->errors++;
          
           /* wakeup requestor */
           fprintf(  stderr,  "RPCIO: SEND failure\n" );
           status = rtems_event_send(  xact->requestor,   RTEMS_RPC_EVENT );
           assert(   status == RTEMS_SUCCESSFUL  );
          
           } else {
           /* send successful; calculate retransmission time
           * and enqueue to temporary list
           */
           if (  FIRST_ATTEMPT != xact->trip ) {
          #if (  DEBUG ) & DEBUG_TIMEOUT
           fprintf(  stderr,  
           "timed out; tolive is %i (  ticks ),   retry period is %i (  ticks )\n",  
           xact->tolive,  
           srv->retry_period );
          #endif
           /* this is a real retry; we backup
           * the server's retry interval
           */
           if (   srv->retry_period < max_period  ) {
          
           /* If multiple transactions for this server
           * fail (  e.g. because it died ) this will
           * back-off very agressively (  doubling
           * the retransmission period for every
           * timed out transaction up to the CAP limit )
           * which is desirable - single packet failure
           * is treated more gracefully by this algorithm.
           */
          
           srv->retry_period<<=1;
          #if (  DEBUG ) & DEBUG_TIMEOUT
           fprintf(  stderr,  
           "adjusted to; retry period %i\n",  
           srv->retry_period );
          #endif
           } else {
           /* never wait longer than RPCIOD_RETX_CAP_S seconds */
           fprintf(  stderr,  
           "RPCIO: server '%s' not responding - still trying\n",  
           srv->name );
           }
           if (   0 == ++srv->retrans % 1000 ) {
           fprintf(  stderr,  
           "RPCIO - statistics: already %li retries to server %s\n",  
           srv->retrans,  
           srv->name );
           }
           } else {
           srv->requests++;
           }
           xact->trip = now;
           {
           long capped_period = srv->retry_period;
           if (   xact->lifetime < capped_period  )
           capped_period = xact->lifetime;
           xact->age = now + capped_period;
           xact->tolive -= capped_period;
           }
           /* enqueue to the list of newly sent transactions */
           xact->node.next = newList;
           newList = &xact->node;
          #if (  DEBUG ) & DEBUG_TIMEOUT
           fprintf(  stderr,  
           "XACT (  0x%08x ) age is 0x%x,   now: 0x%x\n",  
           xact,  
           xact->age,  
           now );
          #endif
           }
           }
           }
          
           /* insert the newly sent transactions into the
           * sorted retransmission list
           */
           for (  ; (  xact = (  RpcUdpXact )newList );  ) {
           register ListNode p,  n;
           newList = newList->next;
           for (   p=&listHead; (  n=p->next ) && xact->age > (  (  RpcUdpXact )n )->age; p=n  )
           /* nothing else to do */;
           nodeAppend(  p,   &xact->node );
           }
          
           if (  now > epoch ) {
           /* every now and then,   readjust the epoch */
           register ListNode n;
           then += now;
           for (  n=listHead.next; n; n=n->next ) {
           /* readjust outstanding time intervals subject to the
           * condition that the 'absolute' time must remain
           * the same. 'age' and 'trip' are measured with
           * respect to 'then' - hence:
           *
           * abs_age == old_age + old_then == new_age + new_then
           *
           * ==> new_age = old_age + old_then - new_then == old_age - 'now'
           */
           (  (  RpcUdpXact )n )->age -= now;
           (  (  RpcUdpXact )n )->trip -= now;
          #if (  DEBUG ) & DEBUG_TIMEOUT
           fprintf(  stderr,  
           "readjusted XACT (  0x%08x ); age is 0x%x,   trip: 0x%x now: 0x%x\n",  
           (  RpcUdpXact )n,  
           (  (  RpcUdpXact )n )->trip,  
           (  (  RpcUdpXact )n )->age,  
           now );
          #endif
           }
           now = 0;
           }
          
           next_retrans = listHead.next ?
           (  (  RpcUdpXact )listHead.next )->age - now :
           epoch; /* make sure we don't miss updating the epoch */
          #if (  DEBUG ) & DEBUG_TIMEOUT
           fprintf(  stderr,  "RPCIO: next timeout is %x\n",  next_retrans );
          #endif
           }
           /* close our socket; shut down the receiver */
           close(  ourSock );
          
          #if 0 /* if we get here,   no transactions exist,   hence there can be none
           * in the queue whatsoever
           */
           /* flush the message queue */
           while (  RTEMS_SUCCESSFUL == rtems_message_queue_receive(  
           q,  
           &xact,  
           &size,  
           RTEMS_NO_WAIT,  
           RTEMS_NO_TIMEOUT ) ) {
           /* TODO enque xact */
           }
          
           /* flush all outstanding transactions */
          
           for (  xact=(  (  RpcUdpXact )listHead.next ); xact; xact=(  (  RpcUdpXact )xact->node.next ) ) {
           xact->status.re_status = RPC_TIMEDOUT;
           rtems_event_send(  xact->requestor,   RTEMS_RPC_EVENT );
           }
          #endif
          
           rtems_message_queue_delete(  q );
          
           MU_DESTROY(  hlock );
          
           fprintf(  stderr,  "RPC daemon exited...\n" );
          
           rtems_semaphore_release(  fini );
           rtems_task_suspend(  RTEMS_SELF );
          }
          
          
          /* support for transaction 'pools'. A number of XACT objects
           * is always kept around. The initial number is 0 but it
           * is allowed to grow up to a maximum.
           * If the need grows beyond the maximum,   behavior depends:
           * Users can either block until a transaction becomes available,  
           * they can create a new XACT on the fly or get an error
           * if no free XACT is available from the pool.
           */
          
          RpcUdpXactPool
          rpcUdpXactPoolCreate(  
           rpcprog_t prog,   rpcvers_t version,  
           int xactsize,   int poolsize )
          {
          RpcUdpXactPool rval = MY_MALLOC(  sizeof(  *rval ) );
          rtems_status_code status;
          
           ASSERT(   rval  );
           status = rtems_message_queue_create(  
           rtems_build_name(  'R',  'P',  'C',  'p' ),  
           poolsize,  
           sizeof(  RpcUdpXact ),  
           RTEMS_DEFAULT_ATTRIBUTES,  
           &rval->box );
           assert(   status == RTEMS_SUCCESSFUL  );
          
           rval->prog = prog;
           rval->version = version;
           rval->xactSize = xactsize;
           return rval;
          }
          
          void
          rpcUdpXactPoolDestroy(  RpcUdpXactPool pool )
          {
          RpcUdpXact xact;
          
           while (  (  xact = rpcUdpXactPoolGet(  pool,   XactGetFail ) ) ) {
           rpcUdpXactDestroy(  xact );
           }
           rtems_message_queue_delete(  pool->box );
           MY_FREE(  pool );
          }
          
          RpcUdpXact
          rpcUdpXactPoolGet(  RpcUdpXactPool pool,   XactPoolGetMode mode )
          {
          RpcUdpXact xact = 0;
          size_t size;
          
           if (  RTEMS_SUCCESSFUL != rtems_message_queue_receive(  
           pool->box,  
           &xact,  
           &size,  
           XactGetWait == mode ?
           RTEMS_WAIT : RTEMS_NO_WAIT,  
           RTEMS_NO_TIMEOUT ) ) {
          
           /* nothing found in box; should we create a new one ? */
          
           xact = (  XactGetCreate == mode ) ?
           rpcUdpXactCreate(  
           pool->prog,  
           pool->version,  
           pool->xactSize ) : 0 ;
           if (  xact )
           xact->pool = pool;
          
           }
           return xact;
          }
          
          void
          rpcUdpXactPoolPut(  RpcUdpXact xact )
          {
          RpcUdpXactPool pool;
          
           pool = xact->pool;
           ASSERT(   pool  );
          
           if (  RTEMS_SUCCESSFUL != rtems_message_queue_send(  
           pool->box,  
           &xact,  
           sizeof(  xact ) ) )
           rpcUdpXactDestroy(  xact );
          }
          
          #ifdef MBUF_RX
          
          /* WORKAROUND: include sys/mbuf.h (  or other bsdnet headers ) only
           * _after_ using malloc(   )/free(   ) & friends because
           * the RTEMS/BSDNET headers redefine those :-(  
           */
          
          #define _KERNEL
          #include <sys/mbuf.h>
          
          ssize_t
          recv_mbuf_from(  int s,   struct mbuf **ppm,   long len,   struct sockaddr *fromaddr,   int *fromlen );
          
          static void
          bufFree(  struct mbuf **m )
          {
           if (  *m ) {
           rtems_bsdnet_semaphore_obtain(   );
           m_freem(  *m );
           rtems_bsdnet_semaphore_release(   );
           *m = 0;
           }
          }
          #endif
          
          #ifdef MBUF_TX
          static void
          paranoia_free(  caddr_t closure,   u_int size )
          {
          #if (  DEBUG )
          RpcUdpXact xact = (  RpcUdpXact )closure;
          int len = (  int )XDR_GETPOS(  &xact->xdrs );
          
           ASSERT(   --xact->refcnt >= 0 && size == len  );
          #endif
          }
          
          static void
          paranoia_ref (  caddr_t closure,   u_int size )
          {
          #if (  DEBUG )
          RpcUdpXact xact = (  RpcUdpXact )closure;
          int len = (  int )XDR_GETPOS(  &xact->xdrs );
           ASSERT(   size == len  );
           xact->refcnt++;
          #endif
          }
          #endif
          
          /* receive from a socket and find
           * the transaction corresponding to the
           * transaction ID received in the server
           * reply.
           *
           * The semantics of the 'pibuf' pointer are
           * as follows:
           *
           * MBUF_RX:
           *
           */
          
          #define RPCIOD_RXBUFSZ UDPMSGSIZE
          
          static RpcUdpXact
          sockRcv(  void )
          {
          int len,  i;
          uint32_t xid;
          union {
           struct sockaddr_in sin;
           struct sockaddr sa;
          } fromAddr;
          int fromLen = sizeof(  fromAddr.sin );
          RxBuf ibuf = 0;
          RpcUdpXact xact = 0;
          
           do {
          
           /* rcv_mbuf(   ) and recvfrom(   ) differ in that the
           * former allocates buffers and passes them back
           * to us whereas the latter requires us to provide
           * buffer space.
           * Hence,   in the first case whe have to make sure
           * no old buffer is leaked - in the second case,  
           * we might well re-use an old buffer but must
           * make sure we have one allocated
           */
          #ifdef MBUF_RX
           if (  ibuf )
           bufFree(  &ibuf );
          
           len = recv_mbuf_from(  
           ourSock,  
           &ibuf,  
           RPCIOD_RXBUFSZ,  
           &fromAddr.sa,  
           &fromLen );
          #else
           if (   !ibuf  )
           ibuf = (  RpcBuf )MY_MALLOC(  RPCIOD_RXBUFSZ );
           if (   !ibuf  )
           goto cleanup; /* no memory - drop this message */
          
           len = recvfrom(  ourSock,  
           ibuf->buf,  
           RPCIOD_RXBUFSZ,  
           0,  
           &fromAddr.sa,  
           &fromLen );
          #endif
          
           if (  len <= 0 ) {
           if (  EAGAIN != errno )
           fprintf(  stderr,  "RECV failed: %s\n",  strerror(  errno ) );
           goto cleanup;
           }
          
          #if (  DEBUG ) & DEBUG_PACKLOSS
           if (   (  unsigned )rand(   ) < DEBUG_PACKLOSS_FRACT  ) {
           /* lose packets once in a while */
           static int xxx = 0;
           if (   ++xxx % 16 == 0  )
           fprintf(  stderr,  "DEBUG: dropped %i packets,   so far...\n",  xxx );
           if (   ibuf  )
           bufFree(   &ibuf  );
           continue;
           }
          #endif
          
           i = (  xid=XID(  ibuf ) ) & XACT_HASH_MSK;
          
           if (   !(  xact=xactHashTbl[i] ) ||
           xact->obuf.xid != xid ||
          #ifdef REJECT_SERVERIP_MISMATCH
           xact->server->addr.sin.sin_addr.s_addr != fromAddr.sin.sin_addr.s_addr ||
          #endif
           xact->server->addr.sin.sin_port != fromAddr.sin.sin_port  ) {
          
           if (  xact ) {
           if (  
          #ifdef REJECT_SERVERIP_MISMATCH
           xact->server->addr.sin.sin_addr.s_addr == fromAddr.sin.sin_addr.s_addr &&
          #endif
           xact->server->addr.sin.sin_port == fromAddr.sin.sin_port &&
           (   xact->obuf.xid == xid + XACT_HASHS ||
           xact->obuf.xid == xid + 2*XACT_HASHS  )
            ) {
          #ifndef DEBUG /* don't complain if it's just a late arrival of a retry */
           fprintf(  stderr,  "RPCIO - FYI sockRcv(   ): dropping late/redundant retry answer\n" );
          #endif
           } else {
           fprintf(  stderr,  "RPCIO WARNING sockRcv(   ): transaction mismatch\n" );
           fprintf(  stderr,  "xact: xid 0x%08" PRIx32 " -- got 0x%08" PRIx32 "\n",  
           xact->obuf.xid,   xid );
           fprintf(  stderr,  "xact: addr 0x%08" PRIx32 " -- got 0x%08" PRIx32 "\n",  
           xact->server->addr.sin.sin_addr.s_addr,  
           fromAddr.sin.sin_addr.s_addr );
           fprintf(  stderr,  "xact: port 0x%08x -- got 0x%08x\n",  
           xact->server->addr.sin.sin_port,  
           fromAddr.sin.sin_port );
           }
           } else {
           fprintf(  stderr,  
           "RPCIO WARNING sockRcv(   ): got xid 0x%08" PRIx32 " but its slot is empty\n",  
           xid );
           }
           /* forget about this one and try again */
           xact = 0;
           }
          
           } while (   !xact  );
          
           xact->ibuf = ibuf;
          #ifndef MBUF_RX
           xact->ibufsize = RPCIOD_RXBUFSZ;
          #endif
          
           return xact;
          
          cleanup:
          
           bufFree(  &ibuf );
          
           return 0;
          }
          
          
          #include <rtems/rtems_bsdnet_internal.h>
          /* double check the event configuration; should probably globally
           * manage system events!!
           * We do this at the end of the file for the same reason we had
           * included mbuf.h only a couple of lines above - see comment up
           * there...
           */
          #if RTEMS_RPC_EVENT & SOSLEEP_EVENT & SBWAIT_EVENT & NETISR_EVENTS
          #error ILLEGAL EVENT CONFIGURATION
          #endif

libfs/src/nfsclient/src/rpcio.modini.c

       1  #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include "librtemsNfs.h"
          /* CEXP module support (  magic init ) */
          void
       8  _cexpModuleInitialize(  void *mod )
          {
           rpcUdpInit(   );
          }
          
          int
      14  _cexpModuleFinalize(  void *mod )
          {
           return rpcUdpCleanup(   );
          }
          
          

libfs/src/nfsclient/src/sock_mbuf.c

       1  /*
           * $Id: sock_mbuf.c,  v 1.4 2010/03/27 04:04:39 ccj Exp $
           *
           * NOTE:
           * This is derived from libnetworking/rtems/rtems_syscall.c
           *
           * RTEMS/libnetworking LICENSING restrictions may apply
           *
           * Author (  modifications only ):
           * Copyright: 2002,   Stanford University and
           * Till Straumann,   <strauman@slac.stanford.edu>
           * Licensing: 'LICENSE.NET' file in the RTEMS top source directory
           * for more information.
           */
          
          /*
          The RTEMS TCP/IP stack is a port of the FreeBSD TCP/IP stack. The following
          copyright and licensing information applies to this code.
          
          This code is found under the c/src/libnetworking directory but does not
          constitute the entire contents of that subdirectory.
          
          =============================================================================
          
          Copyright (  c ) 1980,   1983,   1988,   1993
           The Regents of the University of California. 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.
          3. All advertising materials mentioning features or use of this software
           must display the following acknowledgment:
           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.
          
          -
          Portions Copyright (  c ) 1993 by Digital Equipment Corporation.
          
          Permission to use,   copy,   modify,   and distribute this software for any
          purpose with or without fee is hereby granted,   provided that the above
          copyright notice and this permission notice appear in all copies,   and that
          the name of Digital Equipment Corporation not be used in advertising or
          publicity pertaining to distribution of the document or software without
          specific,   written prior permission.
          
          THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
          WARRANTIES WITH REGARD TO THIS SOFTWARE,   INCLUDING ALL IMPLIED WARRANTIES
          OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
          CORPORATION BE LIABLE FOR ANY SPECIAL,   DIRECT,   INDIRECT,   OR CONSEQUENTIAL
          DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,   DATA OR
          PROFITS,   WHETHER IN AN ACTION OF CONTRACT,   NEGLIGENCE OR OTHER TORTIOUS
          ACTION,   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
          SOFTWARE.
          
          =============================================================================
          */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          #include <stdarg.h>
          #include <stdio.h>
          
          #include <rtems.h>
          #include <rtems/libio.h>
          #include <rtems/error.h>
          
          #define _KERNEL
          #define __BSD_VISIBLE 1
          #include <rtems/rtems_bsdnet.h>
          
          #include <sys/errno.h>
          #include <sys/types.h>
          #include <sys/param.h>
          #include <sys/mbuf.h>
          #include <sys/socket.h>
          #include <sys/socketvar.h>
          #include <sys/protosw.h>
          #include <sys/proc.h>
          #include <sys/fcntl.h>
          #include <sys/filio.h>
          
          #include <net/if.h>
          #include <net/route.h>
          
     108  struct socket *rtems_bsdnet_fdToSocket(  int fd );
          
          /*
           * Package system call argument into mbuf.
           *
           * (  unfortunately,   the original is not public )
           */
          static int
     116  sockaddrtombuf (  struct mbuf **mp,   const struct sockaddr *buf,   int buflen )
          {
          struct mbuf *m;
          struct sockaddr *sa;
          
           if (  (  u_int )buflen > MLEN )
           return (  EINVAL );
          
           rtems_bsdnet_semaphore_obtain(   );
           m = m_get(  M_WAIT,   MT_SONAME );
           rtems_bsdnet_semaphore_release(   );
          
           if (  m == NULL )
           return (  ENOBUFS );
           m->m_len = buflen;
           memcpy (  mtod(  m,   caddr_t ),   buf,   buflen );
           *mp = m;
           sa = mtod(  m,   struct sockaddr * );
           sa->sa_len = buflen;
          
           return 0;
          }
          
          static void
     140  dummyproc(  caddr_t ext_buf,   u_int ext_size )
          {
          }
          
          /*
           * send data by simply allocating an MBUF packet
           * header and pointing it to our data region.
           *
           * Optionally,   the caller may supply 'reference'
           * and 'free' procs. (  The latter may call the
           * user back once the networking stack has
           * released the buffer ).
           *
           * The callbacks are provided with the 'closure'
           * pointer and the 'buflen' argument.
           */
          ssize_t
     157  sendto_nocpy (  
           int s,  
           const void *buf,   size_t buflen,  
           int flags,  
           const struct sockaddr *toaddr,   int tolen,  
           void *closure,  
           void (  *freeproc )(  caddr_t,   u_int ),  
           void (  *refproc )(  caddr_t,   u_int )
           )
          {
           int error;
           struct socket *so;
           struct mbuf *to,   *m;
           int ret = -1;
          
           rtems_bsdnet_semaphore_obtain (   );
           if (  (  so = rtems_bsdnet_fdToSocket (  s ) ) == NULL ) {
           rtems_bsdnet_semaphore_release (   );
           return -1;
           }
          
           error = sockaddrtombuf (  &to,   toaddr,   tolen );
           if (  error ) {
           errno = error;
           rtems_bsdnet_semaphore_release (   );
           return -1;
           }
          
           MGETHDR(  m,   M_WAIT,   MT_DATA );
           m->m_pkthdr.len = 0;
           m->m_pkthdr.rcvif = (  struct ifnet * ) 0;
          
           m->m_flags |= M_EXT;
           m->m_ext.ext_buf = closure ? closure : (  void* )buf;
           m->m_ext.ext_size = buflen;
           /* we _must_ supply non-null procs; otherwise,  
           * the kernel code assumes it's a mbuf cluster
           */
           m->m_ext.ext_free = freeproc ? freeproc : dummyproc;
           m->m_ext.ext_ref = refproc ? refproc : dummyproc;
           m->m_pkthdr.len += buflen;
           m->m_len = buflen;
           m->m_data = (  void* )buf;
          
           error = sosend (  so,   to,   NULL,   m,   NULL,   flags );
           if (  error ) {
           if (  /*auio.uio_resid != len &&*/ (  error == EINTR || error == EWOULDBLOCK ) )
           error = 0;
           }
           if (  error )
           errno = error;
           else
           ret = buflen;
           if (  to )
           m_freem(  to );
           rtems_bsdnet_semaphore_release (   );
           return (  ret );
          }
          
          
          /*
           * receive data in an 'mbuf chain'.
           * The chain must be released once the
           * data has been extracted:
           *
           * rtems_bsdnet_semaphore_obtain(   );
           * m_freem(  chain );
           * rtems_bsdnet_semaphore_release(   );
           */
          ssize_t
     227  recv_mbuf_from(  int s,   struct mbuf **ppm,   long len,   struct sockaddr *fromaddr,   int *fromlen )
          {
           int ret = -1;
           int error;
           struct uio auio;
           struct socket *so;
           struct mbuf *from = NULL;
          
           memset(  &auio,   0,   sizeof(  auio ) );
           *ppm = 0;
          
           rtems_bsdnet_semaphore_obtain (   );
           if (  (  so = rtems_bsdnet_fdToSocket (  s ) ) == NULL ) {
           rtems_bsdnet_semaphore_release (   );
           return -1;
           }
          /* auio.uio_iov = mp->msg_iov;
           auio.uio_iovcnt = mp->msg_iovlen;
           auio.uio_segflg = UIO_USERSPACE;
           auio.uio_rw = UIO_READ;
           auio.uio_offset = 0;
          */
           auio.uio_resid = len;
           error = soreceive (  so,   &from,   &auio,   (  struct mbuf ** ) ppm,  
           (  struct mbuf ** )NULL,  
           NULL );
           if (  error ) {
           if (  auio.uio_resid != len && (  error == EINTR || error == EWOULDBLOCK ) )
           error = 0;
           }
           if (  error ) {
           errno = error;
           }
           else {
           ret = len - auio.uio_resid;
           if (  fromaddr ) {
           len = *fromlen;
           if (  (  len <= 0 ) || (  from == NULL ) ) {
           len = 0;
           }
           else {
           if (  len > from->m_len )
           len = from->m_len;
           memcpy (  fromaddr,   mtod(  from,   caddr_t ),   len );
           }
           *fromlen = len;
           }
           }
           if (  from )
           m_freem (  from );
           if (  error && *ppm ) {
           m_freem(  *ppm );
           *ppm = 0;
           }
           rtems_bsdnet_semaphore_release (   );
           return (  ret );
          }

libfs/src/nfsclient/src/xdr_mbuf.c

       1  /* $Id: xdr_mbuf.c,  v 1.9 2010/06/01 10:41:40 ralf Exp $ */
          
          /* xdr_mbuf is derived from xdr_mem */
          
          /* Author (  mbuf specifica ): Till Straumann <strauman@slac.stanford.edu>,   10/2002 */
          
          /*
           * Sun RPC is a product of Sun Microsystems,   Inc. and is provided for
           * unrestricted use provided that this legend is included on all tape
           * media and as a part of the software program in whole or part. Users
           * may copy or modify Sun RPC without charge,   but are not authorized
           * to license or distribute it to anyone else except as part of a product or
           * program developed by the user.
           *
           * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
           * WARRANTIES OF DESIGN,   MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
           * PURPOSE,   OR ARISING FROM A COURSE OF DEALING,   USAGE OR TRADE PRACTICE.
           *
           * Sun RPC is provided with no support and without any obligation on the
           * part of Sun Microsystems,   Inc. to assist in its use,   correction,  
           * modification or enhancement.
           *
           * SUN MICROSYSTEMS,   INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
           * INFRINGEMENT OF COPYRIGHTS,   TRADE SECRETS OR ANY PATENTS BY SUN RPC
           * OR ANY PART THEREOF.
           *
           * In no event will Sun Microsystems,   Inc. be liable for any lost revenue
           * or profits or other special,   indirect and consequential damages,   even if
           * Sun has been advised of the possibility of such damages.
           *
           * Sun Microsystems,   Inc.
           * 2550 Garcia Avenue
           * Mountain View,   California 94043
           */
          
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          /*static char *sccsid = "from: @(  # )xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
          /*static char *sccsid = "from: @(  # )xdr_mem.c 2.1 88/07/29 4.0 RPCSRC";*/
          static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_mem.c,  v 1.8 1999/08/28 00:02:56 peter Exp $";
          #endif
          
          /*
           * xdr_mbuf,   XDR implementation using mbuf buffers
           *
           * derived from:
           *
           * xdr_mem.h,   XDR implementation using memory buffers.
           *
           * Copyright (  C ) 1984,   Sun Microsystems,   Inc.
           *
           * The MBUF stream is useful for BSDNET kernel (  or RTEMS for that matter )
           * use.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          #include <rpc/types.h>
          #include <rpc/xdr.h>
          #include <netinet/in.h>
          
          #include <stdlib.h>
          
          #define TODO
          
          /* TODO remove: a hack because malloc is redefined */
          #ifdef TODO
          static inline void *
      71  my_malloc(  size_t i )
          {
           return malloc(  i );
          }
          
          static inline void
      77  my_free(  void *p )
          {
           return free(  p );
          }
          #endif
          
          #define DEBUG_ASSERT (  1<<0 )
          #define DEBUG_VERB (  1<<1 )
          
          #define DEBUG DEBUG_ASSERT
          
          #define _KERNEL
          #include <sys/mbuf.h>
          
          #include <assert.h>
          
          #if DEBUG & DEBUG_VERB || defined(  TODO )
          #include <stdio.h>
          #endif
          
      97  static bool_t xdrmbuf_getlong_aligned(  XDR *xdrs,   long *lp );
      98  static bool_t xdrmbuf_putlong_aligned(  XDR *xdrs,   const long *lp );
      99  static bool_t xdrmbuf_getlong_unaligned(  XDR *xdrs,   long *lp );
     100  static bool_t xdrmbuf_putlong_unaligned(  XDR *xdrs,   const long *lp );
     101  static bool_t xdrmbuf_getbytes(  XDR *xdrs,   caddr_t addr,   u_int len );
     102  static bool_t xdrmbuf_putbytes(  XDR *xdrs,   const char *addr,   u_int len );
     103  static u_int xdrmbuf_getpos(  XDR *xdrs ); /* XXX w/64-bit pointers,   u_int not enough! */
     104  static bool_t xdrmbuf_setpos(  XDR *xdrs,   u_int pos );
     105  static int32_t *xdrmbuf_inline_aligned(  XDR *xdrs,   u_int len );
     106  static int32_t *xdrmbuf_inline_unaligned(  XDR *xdrs,   u_int len );
     107  static void xdrmbuf_destroy(  XDR * );
          
          static struct xdr_ops xdrmbuf_ops_aligned = {
           xdrmbuf_getlong_aligned,  
           xdrmbuf_putlong_aligned,  
           xdrmbuf_getbytes,  
           xdrmbuf_putbytes,  
           xdrmbuf_getpos,  
           xdrmbuf_setpos,  
           xdrmbuf_inline_aligned,  
           xdrmbuf_destroy
          };
          
          static struct xdr_ops xdrmbuf_ops_unaligned = {
           xdrmbuf_getlong_unaligned,  
           xdrmbuf_putlong_unaligned,  
           xdrmbuf_getbytes,  
           xdrmbuf_putbytes,  
           xdrmbuf_getpos,  
           xdrmbuf_setpos,  
           xdrmbuf_inline_unaligned,  
           xdrmbuf_destroy
          };
          
          typedef struct MBPrivateRec_ {
           struct mbuf *mchain;
           struct mbuf *mcurrent;
           u_int pos; /* number of bytes contained in all MUBFS ahead
           * of mcurrent
           */
          } MBPrivateRec,   *MBPrivate;
          
          /* NOTE: the stream position helper 'pos'
           * must be managed by the caller!
           */
          static inline void
     143  xdrmbuf_setup(  XDR *xdrs,   struct mbuf *m )
          {
          MBPrivate mbp = (  MBPrivate )xdrs->x_base;
          
           mbp->mcurrent = m;
           xdrs->x_private = mtod(  m,  caddr_t );
           xdrs->x_handy = m->m_len;
           xdrs->x_ops = (  (  uintptr_t )xdrs->x_private & (  sizeof(  int32_t ) - 1 ) )
           ? &xdrmbuf_ops_unaligned : &xdrmbuf_ops_aligned;
          }
          
          static struct mbuf *
     155  xdrmbuf_next(  XDR *xdrs )
          {
          struct mbuf *rval;
          MBPrivate mbp = (  MBPrivate )xdrs->x_base;
          
           if (  mbp->mcurrent ) {
           mbp->pos += mbp->mcurrent->m_len;
           rval = mbp->mcurrent->m_next;
           } else {
           rval = 0;
           }
          
           if (  rval ) {
           xdrmbuf_setup(  xdrs,   rval );
           }
          #if DEBUG & DEBUG_VERB
           else {
           fprintf(  stderr,  "xdrmbuf: end of chain\n" );
           }
          #endif
          
           return rval;
          }
          
          /*
           * The procedure xdrmbuf_create initializes a stream descriptor for a
           * memory buffer.
           */
          void
     184  xdrmbuf_create(  XDR *xdrs,   struct mbuf *mbuf,   enum xdr_op op )
          {
          MBPrivate mbp;
          
           xdrs->x_op = op;
           mbp = (  MBPrivate )my_malloc(  sizeof(  *mbp ) );
           assert(   mbp  );
           xdrs->x_base = (  caddr_t ) mbp;
          
           mbp->mchain = mbuf;
           mbp->pos = 0;
          
          #if DEBUG & DEBUG_VERB
           {
           struct mbuf *mbf;
           fprintf(  stderr,  "Dumping chain:\n" );
           for (  mbf = mbuf; mbf; mbf=mbf->m_next ) {
           int ii;
           fprintf(  stderr,  "MBUF------------" );
           for (  ii=0; ii<mbf->m_len; ii++ ) {
           fprintf(  stderr,  "%02x ",  mtod(  mbf,  char* )[ii] );
           if (  ii%16==0 )
           fputc(  '\n',  stderr );
           }
           fputc(  '\n',  stderr );
           }
           }
          #endif
          
           xdrmbuf_setup(  xdrs,   mbuf );
          }
          
          static void
     217  xdrmbuf_destroy(  XDR *xdrs )
          {
          MBPrivate mbp = (  MBPrivate )xdrs->x_base;
          #if 0 /* leave destroying the chain to the user */
          struct mbuf *m = mbp->mchain;
          
           rtems_bsdnet_semaphore_obtain(   );
           m_freem(  m );
           rtems_bsdnet_semaphore_release(   );
          #endif
          
           my_free(  mbp );
          }
          
          static bool_t
     232  xdrmbuf_getlong_aligned(  register XDR *xdrs,   register long *lp )
          {
           while (   (  signed int )(  xdrs->x_handy -= sizeof(  int32_t ) ) < 0 ) {
           if (  (  xdrs->x_handy += sizeof(  int32_t ) ) == 0 ) {
           /* handy was 0 on entry; request a new buffer.
           * Coded this way,   so the most frequently executed
           * path needs only one comparison...
           */
           if (  !xdrmbuf_next(  xdrs ) )
           return FALSE;
           } else {
           /* uh-oh an aligned long spread over two MBUFS ??
           * let the unaligned handler deal with this rare
           * situation.
           */
           return xdrmbuf_getlong_unaligned(  xdrs,  lp );
           }
           }
           *lp = ntohl(  *(  int32_t * )(  xdrs->x_private ) );
           xdrs->x_private += sizeof(  int32_t );
          #if DEBUG & DEBUG_VERB
           fprintf(  stderr,  "Got aligned long %x\n",  *lp );
          #endif
           return (  TRUE );
          }
          
          static bool_t
     259  xdrmbuf_putlong_aligned(  
           XDR *xdrs,  
           const long *lp )
          {
          fprintf(  stderr,  "TODO: xdrmbuf_putlong_aligned(   ) is unimplemented\n" );
           return FALSE;
          #if 0
           if (  (  xdrs->x_handy -= sizeof(  int32_t ) ) < 0 )
           return (  FALSE );
           *(  int32_t * )xdrs->x_private = htonl(  *lp );
           xdrs->x_private += sizeof(  int32_t );
           return (  TRUE );
          #endif
          }
          
          static bool_t
     275  xdrmbuf_getlong_unaligned(  
           XDR *xdrs,  
           long *lp )
          {
          union {
           int32_t l;
           char c[sizeof(  int32_t )];
          } u;
          
          register int i,  j;
          register char *cp,  *sp;
          
           i = xdrs->x_handy - sizeof(  int32_t );
          
           /* handle the most common case first */
           if (   i >= 0  ) {
          
           xdrs->x_handy = i;
           sp = (  char* )xdrs->x_private;
           xdrs->x_private = sp + sizeof(  int32_t );
          
          #ifdef CANDO_UNALIGNED
           {
           *lp = ntohl(  *(  int32_t * )sp );
          # if DEBUG & DEBUG_VERB
           fprintf(  stderr,  "Got unaligned long %x (  %i remaining )\n",  *lp,   xdrs->x_handy );
          # endif
           return TRUE;
           }
          #else /* machine can't do unaligned access */
           {
           u.c[0] = *sp;
           u.c[1] = *++sp;
           u.c[2] = *++sp;
           u.c[3] = *++sp;
          
           goto done;
           }
          #endif /* CANDO_UNALIGNED */
           }
          
           /* here the messy 'crossing buffers' business starts */
          
          
           j = sizeof(  int32_t );
          
           cp = u.c-1;
          
           /* NOTE: on entry to this section,   handy < j holds */
           do {
           sp = (  (  char* )xdrs->x_private )-1;
          
           if (   (  i=xdrs->x_handy ) >= j  ) {
           /* more data in the buffer than we need:
           * copy everything we need and goto 'done'
           */
           xdrs->x_handy = i-j;
           do {
           *++cp = *++sp;
           } while (  --j > 0 );
           xdrs->x_private = (  caddr_t )++sp;
          
           goto done;
          
           } else {
           /* not enough data - copy as much as possible
           * then get retrieve the next MBUF and start
           * over
           */
           j-=i;
           while (  i-- )
           *++cp = *++sp;
           if (  !xdrmbuf_next(  xdrs ) )
           return FALSE;
          #if DEBUG & DEBUG_VERB
           fprintf(  stderr,  "getlong_unaligned: crossed mbuf boundary\n" );
          #endif
           }
           } while (  j > 0 );
          
          done:
          
           *lp = ntohl(  u.l );
          
          #if DEBUG & DEBUG_VERB
           fprintf(  stderr,  "Got unaligned long %x (  %i remaining )\n",  *lp,   xdrs->x_handy );
          #endif
           return (  TRUE );
          }
          
          static bool_t
     366  xdrmbuf_putlong_unaligned(  
           XDR *xdrs,  
           const long *lp  )
          {
          
           fprintf(  stderr,  "TODO: xdrmbuf_putlong_unaligned(   ) is unimplemented\n" );
           return FALSE;
          #if 0
           {
           int32_t l;
          
           if (  (  xdrs->x_handy -= sizeof(  int32_t ) ) < 0 )
           return (  FALSE );
           l = htonl(  *lp );
           memcpy(  xdrs->x_private,   &l,   sizeof(  int32_t ) );
           xdrs->x_private += sizeof(  int32_t );
           return (  TRUE );
           }
          #endif
          }
          
          static bool_t
     388  xdrmbuf_getbytes(  
           XDR *xdrs,  
           caddr_t addr,  
           u_int len )
          {
          #if DEBUG & DEBUG_VERB
          int olen=len,  bufs=0;
          #endif
          
          #if DEBUG & DEBUG_VERB
           fprintf(  stderr,  "wanting %i bytes (  have %i )\n",  olen,  xdrs->x_handy );
          #endif
          
           while (  len>0 ) {
           if (  xdrs->x_handy >= len ) {
           memcpy(  addr,   xdrs->x_private,   len );
           xdrs->x_private += len;
           xdrs->x_handy -= len;
          #if 0 /* save a couple of instructions */
           len = 0;
          #else
           goto done;
          #endif
           } else {
           if (  xdrs->x_handy > 0 ) {
           memcpy(  addr,   xdrs->x_private,   xdrs->x_handy );
           len -= xdrs->x_handy;
           addr += xdrs->x_handy;
           }
           if (  !xdrmbuf_next(  xdrs ) )
           return FALSE;
          #if DEBUG & DEBUG_VERB
           bufs++;
          #endif
           }
           }
          done:
          #if DEBUG & DEBUG_VERB
           fprintf(  stderr,  "Got %i bytes (  out of %i mbufs )\n",  olen,  bufs );
          #endif
           return (  TRUE );
          }
          
          static bool_t
     432  xdrmbuf_putbytes(  
           XDR *xdrs,  
           const char *addr,  
           u_int len  )
          {
          
           fprintf(  stderr,  "TODO: xdrmbuf_putbytes(   ) is unimplemented\n" );
           return FALSE;
          #if 0
           if (  (  xdrs->x_handy -= len ) < 0 )
           return (  FALSE );
           memcpy(  xdrs->x_private,   addr,   len );
           xdrs->x_private += len;
           return (  TRUE );
          #endif
          }
          
          static u_int
     450  xdrmbuf_getpos(  
           XDR *xdrs )
          {
          #if 1
          MBPrivate mbp = (  MBPrivate )xdrs->x_base;
          struct mbuf *m = mbp->mcurrent;
          u_int rval = mbp->pos;
          
           if (  m ) {
           rval += xdrs->x_private - mtod(  m,   void* );
           }
          #else
          struct mbuf *m;
          u_int rval = 0;
          MBPrivate mbp = (  MBPrivate )xdrs->x_base;
          
           for (   m = mbp->mchain; m && m != mbp->mcurrent; m = m->m_next  )
           rval += m->m_len;
           if (  m ) {
           rval += (  u_long )xdrs->x_private - mtod(  m,   u_long );
           }
          
          #endif
           return rval;
          }
          
          static bool_t
     477  xdrmbuf_setpos(  
           XDR *xdrs,  
           u_int pos )
          {
          struct mbuf *m;
          MBPrivate mbp = (  MBPrivate )xdrs->x_base;
          
           if (  pos >= mbp->pos ) {
           pos -= mbp->pos;
           m = mbp->mcurrent;
           } else {
           m = mbp->mchain;
           mbp->pos = 0;
           }
          
           while (   m && pos >= m->m_len  ) {
           pos -= m->m_len;
           mbp->pos += m->m_len;
           m = m->m_next;
           }
          
           if (  m ) {
           xdrmbuf_setup(  xdrs,   m );
           xdrs->x_private += pos;
           return TRUE;
           }
          
           return 0 == pos ? TRUE : FALSE;
          }
          
          static int32_t *
     508  xdrmbuf_inline_aligned(  
           XDR *xdrs,  
           u_int len )
          {
          int32_t *buf = 0;
          
           if (  xdrs->x_handy == 0 && !xdrmbuf_next(  xdrs ) )
           return 0;
          
           if (  xdrs->x_handy >= len ) {
           xdrs->x_handy -= len;
           buf = (  int32_t * ) xdrs->x_private;
           xdrs->x_private += len;
          #if DEBUG & DEBUG_VERB
           fprintf(  stderr,  "Got %i aligned inline bytes at %x\n",   len,   buf );
          #endif
           }
          #if DEBUG & DEBUG_VERB
           else {
           fprintf(  stderr,  "Skipped %i aligned inline bytes\n",  len );
           }
          #endif
           return (  buf );
          }
          
          static int32_t *
     534  xdrmbuf_inline_unaligned(  
           XDR *xdrs,  
           u_int len  )
          {
           return (  0 );
          }

libfs/src/pipe/fifo.c

       1  /*
           * fifo.c: POSIX FIFO/pipe for RTEMS
           *
           * Author: Wei Shen <cquark@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: fifo.c,  v 1.11 2010/08/10 17:41:32 joel Exp $
           */
          
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_POSIX_API
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #endif
          
          #include <errno.h>
          #include <stdlib.h>
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          
          #include "pipe.h"
          
          
          #define MIN(  a,   b ) (  (  a ) < (  b )? (  a ): (  b ) )
          
          #define LIBIO_ACCMODE(  _iop ) (  (  _iop )->flags & LIBIO_FLAGS_READ_WRITE )
          #define LIBIO_NODELAY(  _iop ) (  (  _iop )->flags & LIBIO_FLAGS_NO_DELAY )
          
          static rtems_id pipe_semaphore = RTEMS_ID_NONE;
          
          
          #define PIPE_EMPTY(  _pipe ) (  _pipe->Length == 0 )
          #define PIPE_FULL(  _pipe ) (  _pipe->Length == _pipe->Size )
          #define PIPE_SPACE(  _pipe ) (  _pipe->Size - _pipe->Length )
          #define PIPE_WSTART(  _pipe ) (  (  _pipe->Start + _pipe->Length ) % _pipe->Size )
          
          #define PIPE_LOCK(  _pipe ) \
           (   rtems_semaphore_obtain(  _pipe->Semaphore,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT ) \
           == RTEMS_SUCCESSFUL  )
          
          #define PIPE_UNLOCK(  _pipe ) rtems_semaphore_release(  _pipe->Semaphore )
          
          #define PIPE_READWAIT(  _pipe ) \
           (   rtems_barrier_wait(  _pipe->readBarrier,   RTEMS_NO_TIMEOUT ) \
           == RTEMS_SUCCESSFUL )
          
          #define PIPE_WRITEWAIT(  _pipe ) \
           (   rtems_barrier_wait(  _pipe->writeBarrier,   RTEMS_NO_TIMEOUT ) \
           == RTEMS_SUCCESSFUL )
          
          #define PIPE_WAKEUPREADERS(  _pipe ) \
           do {uint32_t n; rtems_barrier_release(  _pipe->readBarrier,   &n ); } while(  0 )
          
          #define PIPE_WAKEUPWRITERS(  _pipe ) \
           do {uint32_t n; rtems_barrier_release(  _pipe->writeBarrier,   &n ); } while(  0 )
          
      64  
          #ifdef RTEMS_POSIX_API
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          
          #include <rtems/rtems/barrier.h>
          #include <rtems/score/thread.h>
          
          /* Set barriers to be interruptible by signals. */
          static void pipe_interruptible(  pipe_control_t *pipe )
          {
           Objects_Locations location;
          
           _Barrier_Get(  pipe->readBarrier,   &location )->Barrier.Wait_queue.state
           |= STATES_INTERRUPTIBLE_BY_SIGNAL;
           _Thread_Enable_dispatch(   );
           _Barrier_Get(  pipe->writeBarrier,   &location )->Barrier.Wait_queue.state
           |= STATES_INTERRUPTIBLE_BY_SIGNAL;
      81   _Thread_Enable_dispatch(   );
          }
          #endif
          
          /*
           * Alloc pipe control structure,   buffer,   and resources.
           * Called with pipe_semaphore held.
           */
          static int pipe_alloc(  
           pipe_control_t **pipep
           )
          {
           static char c = 'a';
           pipe_control_t *pipe;
           int err = -ENOMEM;
          
           pipe = malloc(  sizeof(  pipe_control_t ) );
           if (  pipe == NULL )
           return err;
           memset(  pipe,   0,   sizeof(  pipe_control_t ) );
          
           pipe->Size = PIPE_BUF;
           pipe->Buffer = malloc(  pipe->Size );
           if (  ! pipe->Buffer )
           goto err_buf;
          
           err = -ENOMEM;
          
           if (  rtems_barrier_create(  
           rtems_build_name (  'P',   'I',   'r',   c ),  
           RTEMS_BARRIER_MANUAL_RELEASE,   0,  
           &pipe->readBarrier ) != RTEMS_SUCCESSFUL )
           goto err_rbar;
           if (  rtems_barrier_create(  
           rtems_build_name (  'P',   'I',   'w',   c ),  
           RTEMS_BARRIER_MANUAL_RELEASE,   0,  
           &pipe->writeBarrier ) != RTEMS_SUCCESSFUL )
           goto err_wbar;
           if (  rtems_semaphore_create(  
           rtems_build_name (  'P',   'I',   's',   c ),   1,  
           RTEMS_BINARY_SEMAPHORE | RTEMS_FIFO,  
           RTEMS_NO_PRIORITY,   &pipe->Semaphore ) != RTEMS_SUCCESSFUL )
           goto err_sem;
          
          #ifdef RTEMS_POSIX_API
           pipe_interruptible(  pipe );
          #endif
          
           *pipep = pipe;
           if (  c ++ == 'z' )
           c = 'a';
           return 0;
          
          err_sem:
           rtems_barrier_delete(  pipe->writeBarrier );
          err_wbar:
           rtems_barrier_delete(  pipe->readBarrier );
     138  err_rbar:
           free(  pipe->Buffer );
          err_buf:
           free(  pipe );
           return err;
          }
          
          /* Called with pipe_semaphore held. */
          static inline void pipe_free(  
           pipe_control_t *pipe
           )
     149  {
           rtems_barrier_delete(  pipe->readBarrier );
           rtems_barrier_delete(  pipe->writeBarrier );
           rtems_semaphore_delete(  pipe->Semaphore );
           free(  pipe->Buffer );
           free(  pipe );
          }
          
          static rtems_status_code pipe_lock(  void )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
          
           if (  pipe_semaphore == RTEMS_ID_NONE ) {
           rtems_libio_lock(   );
          
           if (  pipe_semaphore == RTEMS_ID_NONE ) {
           sc = rtems_semaphore_create(  
           rtems_build_name(  'P',   'I',   'P',   'E' ),  
           1,  
           RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,  
           RTEMS_NO_PRIORITY,  
           &pipe_semaphore
            );
           }
          
           rtems_libio_unlock(   );
           }
          
           if (  sc == RTEMS_SUCCESSFUL ) {
           sc = rtems_semaphore_obtain(  pipe_semaphore,   RTEMS_WAIT,   RTEMS_NO_TIMEOUT );
           }
     180  
           if (  sc == RTEMS_SUCCESSFUL ) {
           return 0;
           } else {
           return -ENOMEM;
           }
          }
          
          static void pipe_unlock(  void )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
          
           sc = rtems_semaphore_release(  pipe_semaphore );
           #ifdef RTEMS_DEBUG
           if (  sc != RTEMS_SUCCESSFUL ) {
           rtems_fatal_error_occurred(  0xdeadbeef );
           }
     197   #endif
          }
          
          /*
           * If called with *pipep = NULL,   pipe_new will call pipe_alloc to allocate a
           * pipe control structure and set *pipep to its address.
           * pipe is locked,   when pipe_new returns with no error.
           */
          static int pipe_new(  
           pipe_control_t **pipep
           )
          {
           pipe_control_t *pipe;
           int err = 0;
          
           err = pipe_lock(   );
           if (  err )
           return err;
          
           pipe = *pipep;
           if (  pipe == NULL ) {
           err = pipe_alloc(  &pipe );
           if (  err )
           goto out;
           }
          
           if (  ! PIPE_LOCK(  pipe ) )
           err = -EINTR;
          
           if (  *pipep == NULL ) {
           if (  err )
           pipe_free(  pipe );
           else
           *pipep = pipe;
           }
          
          out:
           pipe_unlock(   );
           return err;
     236  }
          
          /*
           * Interface to file system close.
           *
           * *pipep points to pipe control structure. When the last user releases pipe,  
           * it will be set to NULL.
           */
          void pipe_release(  
           pipe_control_t **pipep,  
           rtems_libio_t *iop
           )
          {
           pipe_control_t *pipe = *pipep;
           uint32_t mode;
          
           #if defined(  RTEMS_DEBUG )
           /* WARN pipe not freed and pipep not set to NULL! */
           if (  pipe_lock(   ) )
           rtems_fatal_error_occurred(  0xdeadbeef );
          
           /* WARN pipe not released! */
           if (  !PIPE_LOCK(  pipe ) )
           rtems_fatal_error_occurred(  0xdeadbeef );
           #endif
          
           mode = LIBIO_ACCMODE(  iop );
           if (  mode & LIBIO_FLAGS_READ )
           pipe->Readers --;
           if (  mode & LIBIO_FLAGS_WRITE )
           pipe->Writers --;
          
           PIPE_UNLOCK(  pipe );
          
           if (  pipe->Readers == 0 && pipe->Writers == 0 ) {
          #if 0
           /* To delete an anonymous pipe file when all users closed it */
           if (  pipe->Anonymous )
           delfile = TRUE;
          #endif
           pipe_free(  pipe );
           *pipep = NULL;
           }
           else if (  pipe->Readers == 0 && mode != LIBIO_FLAGS_WRITE )
           /* Notify waiting Writers that all their partners left */
           PIPE_WAKEUPWRITERS(  pipe );
           else if (  pipe->Writers == 0 && mode != LIBIO_FLAGS_READ )
           PIPE_WAKEUPREADERS(  pipe );
          
           pipe_unlock(   );
          
          #if 0
           if (  ! delfile )
           return;
           if (  iop->pathinfo.ops->unlink_h == NULL )
           return;
          
           /* This is safe for IMFS,   but how about other FSes? */
           iop->flags &= ~LIBIO_FLAGS_OPEN;
           if(  iop->pathinfo.ops->unlink_h(  &iop->pathinfo ) )
           return;
          #endif
          
          }
     300  
          /*
           * Interface to file system open.
           *
           * *pipep points to pipe control structure. If called with *pipep = NULL,  
           * fifo_open will try allocating and initializing a control structure. If the
           * call succeeds,   *pipep will be set to address of new control structure.
           */
          int fifo_open(  
           pipe_control_t **pipep,  
           rtems_libio_t *iop
           )
          {
           pipe_control_t *pipe;
           unsigned int prevCounter;
           int err;
          
           err = pipe_new(  pipep );
           if (  err )
           return err;
           pipe = *pipep;
          
           switch (  LIBIO_ACCMODE(  iop ) ) {
           case LIBIO_FLAGS_READ:
           pipe->readerCounter ++;
           if (  pipe->Readers ++ == 0 )
           PIPE_WAKEUPWRITERS(  pipe );
          
           if (  pipe->Writers == 0 ) {
           /* Not an error */
           if (  LIBIO_NODELAY(  iop ) )
           break;
          
           prevCounter = pipe->writerCounter;
           err = -EINTR;
           /* Wait until a writer opens the pipe */
           do {
           PIPE_UNLOCK(  pipe );
           if (  ! PIPE_READWAIT(  pipe ) )
           goto out_error;
           if (  ! PIPE_LOCK(  pipe ) )
           goto out_error;
           } while (  prevCounter == pipe->writerCounter );
           }
           break;
          
           case LIBIO_FLAGS_WRITE:
           pipe->writerCounter ++;
          
           if (  pipe->Writers ++ == 0 )
           PIPE_WAKEUPREADERS(  pipe );
          
           if (  pipe->Readers == 0 && LIBIO_NODELAY(  iop ) ) {
           PIPE_UNLOCK(  pipe );
           err = -ENXIO;
           goto out_error;
           }
          
           if (  pipe->Readers == 0 ) {
           prevCounter = pipe->readerCounter;
           err = -EINTR;
           do {
           PIPE_UNLOCK(  pipe );
           if (  ! PIPE_WRITEWAIT(  pipe ) )
           goto out_error;
           if (  ! PIPE_LOCK(  pipe ) )
           goto out_error;
           } while (  prevCounter == pipe->readerCounter );
           }
           break;
          
           case LIBIO_FLAGS_READ_WRITE:
           pipe->readerCounter ++;
           if (  pipe->Readers ++ == 0 )
           PIPE_WAKEUPWRITERS(  pipe );
           pipe->writerCounter ++;
           if (  pipe->Writers ++ == 0 )
           PIPE_WAKEUPREADERS(  pipe );
           break;
           }
          
           PIPE_UNLOCK(  pipe );
           return 0;
          
     384  out_error:
           pipe_release(  pipep,   iop );
           return err;
          }
          
          /*
           * Interface to file system read.
           */
          ssize_t pipe_read(  
           pipe_control_t *pipe,  
           void *buffer,  
           size_t count,  
           rtems_libio_t *iop
           )
          {
           int chunk,   chunk1,   read = 0,   ret = 0;
          
           if (  ! PIPE_LOCK(  pipe ) )
           return -EINTR;
          
           while (  read < count ) {
           while (  PIPE_EMPTY(  pipe ) ) {
           /* Not an error */
           if (  pipe->Writers == 0 )
           goto out_locked;
          
           if (  LIBIO_NODELAY(  iop ) ) {
           ret = -EAGAIN;
           goto out_locked;
           }
          
           /* Wait until pipe is no more empty or no writer exists */
           pipe->waitingReaders ++;
           PIPE_UNLOCK(  pipe );
           if (  ! PIPE_READWAIT(  pipe ) )
           ret = -EINTR;
           if (  ! PIPE_LOCK(  pipe ) ) {
           /* WARN waitingReaders not restored! */
           ret = -EINTR;
           goto out_nolock;
           }
           pipe->waitingReaders --;
           if (  ret != 0 )
           goto out_locked;
           }
          
           /* Read chunk bytes */
           chunk = MIN(  count - read,   pipe->Length );
           chunk1 = pipe->Size - pipe->Start;
           if (  chunk > chunk1 ) {
           memcpy(  buffer + read,   pipe->Buffer + pipe->Start,   chunk1 );
           memcpy(  buffer + read + chunk1,   pipe->Buffer,   chunk - chunk1 );
           }
           else
           memcpy(  buffer + read,   pipe->Buffer + pipe->Start,   chunk );
          
           pipe->Start += chunk;
           pipe->Start %= pipe->Size;
           pipe->Length -= chunk;
           /* For buffering optimization */
           if (  PIPE_EMPTY(  pipe ) )
           pipe->Start = 0;
          
           if (  pipe->waitingWriters > 0 )
           PIPE_WAKEUPWRITERS(  pipe );
           read += chunk;
           }
          
          out_locked:
           PIPE_UNLOCK(  pipe );
          
          out_nolock:
     456   if (  read > 0 )
           return read;
           return ret;
          }
          
          /*
           * Interface to file system write.
           */
          ssize_t pipe_write(  
           pipe_control_t *pipe,  
           const void *buffer,  
           size_t count,  
           rtems_libio_t *iop
           )
          {
           int chunk,   chunk1,   written = 0,   ret = 0;
          
           /* Write nothing */
           if (  count == 0 )
           return 0;
          
           if (  ! PIPE_LOCK(  pipe ) )
           return -EINTR;
          
           if (  pipe->Readers == 0 ) {
           ret = -EPIPE;
           goto out_locked;
           }
          
           /* Write of PIPE_BUF bytes or less shall not be interleaved */
           chunk = count <= pipe->Size ? count : 1;
          
           while (  written < count ) {
           while (  PIPE_SPACE(  pipe ) < chunk ) {
           if (  LIBIO_NODELAY(  iop ) ) {
           ret = -EAGAIN;
           goto out_locked;
           }
          
           /* Wait until there is chunk bytes space or no reader exists */
           pipe->waitingWriters ++;
           PIPE_UNLOCK(  pipe );
           if (  ! PIPE_WRITEWAIT(  pipe ) )
           ret = -EINTR;
           if (  ! PIPE_LOCK(  pipe ) ) {
           /* WARN waitingWriters not restored! */
           ret = -EINTR;
           goto out_nolock;
           }
           pipe->waitingWriters --;
           if (  ret != 0 )
           goto out_locked;
          
           if (  pipe->Readers == 0 ) {
           ret = -EPIPE;
           goto out_locked;
           }
           }
          
           chunk = MIN(  count - written,   PIPE_SPACE(  pipe ) );
           chunk1 = pipe->Size - PIPE_WSTART(  pipe );
           if (  chunk > chunk1 ) {
           memcpy(  pipe->Buffer + PIPE_WSTART(  pipe ),   buffer + written,   chunk1 );
           memcpy(  pipe->Buffer,   buffer + written + chunk1,   chunk - chunk1 );
           }
           else
           memcpy(  pipe->Buffer + PIPE_WSTART(  pipe ),   buffer + written,   chunk );
          
           pipe->Length += chunk;
           if (  pipe->waitingReaders > 0 )
           PIPE_WAKEUPREADERS(  pipe );
           written += chunk;
           /* Write of more than PIPE_BUF bytes can be interleaved */
           chunk = 1;
           }
          
          out_locked:
           PIPE_UNLOCK(  pipe );
          
          out_nolock:
          #ifdef RTEMS_POSIX_API
           /* Signal SIGPIPE */
           if (  ret == -EPIPE )
           kill(  getpid(   ),   SIGPIPE );
          #endif
          
     542   if (  written > 0 )
           return written;
           return ret;
          }
          
          /*
           * Interface to file system ioctl.
           */
          int pipe_ioctl(  
           pipe_control_t *pipe,  
           uint32_t cmd,  
           void *buffer,  
           rtems_libio_t *iop
           )
          {
           if (  cmd == FIONREAD ) {
           if (  buffer == NULL )
           return -EFAULT;
          
           if (  ! PIPE_LOCK(  pipe ) )
           return -EINTR;
          
           /* Return length of pipe */
           *(  unsigned int * )buffer = pipe->Length;
           PIPE_UNLOCK(  pipe );
           return 0;
     568   }
          
           return -EINVAL;
          }
          
          /*
           * Interface to file system lseek.
           */
          int pipe_lseek(  
           pipe_control_t *pipe,  
           off_t offset,  
           int whence,  
           rtems_libio_t *iop
           )
          {
           /* Seek on pipe is not supported */
           return -ESPIPE;
          }

libfs/src/pipe/pipe.c

       1  /*
           * pipe.c: anonymous pipe
           *
           * Author: Wei Shen <cquark@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: pipe.c,  v 1.9 2010/08/28 19:49:47 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <fcntl.h>
          #include <rtems/libio_.h>
          #include <rtems/seterr.h>
          
          /* Incremental number added to names of anonymous pipe files */
          /* FIXME: This approach is questionable */
          static uint16_t rtems_pipe_no = 0;
          
          /*
           * Called by pipe(   ) to create an anonymous pipe.
           */
      29  int pipe_create(  
           int filsdes[2]
           )
          {
           rtems_libio_t *iop;
           int err = 0;
          
           if (  rtems_mkdir(  "/tmp",   S_IRWXU | S_IRWXG | S_IRWXO ) != 0 )
           return -1;
          
           /* /tmp/.fifoXXXX */
           char fifopath[15];
           memcpy(  fifopath,   "/tmp/.fifo",   10 );
           sprintf(  fifopath + 10,   "%04x",   rtems_pipe_no ++ );
          
           /* Try creating FIFO file until find an available file name */
           while (  mkfifo(  fifopath,   S_IRUSR|S_IWUSR ) != 0 ) {
           if (  errno != EEXIST ){
           return -1;
           }
           /* Just try once... */
           return -1;
           /* sprintf(  fifopath + 10,   "%04x",   rtems_pipe_no ++ ); */
           }
          
           /* Non-blocking open to avoid waiting for writers */
           filsdes[0] = open(  fifopath,   O_RDONLY | O_NONBLOCK );
           if (  filsdes[0] < 0 ) {
           err = errno;
           /* Delete file at errors,   or else if pipe is successfully created
           the file node will be deleted after it is closed by all. */
           unlink(  fifopath );
           }
           else {
           /* Reset open file to blocking mode */
           iop = rtems_libio_iop(  filsdes[0] );
           iop->flags &= ~LIBIO_FLAGS_NO_DELAY;
          
           filsdes[1] = open(  fifopath,   O_WRONLY );
          
           if (  filsdes[1] < 0 ) {
           err = errno;
           close(  filsdes[0] );
           }
           unlink(  fifopath );
           }
           if(  err != 0 )
           rtems_set_errno_and_return_minus_one(  err );
           return 0;
          }
          

libfs/src/rfs/rtems-rfs-bitmaps-ut.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-bitmaps-ut.c,  v 1.6 2010/06/17 02:48:37 ralf Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Bitmap Unit Test..
           *
           * This is a unit test module for the bit map functions.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <stdlib.h>
          #include <inttypes.h>
          
          #include <rtems/rfs/rtems-rfs-bitmaps.h>
          #include <rtems/rfs/rtems-rfs-file-system.h>
          
          #define rtems_rfs_exit_on_error(  _rc,   _r,   _c,   _b ) \
           if (  (  _rc > 0 ) || _r ) { free (  _b ); rtems_rfs_bitmap_close (  _c ); return; }
          
      34  static bool
          rtems_rfs_bitmap_ut_test_range (  rtems_rfs_bitmap_control* control,  
           int test,  
           bool set,  
           rtems_rfs_bitmap_bit bit,  
           size_t size )
          {
           unsigned int count;
           bool result;
           for (  count = 0; count < size; count++ )
           {
           int rc = rtems_rfs_bitmap_map_test (  control,   bit + count,   &result );
           if (  rc > 0 )
           {
           printf (  " %2d. Test bit %" PRId32 " in range (  %" PRId32 ",  %ld] is %s: ",  
           test,   bit + count,   bit,   bit + size - 1,   !set ? "set" : "clear" );
           printf (  "FAIL (  %s )\n",   strerror (  rc ) );
           return false;
           }
           if (  !set )
           result = !result;
           if (  !result )
           {
           printf (  " %2d. Test bit %" PRId32 " in range (  %" PRId32 ",  %ld] is %s: ",  
           test,   bit + count,   bit,   bit + size - 1,   !set ? "set" : "clear" );
           printf (  " %s\n",   !result ? "pass" : "FAIL" );
           return false;
           }
           }
          
           printf (  " %2d. Test bit range (  %" PRId32 ",  %ld] all %s: pass\n",  
           test,   bit,   bit + size - 1,   set ? "set" : "clear" );
          
           return true;
          }
          
      70  static bool
          rtems_rfs_bitmap_ut_alloc_seq_test (  rtems_rfs_bitmap_control* control,  
           int test,  
           rtems_rfs_bitmap_bit bit,  
           size_t size )
          {
           bool state;
           int i;
           int rc;
          
           printf (  " %2d. Set all bits\n",   test );
           rc = rtems_rfs_bitmap_map_set_all (  control );
           if (  rc > 0 )
           {
           printf (  " %2d. set all bits: FAIL (  %s )\n",   test,   strerror (  rc ) );
           return false;
           }
          
           for (  i = 0; i < size; i++ )
           rtems_rfs_bitmap_map_clear (  control,   bit + i );
          
           printf (  " %2d. Cleared bits (  %" PRId32 ",   %ld] (  %zd )\n",  
           test,   bit,   bit + size - 1,   size );
          
           for (  i = 0; i < rtems_rfs_bitmap_element_bits (   ); i++ )
           {
           rc = rtems_rfs_bitmap_map_test (  control,   bit + i,   &state );
           if (  rc > 0 )
           {
           printf (  " %2d. test bit: FAIL (  %s )\n",   test,   strerror (  rc ) );
           return false;
           }
           if (  state )
           {
           printf (  " %2d. Cleared bit still set: bit = %" PRId32 "\n",   test,   bit + i );
           return false;
           }
           }
          
           for (  i = 0,   bit = 0; i < size; i++ )
           {
           rtems_rfs_bitmap_bit seed = bit;
           bool result;
           int rc;
           rc = rtems_rfs_bitmap_map_alloc (  control,   seed,   &result,   &bit );
           if (  rc > 0 )
           {
           printf (  " %2d. map all: FAIL (  %s )\n",   test,   strerror (  rc ) );
           return false;
           }
           if (  !result )
           {
           printf (  " %2d. Find bit with seed = %" PRId32 ": %s: bit = %" PRId32 "\n",  
           test,   seed,   result ? "pass" : "FAIL",   bit );
           return false;
           }
           }
          
           printf (  " %2d. Alloc'ed all bits (  %" PRId32 ",   %ld] (  %zd )\n",  
           test,   bit,   bit + size - 1,   size );
          
           return true;
          }
          
     134  static void
          rtems_rfs_bitmap_ut_test_bitmap (  size_t size )
          {
           rtems_rfs_file_system fs;
           rtems_rfs_bitmap_control control;
           rtems_rfs_buffer_handle handle;
           rtems_rfs_buffer buffer;
           rtems_rfs_bitmap_bit bit = 0;
           rtems_rfs_bitmap_bit first_bit;
           rtems_rfs_bitmap_bit last_bit;
           bool result;
           size_t bytes;
           size_t clear;
           int rc;
          
           bytes = (  rtems_rfs_bitmap_elements (  size ) *
           sizeof (  rtems_rfs_bitmap_element ) );
          
           memset (  &fs,   0,   sizeof (  fs ) );
           memset (  &buffer,   0,   sizeof (  buffer ) );
          
           buffer.buffer = malloc (  bytes );
           buffer.block = 1;
          
           if (  !buffer.buffer )
           {
           printf (  " Cannot allocate bitmap memory\n" );
           return;
           }
          
          #if RTEMS_RFS_BITMAP_CLEAR_ZERO
           memset (  buffer.buffer,   0,   bytes );
          #else
           memset (  buffer.buffer,   0xff,   bytes );
          #endif
          
           /*
           * Do not close the handle so no writes need occur.
           */
           rc = rtems_rfs_buffer_handle_open (  &fs,   &handle );
           if (  rc > 0 )
           {
           printf (  " Cannot open the handle: %d: %s\n",   rc,   strerror (  rc ) );
           free (  buffer.buffer );
           return;
           }
          
           handle.buffer = &buffer;
           handle.bnum = 1;
          
           printf (  "\nRFS Bitmap Test : size = %zd (  %zd )\n",  
           size,   rtems_rfs_bitmap_elements (  size ) );
           rc = rtems_rfs_bitmap_open (  &control,   &fs,   &handle,   size,   1 );
           if (  rc > 0 )
           {
           printf (  " Cannot open the bitmap: %s\n",   strerror (  rc ) );
           free (  buffer.buffer );
           return;
           }
          
           /*
           * This is a new bitmap with no bits set. Try and find a bit with a few
           * seeds.
           */
           rc = rtems_rfs_bitmap_map_alloc (  &control,   size * 2,   &result,   &bit );
           printf (  " 1. Find bit with seed > size: %s (  %s )\n",  
           result ? "FAIL" : "pass",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   result,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_alloc (  &control,   size,   &result,   &bit );
           printf (  " 2. Find bit with seed = size: %s (  %s )\n",  
           result ? "FAIL" : "pass",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   result,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_alloc (  &control,   0,   &result,   &bit );
           result = result && (  bit == 0 );
           printf (  " 3. Find bit 0 with seed = 0: %s (  %s ): bit = %" PRId32 "\n",  
           result ? "pass" : "FAIL",   strerror (  rc ),   bit );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_alloc (  &control,   size - 1,   &result,   &bit );
           result = result && (  bit == (  size - 1 ) );
           printf (  " 4. Find bit (  size - 1 ) with seed = (  size - 1 ) (  %zd ): %s (  %s ): bit = %" PRId32 "\n",  
           size - 1,   result ? "pass" : "FAIL",   strerror (  rc ),   bit );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
          
           /*
           * Test the bits allocated to make sure they are set.
           */
          
           rc = rtems_rfs_bitmap_map_test (  &control,   0,   &result );
           printf (  " 5. Test bit 0: %s (  %s )\n",  
           result ? "pass" : "FAIL",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_test (  &control,   size - 1,   &result );
           printf (  " 6. Test bit (  size - 1 ) (  %zd ): %s (  %s )\n",  
           size - 1,   result ? "pass" : "FAIL",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           if (  !rtems_rfs_bitmap_ut_test_range (  &control,   7,   false,   1,   size - 2 ) )
           rtems_rfs_exit_on_error (  0,   !result,   &control,   buffer.buffer );
          
           /*
           * Set all bits then clear one and find it.
           */
           rc = rtems_rfs_bitmap_map_set_all (  &control );
           printf (  " 8. Set all bits: %s (  %s )\n",  
           rc == 0 ? "PASS" : "FAIL",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   false,   &control,   buffer.buffer );
          
           bit = rand (   ) % size;
          
           rc = rtems_rfs_bitmap_map_clear (  &control,   bit );
           printf (  " 9. Clear bit %" PRId32 ": %s (  %s )\n",  
           bit,   rc == 0 ? "PASS" : "FAIL",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   false,   &control,   buffer.buffer );
          
           last_bit = bit;
           rc = rtems_rfs_bitmap_map_alloc (  &control,   0,   &result,   &bit );
           result = result && (  bit == last_bit );
           printf (  " 10. Find bit with seed = 0: %s (  %s ): bit = %" PRId32 "\n",  
           result ? "pass" : "FAIL",   strerror (  rc ),   bit );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_alloc (  &control,   0,   &result,   &bit );
           result = !result || (  bit != last_bit );
           printf (  " 11. Fail to find bit with seed = 0: %s (  %s ): bit = %" PRId32 "\n",  
           result ? "pass" : "FAIL",   strerror (  rc ),   bit );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_clear (  &control,   0 );
           printf (  " 12. Clear bit 0: %s (  %s )\n",  
           rc == 0 ? "pass" : "FAIL",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   false,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_alloc (  &control,   size - 1,   &result,   &bit );
           result = result && (  bit == 0 );
           printf (  " 13. Find bit with seed = (  size - 1 ): %s (  %s ): bit = %" PRId32 "\n",  
           result ? "pass" : "FAIL",   strerror (  rc ),   bit );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_clear (  &control,   size - 1 );
           printf (  " 14. Clear bit (  size - 1 ) (  %zd ): %s (  %s )\n",  
           size - 1,   rc == 0 ? "pass" : "FAIL",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   false,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_alloc (  &control,   0,   &result,   &bit );
           result = result && (  bit == (  size - 1 ) );
           printf (  " 15. Find bit with seed = 0: %s (  %s ): bit = %" PRId32 "\n",  
           result ? "pass" : "FAIL",   strerror (  rc ),   bit );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_clear (  &control,   0 );
           printf (  " 16. Clear bit 0: %s (  %s )\n",  
           rc == 0 ? "pass" : "FAIL",   strerror (  rc ) );
          
           rc = rtems_rfs_bitmap_map_alloc (  &control,   size / 2,   &result,   &bit );
           result = result && (  bit == 0 );
           printf (  " 17. Find bit with seed = (  size / 2 ) (  %zd ): %s (  %s ): bit = %" PRId32 "\n",  
           size / 2,   result ? "pass" : "FAIL",   strerror (  rc ),   bit );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_clear (  &control,   size - 1 );
           printf (  " 18. Clear bit (  size - 1 ) (  %zd ): %s,   (  %s )\n",  
           size - 1,   rc == 0 ? "pass" : "FAIL",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   false,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_alloc (  &control,   size / 2,   &result,   &bit );
           result = result && (  bit == (  size - 1 ) );
           printf (  " 19. Find bit with seed = (  size / 2 ) (  %zd ): %s (  %s ): bit = %" PRId32 "\n",  
           size / 2,   result ? "pass" : "FAIL",   strerror (  rc ),   bit );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_clear (  &control,   0 );
           printf (  " 20. Clear bit 0: %s (  %s )\n",  
           rc == 0 ? "pass" : "FAIL",   strerror (  rc ) );
          
           rc = rtems_rfs_bitmap_map_alloc (  &control,   (  size / 2 ) - 1,   &result,   &bit );
           result = result && (  bit == 0 );
           printf (  " 21. Find bit with seed = (  (  size / 2 ) - 1 ) (  %zd ): %s (  %s ): bit = %" PRId32 "\n",  
           (  size / 2 ) - 1,   result ? "pass" : "FAIL",   strerror (  rc ),   bit );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           rc = rtems_rfs_bitmap_map_clear (  &control,   size - 1 );
           printf (  " 22. Clear bit (  size - 1 ) (  %zd ): %s (  %s )\n",  
           size - 1,   rc == 0 ? "pass" : "FAIL",   strerror (  rc ) );
          
           rc = rtems_rfs_bitmap_map_alloc (  &control,   (  size / 2 ) - 1,   &result,   &bit );
           result = result && (  bit == (  size - 1 ) );
           printf (  " 23. Find bit with seed = (  (  size / 2 ) - 1 ) (  %zd ): %s (  %s ): bit = %" PRId32 "\n",  
           (  size / 2 ) - 1,   result ? "pass" : "FAIL",   strerror (  rc ),   bit );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           bit = rand (   ) % (  size / 2 ) + rtems_rfs_bitmap_element_bits (   );
           result = rtems_rfs_bitmap_ut_alloc_seq_test (  &control,   23,   bit,  
           rtems_rfs_bitmap_element_bits (   ) );
           rtems_rfs_exit_on_error (  0,   !result,   &control,   buffer.buffer );
          
           bit = rand (   ) % (  size / 2 ) + rtems_rfs_bitmap_element_bits (   );
           result = rtems_rfs_bitmap_ut_alloc_seq_test (  &control,   24,   bit,   57 );
           rtems_rfs_exit_on_error (  0,   !result,   &control,   buffer.buffer );
          
           /*
           * Set all bits,   clear a random numberone then create a search map and make
           * sure the clear count is correct.
           */
           rc = rtems_rfs_bitmap_map_set_all (  &control );
           printf (  " 25. Set all bits: %s (  %s )\n",  
           rc == 0 ? "PASS" : "FAIL",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   false,   &control,   buffer.buffer );
          
           first_bit = rand (   ) % (  size / 2 ) + rtems_rfs_bitmap_element_bits (   );
           last_bit = first_bit + rand (   ) % (  size / 2 ) + rtems_rfs_bitmap_element_bits (   );
          
           for (  bit = first_bit; bit < last_bit; bit++ )
           {
           rc = rtems_rfs_bitmap_map_clear (  &control,   bit );
           if (  rc > 0 )
           {
           printf (  " 26. Clear bit %" PRId32 ": %s (  %s )\n",  
           bit,   rc == 0 ? "PASS" : "FAIL",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   false,   &control,   buffer.buffer );
           }
           }
          
           printf (  " 26. Clear bit (  %" PRId32 ",   %" PRId32 "]: %s (  %s )\n",  
           first_bit,   last_bit,   rc == 0 ? "PASS" : "FAIL",   strerror (  rc ) );
          
           clear = rtems_rfs_bitmap_map_free (  &control );
           result = clear == (  last_bit - first_bit );
           printf (  " 27. Check free count is %zd: %" PRId32 ": %s (  %s )\n",  
           clear,   last_bit - first_bit,  
           result ? "pass" : "FAIL",   strerror (  rc ) );
          
           rc = rtems_rfs_bitmap_create_search (  &control );
           result = clear == rtems_rfs_bitmap_map_free (  &control );
           printf (  " 28. Create search check free count is %zd: %zd: %s (  %s )\n",  
           clear,   rtems_rfs_bitmap_map_free (  &control ),  
           result ? "pass" : "FAIL",   strerror (  rc ) );
           rtems_rfs_exit_on_error (  rc,   !result,   &control,   buffer.buffer );
          
           rtems_rfs_bitmap_close (  &control );
           free (  buffer.buffer );
          }
          
     381  void
          rtems_rfs_bitmap_unit_test (  void )
          {
           printf (  "RTEMS File System Bitmap Unit Test\n" );
           printf (  " Bit set value : %d\n",   RTEMS_RFS_BITMAP_BIT_SET );
           printf (  " Bit clear value : %d\n",   RTEMS_RFS_BITMAP_BIT_CLEAR );
           printf (  " Num bit per element : %zd\n",   rtems_rfs_bitmap_element_bits (   ) );
          
          #if INT_MAX >= 0x23984237
           srand (  0x23984237 );
          #else
           srand (  0x2398 );
          #endif
          
           rtems_rfs_bitmap_ut_test_bitmap (  2048 );
           rtems_rfs_bitmap_ut_test_bitmap (  420 );
          }
          

libfs/src/rfs/rtems-rfs-bitmaps.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-bitmaps.c,  v 1.2 2010/03/27 04:04:40 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Bitmap Routines.
           *
           * These functions manage bit maps. A bit map consists of the map of bit
           * allocated in a block and a search map where a bit represents 32 actual
           * bits. The search map allows for a faster search for an available bit as 32
           * search bits can checked in a test.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /**
           * Set to 1 to enable warnings when developing.
           */
          #define RTEMS_RFS_BITMAP_WARNINGS 0
          
          #if RTEMS_RFS_BITMAP_WARNINGS
          #include <stdio.h>
          #endif
          #include <stdlib.h>
          #include <rtems/rfs/rtems-rfs-bitmaps.h>
          
          /**
           * Test a bit in an element. If set return true else return false.
           *
           * @param target The target to test the bit in.
           * @param bit The bit to test.
           * @retval true The bit is set.
           * @retval false The bit is clear.
           */
          static bool
      47  rtems_rfs_bitmap_test (  rtems_rfs_bitmap_element target,  
           rtems_rfs_bitmap_bit bit )
          {
           return RTEMS_RFS_BITMAP_TEST_BIT (  target,   bit );
          }
          
          /**
           * Set the bits in the element. Bits not set in the bit argument are left
           * unchanged.
           *
           * @param target The target element bits are set.
           * @param bits The bits in the target to set. A 1 in the bits will set the
           * same bit in the target.
           */
          static rtems_rfs_bitmap_element
      62  rtems_rfs_bitmap_set (  rtems_rfs_bitmap_element target,  
           rtems_rfs_bitmap_element bits )
          {
           return RTEMS_RFS_BITMAP_SET_BITS (  target,   bits );
          }
          
          /**
           * Clear the bits in the element. Bits not set in the bit argument are left
           * unchanged.
           *
           * @param target The target element to clear the bits in.
           * @param bits The bits in the target to clear. A 1 in the bits will clear the
           * bit in the target.
           */
          static rtems_rfs_bitmap_element
      77  rtems_rfs_bitmap_clear (  rtems_rfs_bitmap_element target,  
           rtems_rfs_bitmap_element bits )
          {
           return RTEMS_RFS_BITMAP_CLEAR_BITS (  target,   bits );
          }
          
          /**
           * Merge the bits in 2 variables based on the mask. A set bit in the mask will
           * merge the bits from bits1 and a clear bit will merge the bits from bits2.
           * The mask is always defined as 1 being set and 0 being clear.
           */
          static rtems_rfs_bitmap_element
      89  rtems_rfs_bitmap_merge (  rtems_rfs_bitmap_element bits1,  
           rtems_rfs_bitmap_element bits2,  
           rtems_rfs_bitmap_element mask )
          {
           /*
           * Use the normal bit operators because we do not change the bits just merge
           * the 2 separate parts.
           */
           bits1 &= mask;
           bits2 &= RTEMS_RFS_BITMAP_INVERT_MASK (  mask );
           return bits1 | bits2;
          }
          
          /**
           * Match the bits of 2 elements and return true if they match else return
           * false.
           *
           * @param bits1 One set of bits to match.
           * @param bits2 The second set of bits to match.
           * @retval true The bits match.
           * @retval false The bits do not match.
           */
          static bool
     112  rtems_rfs_bitmap_match (  rtems_rfs_bitmap_element bits1,  
           rtems_rfs_bitmap_element bits2 )
          {
           return bits1 ^ bits2 ? false : true;
          }
          
          #if RTEMS_NOT_USED_BUT_KEPT
          /**
           * Match the bits of 2 elements within the mask and return true if they match
           * else return false.
           *
           * @param mask The mask over which the match occurs. A 1 is a valid mask bit.
           * @param bits1 One set of bits to match.
           * @param bits2 The second set of bits to match.
           * @retval true The bits match.
           * @retval false The bits do not match.
           */
          static bool
     130  rtems_rfs_bitmap_match_masked (  rtems_rfs_bitmap_element mask,  
           rtems_rfs_bitmap_element bits1,  
           rtems_rfs_bitmap_element bits2 )
          {
           return (  bits1 ^ bits2 ) & mask ? false : true;
          }
          #endif
          
          /**
           * Return the map after loading from disk if not already loaded.
           *
           * @param control The bitmap control.
           * @param rtems_rfs_bitmap_map* Pointer to the bitmap map data if no error.
           * @return int The error number (  errno ). No error if 0.
           */
          static int
     146  rtems_rfs_bitmap_load_map (  rtems_rfs_bitmap_control* control,  
           rtems_rfs_bitmap_map* map )
          {
           int rc;
          
           if (  !control->buffer )
           return ENXIO;
          
           *map = NULL;
          
           rc = rtems_rfs_buffer_handle_request (  control->fs,  
           control->buffer,  
           control->block,  
           true );
           if (  rc )
           return rc;
          
           *map = rtems_rfs_buffer_data (  control->buffer );
           return 0;
          }
          
          rtems_rfs_bitmap_element
     168  rtems_rfs_bitmap_mask (  unsigned int size )
          {
           rtems_rfs_bitmap_element mask = RTEMS_RFS_BITMAP_ELEMENT_FULL_MASK;
           mask >>= (  rtems_rfs_bitmap_element_bits (   ) - size );
           return mask;
          }
          
          rtems_rfs_bitmap_element
     176  rtems_rfs_bitmap_mask_section (  unsigned int start,   unsigned int end )
          {
           rtems_rfs_bitmap_element mask = 0;
           if (  end > start )
           mask = rtems_rfs_bitmap_mask (  end - start ) << start;
           return mask;
          }
          
          int
     185  rtems_rfs_bitmap_map_set (  rtems_rfs_bitmap_control* control,  
           rtems_rfs_bitmap_bit bit )
          {
           rtems_rfs_bitmap_map map;
           rtems_rfs_bitmap_map search_map;
           int index;
           int offset;
           int rc;
           rc = rtems_rfs_bitmap_load_map (  control,   &map );
           if (  rc > 0 )
           return rc;
           if (  bit >= control->size )
           return EINVAL;
           search_map = control->search_bits;
           index = rtems_rfs_bitmap_map_index (  bit );
           offset = rtems_rfs_bitmap_map_offset (  bit );
           map[index] = rtems_rfs_bitmap_set (  map[index],   1 << offset );
           if (  rtems_rfs_bitmap_match(  map[index],   RTEMS_RFS_BITMAP_ELEMENT_SET ) )
           {
           bit = index;
           index = rtems_rfs_bitmap_map_index (  bit );
           offset = rtems_rfs_bitmap_map_offset (  bit );
           search_map[index] = rtems_rfs_bitmap_set (  search_map[index],   1 << offset );
           control->free--;
           rtems_rfs_buffer_mark_dirty (  control->buffer );
           }
           return 0;
          }
          
          int
     215  rtems_rfs_bitmap_map_clear (  rtems_rfs_bitmap_control* control,  
           rtems_rfs_bitmap_bit bit )
          {
           rtems_rfs_bitmap_map map;
           rtems_rfs_bitmap_map search_map;
           int index;
           int offset;
           int rc;
           rc = rtems_rfs_bitmap_load_map (  control,   &map );
           if (  rc > 0 )
           return rc;
           if (  bit >= control->size )
           return EINVAL;
           search_map = control->search_bits;
           index = rtems_rfs_bitmap_map_index (  bit );
           offset = rtems_rfs_bitmap_map_offset (  bit );
           map[index] = rtems_rfs_bitmap_clear (  map[index],   1 << offset );
           bit = index;
           index = rtems_rfs_bitmap_map_index (  bit );
           offset = rtems_rfs_bitmap_map_offset(  bit );
           search_map[index] = rtems_rfs_bitmap_clear (  search_map[index],   1 << offset );
           rtems_rfs_buffer_mark_dirty (  control->buffer );
           control->free++;
           return 0;
          }
          
          int
     242  rtems_rfs_bitmap_map_test (  rtems_rfs_bitmap_control* control,  
           rtems_rfs_bitmap_bit bit,  
           bool* state )
          {
           rtems_rfs_bitmap_map map;
           int index;
           int rc;
           rc = rtems_rfs_bitmap_load_map (  control,   &map );
           if (  rc > 0 )
           return rc;
           if (  bit >= control->size )
           return EINVAL;
           index = rtems_rfs_bitmap_map_index (  bit );
           *state = rtems_rfs_bitmap_test (  map[index],   bit );
           return 0;
          }
          
          int
     260  rtems_rfs_bitmap_map_set_all (  rtems_rfs_bitmap_control* control )
          {
           rtems_rfs_bitmap_map map;
           size_t elements;
           int e;
           int rc;
          
           rc = rtems_rfs_bitmap_load_map (  control,   &map );
           if (  rc > 0 )
           return rc;
          
           elements = rtems_rfs_bitmap_elements (  control->size );
          
           control->free = 0;
          
           for (  e = 0; e < elements; e++ )
           map[e] = RTEMS_RFS_BITMAP_ELEMENT_SET;
          
           elements = rtems_rfs_bitmap_elements (  elements );
          
           for (  e = 0; e < elements; e++ )
           control->search_bits[e] = RTEMS_RFS_BITMAP_ELEMENT_SET;
          
           rtems_rfs_buffer_mark_dirty (  control->buffer );
          
           return 0;
          }
          
          int
     289  rtems_rfs_bitmap_map_clear_all (  rtems_rfs_bitmap_control* control )
          {
           rtems_rfs_bitmap_map map;
           rtems_rfs_bitmap_bit last_search_bit;
           size_t elements;
           int e;
           int rc;
          
           rc = rtems_rfs_bitmap_load_map (  control,   &map );
           if (  rc > 0 )
           return rc;
          
           elements = rtems_rfs_bitmap_elements (  control->size );
          
           control->free = elements;
          
           for (  e = 0; e < elements; e++ )
           map[e] = RTEMS_RFS_BITMAP_ELEMENT_CLEAR;
          
           /*
           * Set the un-mapped bits in the last search element so the available logic
           * works.
           */
           last_search_bit = rtems_rfs_bitmap_map_offset (  elements );
          
           if (  last_search_bit == 0 )
           last_search_bit = rtems_rfs_bitmap_element_bits (   );
          
           elements = rtems_rfs_bitmap_elements (  elements );
          
           for (  e = 0; e < (  elements - 1 ); e++ )
           control->search_bits[e] = RTEMS_RFS_BITMAP_ELEMENT_CLEAR;
          
           control->search_bits[elements - 1] =
           rtems_rfs_bitmap_merge (  RTEMS_RFS_BITMAP_ELEMENT_CLEAR,  
           RTEMS_RFS_BITMAP_ELEMENT_SET,  
           rtems_rfs_bitmap_mask (  last_search_bit ) );
          
           rtems_rfs_buffer_mark_dirty (  control->buffer );
          
           return 0;
          }
          
          static int
     333  rtems_rfs_search_map_for_clear_bit (  rtems_rfs_bitmap_control* control,  
           rtems_rfs_bitmap_bit* bit,  
           bool* found,  
           size_t window,  
           int direction )
          {
           rtems_rfs_bitmap_map map;
           rtems_rfs_bitmap_bit test_bit;
           rtems_rfs_bitmap_bit end_bit;
           rtems_rfs_bitmap_element* search_bits;
           int search_index;
           int search_offset;
           rtems_rfs_bitmap_element* map_bits;
           int map_index;
           int map_offset;
           int rc;
          
           *found = false;
          
           /*
           * Load the bitmap.
           */
           rc = rtems_rfs_bitmap_load_map (  control,   &map );
           if (  rc > 0 )
           return rc;
          
           /*
           * Calculate the bit we are testing plus the end point we search over.
           */
           test_bit = *bit;
           end_bit = test_bit + (  window * direction );
          
           if (  end_bit < 0 )
           end_bit = 0;
           else if (  end_bit >= control->size )
           end_bit = control->size - 1;
          
           map_index = rtems_rfs_bitmap_map_index (  test_bit );
           map_offset = rtems_rfs_bitmap_map_offset (  test_bit );
           search_index = rtems_rfs_bitmap_map_index (  map_index );
           search_offset = rtems_rfs_bitmap_map_offset (  map_index );
          
           search_bits = &control->search_bits[search_index];
           map_bits = &map[map_index];
          
           /*
           * Check each bit from the search map offset for a clear bit.
           */
           do
           {
           /*
           * If any bit is clear find that bit and then search the map element. If
           * all bits are set there are no map bits so move to the next search
           * element.
           */
           if (  !rtems_rfs_bitmap_match (  *search_bits,   RTEMS_RFS_BITMAP_ELEMENT_SET ) )
           {
           while (  (  search_offset >= 0 )
           && (  search_offset < rtems_rfs_bitmap_element_bits (   ) ) )
           {
           if (  !rtems_rfs_bitmap_test (  *search_bits,   search_offset ) )
           {
           /*
           * Find the clear bit in the map. Update the search map and map if
           * found. We may find none are spare if searching up from the seed.
           */
           while (  (  map_offset >= 0 )
           && (  map_offset < rtems_rfs_bitmap_element_bits (   ) ) )
           {
           if (  !rtems_rfs_bitmap_test (  *map_bits,   map_offset ) )
           {
           *map_bits = rtems_rfs_bitmap_set (  *map_bits,   1 << map_offset );
           if (  rtems_rfs_bitmap_match(  *map_bits,  
           RTEMS_RFS_BITMAP_ELEMENT_SET ) )
           *search_bits = rtems_rfs_bitmap_set (  *search_bits,  
           1 << search_offset );
           control->free--;
           *bit = test_bit;
           *found = true;
           rtems_rfs_buffer_mark_dirty (  control->buffer );
           return 0;
           }
          
           if (  test_bit == end_bit )
           break;
          
           map_offset += direction;
           test_bit += direction;
           }
           }
          
           map_bits += direction;
           map_index += direction;
           map_offset = direction > 0 ? 0 : rtems_rfs_bitmap_element_bits (   ) - 1;
          
           test_bit = (  map_index * rtems_rfs_bitmap_element_bits (   ) ) + map_offset;
          
           search_offset += direction;
          
           if (  (  (  direction < 0 ) && (  test_bit <= end_bit ) )
           || (  (  direction > 0 ) && (  test_bit >= end_bit ) ) )
           break;
           }
           }
           else
           {
           /*
           * Move to the next search element. We need to determine the number of
           * bits in the search offset that are being skipped so the map bits
           * pointer can be updated. If we are moving down and we have a search
           * offset of 0 then the search map adjustment is to the top bit of the
           * pervious search bit's value.
           *
           * Align test_bit either up or down depending on the direction to next 32
           * bit boundary.
           */
           rtems_rfs_bitmap_bit bits_skipped;
           test_bit &= ~(  (  1 << RTEMS_RFS_ELEMENT_BITS_POWER_2 ) - 1 );
           if (  direction > 0 )
           {
           bits_skipped = rtems_rfs_bitmap_element_bits (   ) - search_offset;
           test_bit += bits_skipped * rtems_rfs_bitmap_element_bits (   );
           map_offset = 0;
           }
           else
           {
           bits_skipped = search_offset + 1;
           /*
           * Need to remove 1 for the rounding up. The above rounds down and
           * adds 1. Remember the logic is for subtraction.
           */
           test_bit -= (  (  bits_skipped - 1 ) * rtems_rfs_bitmap_element_bits (   ) ) + 1;
           map_offset = rtems_rfs_bitmap_element_bits (   ) - 1;
           }
           map_bits += direction * bits_skipped;
           map_index += direction * bits_skipped;
           }
          
           search_bits += direction;
           search_offset = direction > 0 ? 0 : rtems_rfs_bitmap_element_bits (   ) - 1;
           }
           while (  (  (  direction < 0 ) && (  test_bit >= end_bit ) )
           || (  (  direction > 0 ) && (  test_bit <= end_bit ) ) );
          
           return 0;
          }
          
          int
     481  rtems_rfs_bitmap_map_alloc (  rtems_rfs_bitmap_control* control,  
           rtems_rfs_bitmap_bit seed,  
           bool* allocated,  
           rtems_rfs_bitmap_bit* bit )
          {
           rtems_rfs_bitmap_bit upper_seed;
           rtems_rfs_bitmap_bit lower_seed;
           rtems_rfs_bitmap_bit window; /* may become a parameter */
           int rc = 0;
          
           /*
           * By default we assume the allocation failed.
           */
           *allocated = false;
          
           /*
           * The window is the number of bits we search over in either direction each
           * time.
           */
           window = RTEMS_RFS_BITMAP_SEARCH_WINDOW;
          
           /*
           * Start from the seed and move in either direction. Search in window amounts
           * of bits from the original seed above then below. That is search from the
           * seed up then from the seed down a window number of bits,   then repeat the
           * process from the window distance from the seed,   again above then
           * below. Keep moving out until all bits have been searched.
           */
           upper_seed = seed;
           lower_seed = seed;
          
           /*
           * If the upper and lower seed values have reached the limits of the bitmap
           * we have searched all of the map. The seed may not be aligned to a window
           * boundary so we may need to search a partial window and this may also not
           * be balanced for the upper or lower seeds. We move to the limits,   search
           * then return false if no clear bits are found.
           */
           while (  (  (  upper_seed >= 0 ) && (  upper_seed < control->size ) )
           || (  (  lower_seed >= 0 ) && (  lower_seed < control->size ) ) )
           {
           /*
           * Search up first so bits allocated in succession are grouped together.
           */
           if (  upper_seed < control->size )
           {
           *bit = upper_seed;
           rc = rtems_rfs_search_map_for_clear_bit (  control,   bit,   allocated,  
           window,   1 );
           if (  (  rc > 0 ) || *allocated )
           break;
           }
          
           if (  lower_seed >= 0 )
           {
           *bit = lower_seed;
           rc = rtems_rfs_search_map_for_clear_bit (  control,   bit,   allocated,  
           window,   -1 );
           if (  (  rc > 0 ) || *allocated )
           break;
           }
          
           /*
           * Do not bound the limits at the edges of the map. Do not update if an
           * edge has been passed.
           */
           if (  upper_seed < control->size )
           upper_seed += window;
           if (  lower_seed >= 0 )
           lower_seed -= window;
           }
          
           return 0;
          }
          
          int
     557  rtems_rfs_bitmap_create_search (  rtems_rfs_bitmap_control* control )
          {
           rtems_rfs_bitmap_map search_map;
           rtems_rfs_bitmap_map map;
           size_t size;
           rtems_rfs_bitmap_bit bit;
           int rc;
          
           rc = rtems_rfs_bitmap_load_map (  control,   &map );
           if (  rc > 0 )
           return rc;
          
           control->free = 0;
           search_map = control->search_bits;
           size = control->size;
           bit = 0;
          
           *search_map = RTEMS_RFS_BITMAP_ELEMENT_CLEAR;
           while (  size )
           {
           rtems_rfs_bitmap_element bits;
           int available;
           if (  size < rtems_rfs_bitmap_element_bits (   ) )
           {
           bits = rtems_rfs_bitmap_merge (  *map,  
           RTEMS_RFS_BITMAP_ELEMENT_SET,  
           rtems_rfs_bitmap_mask_section (  0,   size ) );
           available = size;
           }
           else
           {
           bits = *map;
           available = rtems_rfs_bitmap_element_bits (   );
           }
          
           if (  rtems_rfs_bitmap_match (  bits,   RTEMS_RFS_BITMAP_ELEMENT_SET ) )
           rtems_rfs_bitmap_set (  *search_map,   bit );
           else
           {
           int b;
           for (  b = 0; b < available; b++ )
           if (  !rtems_rfs_bitmap_test (  bits,   b ) )
           control->free++;
           }
          
           size -= available;
          
           if (  bit == rtems_rfs_bitmap_element_bits (   ) )
           {
           bit = 0;
           search_map++;
           *search_map = RTEMS_RFS_BITMAP_ELEMENT_CLEAR;
           }
           else
           bit++;
           map++;
           }
          
           return 0;
          }
          
          int
     619  rtems_rfs_bitmap_open (  rtems_rfs_bitmap_control* control,  
           rtems_rfs_file_system* fs,  
           rtems_rfs_buffer_handle* buffer,  
           size_t size,  
           rtems_rfs_buffer_block block )
          {
           size_t elements = rtems_rfs_bitmap_elements (  size );
          
           control->buffer = buffer;
           control->fs = fs;
           control->block = block;
           control->size = size;
          
           elements = rtems_rfs_bitmap_elements (  elements );
           control->search_bits = malloc (  elements * sizeof (  rtems_rfs_bitmap_element ) );
          
           if (  !control->search_bits )
           return ENOMEM;
          
           return rtems_rfs_bitmap_create_search (  control );
          }
          
          int
     642  rtems_rfs_bitmap_close (  rtems_rfs_bitmap_control* control )
          {
           free (  control->search_bits );
           return 0;
          }

libfs/src/rfs/rtems-rfs-block.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-block.c,  v 1.7 2010/10/11 04:34:48 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Block Routines.
           *
           * These functions manage blocks in the RFS file system. A block is an area of
           * the media and its size is set for a each specific media. The block size is
           * set when the file system is set up and needs to be matched for it to be read
           * correctly.
           *
           * Blocks are managed as groups. A block group or "group" is part of the total
           * number of blocks being managed by the file system and exist to allow
           * resources to localised. A file in a directory will be allocated blocks in
           * the same group as the directory,   and the blocks for the file will also be
           * allocated in the same group.
           *
           * A group consist of a block bitmap,   inodes and data blocks. The first block
           * of the file system will hold the superblock. The block bitmap is a
           * collection of blocks that hold a map of bits,   one bit per block for each
           * block in the group. When a file system is mounted the block bitmaps are read
           * and a summary bit map is made. The summary bitmap has a single bit for 32
           * bits in the bitmap and is set when all 32 bits it maps to are set. This
           * speeds up the search for a free block by a factor of 32.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <rtems/rfs/rtems-rfs-block.h>
          #include <rtems/rfs/rtems-rfs-data.h>
          #include <rtems/rfs/rtems-rfs-group.h>
          #include <rtems/rfs/rtems-rfs-inode.h>
          
          void
      49  rtems_rfs_block_get_bpos (  rtems_rfs_file_system* fs,  
           rtems_rfs_pos pos,  
           rtems_rfs_block_pos* bpos )
          {
           bpos->bno = pos / rtems_rfs_fs_block_size (  fs );
           bpos->boff = pos % rtems_rfs_fs_block_size (  fs );
          }
          
          rtems_rfs_pos
      58  rtems_rfs_block_get_pos (  rtems_rfs_file_system* fs,  
           rtems_rfs_block_pos* bpos )
          {
           return (  bpos->bno * rtems_rfs_fs_block_size (  fs ) ) + bpos->boff;
          }
          
          void
      65  rtems_rfs_block_get_block_size (  rtems_rfs_file_system* fs,  
           rtems_rfs_pos pos,  
           rtems_rfs_block_size* size )
          {
           if (  pos == 0 )
           rtems_rfs_block_set_size_zero (  size );
           else
           {
           size->count = pos / rtems_rfs_fs_block_size (  fs ) + 1;
           size->offset = pos % rtems_rfs_fs_block_size (  fs );
           }
          }
          
          rtems_rfs_pos
      79  rtems_rfs_block_get_size (  rtems_rfs_file_system* fs,  
           rtems_rfs_block_size* size )
          {
           uint32_t offset;
           uint64_t block_size;
           if (  size->count == 0 )
           return 0;
           if (  size->offset == 0 )
           offset = rtems_rfs_fs_block_size (  fs );
           else
           offset = size->offset;
           block_size = rtems_rfs_fs_block_size (  fs );
           return (  (  (  uint64_t ) (  size->count - 1 ) ) * block_size ) + offset;
          }
          
          int
      95  rtems_rfs_block_map_open (  rtems_rfs_file_system* fs,  
           rtems_rfs_inode_handle* inode,  
           rtems_rfs_block_map* map )
          {
           int b;
           int rc;
          
           /*
           * Set the count to 0 so at least find fails,   then open the handle and make
           * sure the inode has been loaded into memory. If we did not load the inode
           * do not unload it. The caller may assume it is still loaded when we return.
           */
          
           map->dirty = false;
           map->inode = NULL;
           rtems_rfs_block_set_size_zero (  &map->size );
           rtems_rfs_block_set_bpos_zero (  &map->bpos );
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &map->singly_buffer );
           if (  rc > 0 )
           return rc;
           rc = rtems_rfs_buffer_handle_open (  fs,   &map->doubly_buffer );
           if (  rc > 0 )
           return rc;
          
           rc = rtems_rfs_inode_load (  fs,   inode );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &map->singly_buffer );
           rtems_rfs_buffer_handle_close (  fs,   &map->doubly_buffer );
           return rc;
           }
          
           /*
           * Extract the block and block count data from the inode into the targets
           * byte order.
           */
           map->inode = inode;
           for (  b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++ )
           map->blocks[b] = rtems_rfs_inode_get_block (  inode,   b );
           map->size.count = rtems_rfs_inode_get_block_count (  inode );
           map->size.offset = rtems_rfs_inode_get_block_offset (  inode );
           map->last_map_block = rtems_rfs_inode_get_last_map_block (  inode );
           map->last_data_block = rtems_rfs_inode_get_last_data_block (  inode );
          
           rc = rtems_rfs_inode_unload (  fs,   inode,   false );
          
           return rc;
          }
          
          int
     146  rtems_rfs_block_map_close (  rtems_rfs_file_system* fs,  
           rtems_rfs_block_map* map )
          {
           int rc = 0;
           int brc;
          
           if (  map->dirty && map->inode )
           {
           brc = rtems_rfs_inode_load (  fs,   map->inode );
           if (  brc > 0 )
           rc = brc;
          
           if (  rc == 0 )
           {
           int b;
          
           for (  b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++ )
           rtems_rfs_inode_set_block (  map->inode,   b,   map->blocks[b] );
           rtems_rfs_inode_set_block_count (  map->inode,   map->size.count );
           rtems_rfs_inode_set_block_offset (  map->inode,   map->size.offset );
           rtems_rfs_inode_set_last_map_block (  map->inode,   map->last_map_block );
           rtems_rfs_inode_set_last_data_block (  map->inode,   map->last_data_block );
          
           brc = rtems_rfs_inode_unload (  fs,   map->inode,   true );
           if (  brc > 0 )
           rc = brc;
          
           map->dirty = false;
           }
           }
          
           map->inode = NULL;
          
           brc = rtems_rfs_buffer_handle_close (  fs,   &map->singly_buffer );
           if (  (  brc > 0 ) && (  rc == 0 ) )
           rc = brc;
           brc = rtems_rfs_buffer_handle_close (  fs,   &map->doubly_buffer );
           if (  (  brc > 0 ) && (  rc == 0 ) )
           rc = brc;
           return rc;
          }
          
          /**
           * Find a block indirectly held in a table of block numbers.
           *
           * @param fs The file system.
           * @param buffer The handle to access the block data by.
           * @param block The block number of the table of block numbers.
           * @param offset The offset in the table of the block number to return. This is
           * a block number offset not a byte offset into the table.
           * @param result Pointer to the result of the search.
           * @return int The error number (  errno ). No error if 0.
           */
          static int
     200  rtems_rfs_block_find_indirect (  rtems_rfs_file_system* fs,  
           rtems_rfs_buffer_handle* buffer,  
           rtems_rfs_block_no block,  
           int offset,  
           rtems_rfs_block_no* result )
          {
           int rc;
          
           /*
           * If the handle has a buffer and this request is a different block the current
           * buffer is released.
           */
           rc = rtems_rfs_buffer_handle_request (  fs,   buffer,   block,   true );
           if (  rc > 0 )
           return rc;
          
           *result = rtems_rfs_block_get_number (  buffer,   offset );
           if (  (  *result + 1 ) == 0 )
           *result = 0;
          
           if (  *result >= rtems_rfs_fs_blocks (  fs ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BLOCK_FIND ) )
           printf (  "rtems-rfs: block-find: invalid block in table:"
           " block=%" PRId32 ",   indirect=%" PRId32 "/%d\n",   *result,   block,   offset );
           *result = 0;
           rc = EIO;
           }
          
           return 0;
          }
          
          int
     233  rtems_rfs_block_map_find (  rtems_rfs_file_system* fs,  
           rtems_rfs_block_map* map,  
           rtems_rfs_block_pos* bpos,  
           rtems_rfs_block_no* block )
          {
           int rc = 0;
          
           *block = 0;
          
           /*
           * Range checking here makes the remaining logic simpler.
           */
           if (  rtems_rfs_block_pos_block_past_end (  bpos,   &map->size ) )
           return ENXIO;
          
           /*
           * If the block position is the same and we have found the block just return it.
           */
           if (  (  bpos->bno == map->bpos.bno ) && (  map->bpos.block != 0 ) )
           {
           *block = map->bpos.block;
           }
           else
           {
           /*
           * Determine the type of access we need to perform. If the number of blocks
           * is less than or equal to the number of slots in the inode the blocks are
           * directly accessed.
           */
           if (  map->size.count <= RTEMS_RFS_INODE_BLOCKS )
           {
           *block = map->blocks[bpos->bno];
           }
           else
           {
           /*
           * The map is either singly or doubly indirect.
           */
           rtems_rfs_block_no direct;
           rtems_rfs_block_no singly;
          
           direct = bpos->bno % fs->blocks_per_block;
           singly = bpos->bno / fs->blocks_per_block;
          
           if (  map->size.count <= fs->block_map_singly_blocks )
           {
           /*
           * This is a single indirect table of blocks anchored off a slot in the
           * inode.
           */
           rc = rtems_rfs_block_find_indirect (  fs,  
           &map->singly_buffer,  
           map->blocks[singly],  
           direct,   block );
           }
           else
           {
           /*
           * The map is doubly indirect.
           */
           rtems_rfs_block_no doubly;
          
           doubly = singly / fs->blocks_per_block;
           singly %= fs->blocks_per_block;
          
           if (  map->size.count < fs->block_map_doubly_blocks )
           {
           rc = rtems_rfs_block_find_indirect (  fs,  
           &map->doubly_buffer,  
           map->blocks[doubly],  
           singly,   &singly );
           if (  rc == 0 )
           {
           rc = rtems_rfs_block_find_indirect (  fs,  
           &map->singly_buffer,  
           singly,   direct,   block );
           }
           }
           else
           {
           /*
           * This should never happen. Here so Joel can remove once his coverage
           * testing gets to the file systems.
           */
           rc = ENXIO;
           }
           }
           }
           }
          
           if (  rc == 0 )
           {
           rtems_rfs_block_copy_bpos (  &map->bpos,   bpos );
           map->bpos.block = *block;
           }
          
           return rc;
          }
          
          int
     333  rtems_rfs_block_map_seek (  rtems_rfs_file_system* fs,  
           rtems_rfs_block_map* map,  
           rtems_rfs_pos_rel offset,  
           rtems_rfs_block_no* block )
          {
           rtems_rfs_block_pos bpos;
           rtems_rfs_block_copy_bpos (  &bpos,   &map->bpos );
           rtems_rfs_block_add_pos (  fs,   offset,   &bpos );
           return rtems_rfs_block_map_find (  fs,   map,   &bpos,   block );
          }
          
          int
     345  rtems_rfs_block_map_next_block (  rtems_rfs_file_system* fs,  
           rtems_rfs_block_map* map,  
           rtems_rfs_block_no* block )
          {
           rtems_rfs_block_pos bpos;
           bpos.bno = map->bpos.bno + 1;
           bpos.boff = 0;
           bpos.block = 0;
           return rtems_rfs_block_map_find (  fs,   map,   &bpos,   block );
          }
          
          /**
           * Allocate an indirect block to a map.
           *
           * @param fs The file system data.
           * @param map The map the allocation is for.
           * @param buffer The buffer the indirect block is accessed by.
           * @param block The block number of the indirect block allocated.
           * @param upping True is upping the map to the next indirect level.
           * @return int The error number (  errno ). No error if 0.
           */
          static int
     367  rtems_rfs_block_map_indirect_alloc (  rtems_rfs_file_system* fs,  
           rtems_rfs_block_map* map,  
           rtems_rfs_buffer_handle* buffer,  
           rtems_rfs_block_no* block,  
           bool upping )
          {
           rtems_rfs_bitmap_bit new_block;
           int rc;
           /*
           * Save the new block locally because upping can have *block pointing to the
           * slots which are cleared when upping.
           */
           rc = rtems_rfs_group_bitmap_alloc (  fs,   map->last_map_block,   false,   &new_block );
           if (  rc > 0 )
           return rc;
           rc = rtems_rfs_buffer_handle_request (  fs,   buffer,   new_block,   false );
           if (  rc > 0 )
           {
           rtems_rfs_group_bitmap_free (  fs,   false,   new_block );
           return rc;
           }
           memset (  rtems_rfs_buffer_data (  buffer ),   0xff,   rtems_rfs_fs_block_size (  fs ) );
           if (  upping )
           {
           int b;
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BLOCK_MAP_GROW ) )
           printf (  "rtems-rfs: block-map-grow: upping: block-count=%" PRId32 "\n",  
           map->size.count );
           for (  b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++ )
           rtems_rfs_block_set_number (  buffer,   b,   map->blocks[b] );
           memset (  map->blocks,   0,   sizeof (  map->blocks ) );
           }
           rtems_rfs_buffer_mark_dirty (  buffer );
           *block = new_block;
           map->last_map_block = new_block;
           return 0;
          }
          
          int
     406  rtems_rfs_block_map_grow (  rtems_rfs_file_system* fs,  
           rtems_rfs_block_map* map,  
           size_t blocks,  
           rtems_rfs_block_no* new_block )
          {
           int b;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BLOCK_MAP_GROW ) )
           printf (  "rtems-rfs: block-map-grow: entry: blocks=%zd count=%" PRIu32 "\n",  
           blocks,   map->size.count );
          
           if (  (  map->size.count + blocks ) >= rtems_rfs_fs_max_block_map_blocks (  fs ) )
           return EFBIG;
          
           /*
           * Allocate a block at a time. The buffer handles hold the blocks so adding
           * this way does not thrash the cache with lots of requests.
           */
           for (  b = 0; b < blocks; b++ )
           {
           rtems_rfs_bitmap_bit block;
           int rc;
          
           /*
           * Allocate the block. If an indirect block is needed and cannot be
           * allocated free this block.
           */
          
           rc = rtems_rfs_group_bitmap_alloc (  fs,   map->last_data_block,  
           false,   &block );
           if (  rc > 0 )
           return rc;
          
           if (  map->size.count < RTEMS_RFS_INODE_BLOCKS )
           map->blocks[map->size.count] = block;
           else
           {
           /*
           * Single indirect access is occuring. It could still be doubly indirect.
           */
           rtems_rfs_block_no direct;
           rtems_rfs_block_no singly;
          
           direct = map->size.count % fs->blocks_per_block;
           singly = map->size.count / fs->blocks_per_block;
          
           if (  map->size.count < fs->block_map_singly_blocks )
           {
           /*
           * Singly indirect tables are being used. Allocate a new block for a
           * mapping table if direct is 0 or we are moving up (  upping ). If upping
           * move the direct blocks into the table and if not this is the first
           * entry of a new block.
           */
           if (  (  direct == 0 ) ||
           (  (  singly == 0 ) && (  direct == RTEMS_RFS_INODE_BLOCKS ) ) )
           {
           /*
           * Upping is when we move from direct to singly indirect.
           */
           bool upping;
           upping = map->size.count == RTEMS_RFS_INODE_BLOCKS;
           rc = rtems_rfs_block_map_indirect_alloc (  fs,   map,  
           &map->singly_buffer,  
           &map->blocks[singly],  
           upping );
           }
           else
           {
           rc = rtems_rfs_buffer_handle_request (  fs,   &map->singly_buffer,  
           map->blocks[singly],   true );
           }
          
           if (  rc > 0 )
           {
           rtems_rfs_group_bitmap_free (  fs,   false,   block );
           return rc;
           }
           }
           else
           {
           /*
           * Doubly indirect tables are being used.
           */
           rtems_rfs_block_no doubly;
           rtems_rfs_block_no singly_block;
          
           doubly = singly / fs->blocks_per_block;
           singly %= fs->blocks_per_block;
          
           /*
           * Allocate a new block for a singly indirect table if direct is 0 as
           * it is the first entry of a new block. We may also need to allocate a
           * doubly indirect block as well. Both always occur when direct is 0
           * and the doubly indirect block when singly is 0.
           */
           if (  direct == 0 )
           {
           rc = rtems_rfs_block_map_indirect_alloc (  fs,   map,  
           &map->singly_buffer,  
           &singly_block,  
           false );
           if (  rc > 0 )
           {
           rtems_rfs_group_bitmap_free (  fs,   false,   block );
           return rc;
           }
          
           /*
           * Allocate a new block for a doubly indirect table if singly is 0 as
           * it is the first entry of a new singly indirect block.
           */
           if (  (  singly == 0 ) ||
           (  (  doubly == 0 ) && (  singly == RTEMS_RFS_INODE_BLOCKS ) ) )
           {
           bool upping;
           upping = map->size.count == fs->block_map_singly_blocks;
           rc = rtems_rfs_block_map_indirect_alloc (  fs,   map,  
           &map->doubly_buffer,  
           &map->blocks[doubly],  
           upping );
           if (  rc > 0 )
           {
           rtems_rfs_group_bitmap_free (  fs,   false,   singly_block );
           rtems_rfs_group_bitmap_free (  fs,   false,   block );
           return rc;
           }
           }
           else
           {
           rc = rtems_rfs_buffer_handle_request (  fs,   &map->doubly_buffer,  
           map->blocks[doubly],   true );
           if (  rc > 0 )
           {
           rtems_rfs_group_bitmap_free (  fs,   false,   singly_block );
           rtems_rfs_group_bitmap_free (  fs,   false,   block );
           return rc;
           }
           }
          
           rtems_rfs_block_set_number (  &map->doubly_buffer,  
           singly,  
           singly_block );
           }
           else
           {
           rc = rtems_rfs_buffer_handle_request (  fs,  
           &map->doubly_buffer,  
           map->blocks[doubly],  
           true );
           if (  rc > 0 )
           {
           rtems_rfs_group_bitmap_free (  fs,   false,   block );
           return rc;
           }
          
           singly_block = rtems_rfs_block_get_number (  &map->doubly_buffer,  
           singly );
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &map->singly_buffer,  
           singly_block,   true );
           if (  rc > 0 )
           {
           rtems_rfs_group_bitmap_free (  fs,   false,   block );
           return rc;
           }
           }
           }
          
           rtems_rfs_block_set_number (  &map->singly_buffer,   direct,   block );
           }
          
           map->size.count++;
           map->size.offset = 0;
          
           if (  b == 0 )
           *new_block = block;
           map->last_data_block = block;
           map->dirty = true;
           }
          
           return 0;
          }
          
          /**
           * Shrink an indirect block.
           *
           * @param fs The file system data.
           * @param map The map the allocation is for.
           * @param buffer The buffer the indirect block is accessed by.
           * @param indirect The index index in the inode's block table.
           * @param index The index in the indirect table of the block.
           * @return int The error number (  errno ). No error if 0.
           */
          static int
     601  rtems_rfs_block_map_indirect_shrink (  rtems_rfs_file_system* fs,  
           rtems_rfs_block_map* map,  
           rtems_rfs_buffer_handle* buffer,  
           rtems_rfs_block_no indirect,  
           rtems_rfs_block_no index )
          {
           int rc = 0;
          
           /*
           * If this is the first block in the indirect table (  index == 0 ),   ie the last
           * block to be freed and the indirect block is now also free,   or we have only
           * one indirect table and we can fit the remaining blocks into the inode,  
           * then either move to the next indirect block or move the remaining blocks
           * into the inode and free the indirect table's block.
           */
           if (  (  index == 0 ) ||
           (  (  indirect == 0 ) && (  index == RTEMS_RFS_INODE_BLOCKS ) ) )
           {
           rtems_rfs_block_no block_to_free = map->blocks[indirect];
          
           if (  (  indirect == 0 ) && (  index == RTEMS_RFS_INODE_BLOCKS ) )
           {
           /*
           * Move to direct inode access.
           */
           int b;
           for (  b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++ )
           map->blocks[b] = rtems_rfs_block_get_number (  buffer,   b );
           }
           else
           {
           /*
           * One less singly indirect block in the inode.
           */
           map->blocks[indirect] = 0;
           }
          
           rc = rtems_rfs_group_bitmap_free (  fs,   false,   block_to_free );
           if (  rc > 0 )
           return rc;
          
           map->last_map_block = block_to_free;
           }
          
           return rc;
          }
          
          int
     649  rtems_rfs_block_map_shrink (  rtems_rfs_file_system* fs,  
           rtems_rfs_block_map* map,  
           size_t blocks )
          {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BLOCK_MAP_SHRINK ) )
           printf (  "rtems-rfs: block-map-shrink: entry: blocks=%zd count=%" PRIu32 "\n",  
           blocks,   map->size.count );
          
           if (  map->size.count == 0 )
           return 0;
          
           if (  blocks > map->size.count )
           blocks = map->size.count;
          
           while (  blocks )
           {
           rtems_rfs_block_no block;
           rtems_rfs_block_no block_to_free;
           int rc;
          
           block = map->size.count - 1;
          
           if (  block < RTEMS_RFS_INODE_BLOCKS )
           {
           /*
           * We have less than RTEMS_RFS_INODE_BLOCKS so they are held in the
           * inode.
           */
           block_to_free = map->blocks[block];
           map->blocks[block] = 0;
           }
           else
           {
           /*
           * Single indirect access is occuring. It could still be doubly indirect.
           *
           * The 'direct' variable is the offset in to the indirect table of
           * blocks,   and 'singly' is the inode block index of the singly indirect
           * table of block numbers.
           */
           rtems_rfs_block_no direct;
           rtems_rfs_block_no singly;
          
           direct = block % fs->blocks_per_block;
           singly = block / fs->blocks_per_block;
          
           if (  block < fs->block_map_singly_blocks )
           {
           /*
           * Request the indirect block and then obtain the block number from the
           * indirect block.
           */
           rc = rtems_rfs_buffer_handle_request (  fs,   &map->singly_buffer,  
           map->blocks[singly],   true );
           if (  rc > 0 )
           return rc;
          
           block_to_free = rtems_rfs_block_get_number (  &map->singly_buffer,  
           direct );
          
           rc = rtems_rfs_block_map_indirect_shrink (  fs,   map,   &map->singly_buffer,  
           singly,   direct );
           if (  rc )
           return rc;
           }
           else if (  block < fs->block_map_doubly_blocks )
           {
           /*
           * Doubly indirect tables are being used. The 'doubly' variable is the
           * index in to the inode's block table and points to a singly indirect
           * table of block numbers. The 'doubly_singly' variable is the index
           * into the doubly indirect table pointing to the singly indirect table
           * of block numbers that form the map. This is used later to determine
           * if the current doubly indirect table needs to be freed. The 'direct'
           * value is still valid for doubly indirect tables.
           */
           rtems_rfs_block_no doubly;
           rtems_rfs_block_no doubly_singly;
          
           doubly = singly / fs->blocks_per_block;
           doubly_singly = singly % fs->blocks_per_block;
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &map->doubly_buffer,  
           map->blocks[doubly],   true );
           if (  rc > 0 )
           return rc;
          
           singly = rtems_rfs_block_get_number (  &map->doubly_buffer,  
           doubly_singly );
          
           /*
           * Read the singly indirect table and get the block number.
           */
           rc = rtems_rfs_buffer_handle_request (  fs,   &map->singly_buffer,  
           singly,   true );
           if (  rc > 0 )
           return rc;
          
           block_to_free = rtems_rfs_block_get_number (  &map->singly_buffer,  
           direct );
          
           if (  direct == 0 )
           {
           rc = rtems_rfs_group_bitmap_free (  fs,   false,   singly );
           if (  rc > 0 )
           return rc;
          
           map->last_map_block = singly;
          
           rc = rtems_rfs_block_map_indirect_shrink (  fs,   map,   &map->doubly_buffer,  
           doubly,   doubly_singly );
           if (  rc )
           return rc;
           }
           }
           else
           {
           rc = EIO;
           break;
           }
           }
           rc = rtems_rfs_group_bitmap_free (  fs,   false,   block_to_free );
           if (  rc > 0 )
           return rc;
           map->size.count--;
           map->size.offset = 0;
           map->last_data_block = block_to_free;
           map->dirty = true;
           blocks--;
           }
          
           if (  map->size.count == 0 )
           {
           map->last_map_block = 0;
           map->last_data_block = 0;
           }
          
           /*
           * Keep the position inside the map.
           */
           if (  rtems_rfs_block_pos_past_end (  &map->bpos,   &map->size ) )
           rtems_rfs_block_size_get_bpos (  &map->size,   &map->bpos );
          
           return 0;
          }
          
          int
     796  rtems_rfs_block_map_free_all (  rtems_rfs_file_system* fs,  
           rtems_rfs_block_map* map )
          {
           return rtems_rfs_block_map_shrink (  fs,   map,   map->size.count );
          }

libfs/src/rfs/rtems-rfs-buffer-bdbuf.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-buffer-bdbuf.c,  v 1.4 2010/06/16 16:59:43 ralf Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Buffer Routines for the RTEMS libblock BD buffer cache.
           *
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          #include <errno.h>
          
          #include <rtems/rfs/rtems-rfs-buffer.h>
          #include <rtems/rfs/rtems-rfs-file-system.h>
          
          #if RTEMS_RFS_USE_LIBBLOCK
          
          /**
           * Show errors.
           */
          #define RTEMS_RFS_BUFFER_ERRORS 0
          
          int
      37  rtems_rfs_buffer_bdbuf_request (  rtems_rfs_file_system* fs,  
           rtems_rfs_buffer_block block,  
           bool read,  
           rtems_rfs_buffer** buffer )
          {
           rtems_status_code sc;
           int rc = 0;
          
           if (  read )
           sc = rtems_bdbuf_read (  rtems_rfs_fs_device (  fs ),   block,   buffer );
           else
           sc = rtems_bdbuf_get (  rtems_rfs_fs_device (  fs ),   block,   buffer );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
          #if RTEMS_RFS_BUFFER_ERRORS
           printf (  "rtems-rfs: buffer-bdbuf-request: block=%lu: bdbuf-%s: %d: %s\n",  
           block,   read ? "read" : "get",   sc,   rtems_status_text (  sc ) );
          #endif
           rc = EIO;
           }
          
           return rc;
          }
          
          int
      63  rtems_rfs_buffer_bdbuf_release (  rtems_rfs_buffer* buffer,  
           bool modified )
          {
           rtems_status_code sc;
           int rc = 0;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_RELEASE ) )
           printf (  "rtems-rfs: bdbuf-release: block=%" PRIuPTR " bdbuf=%" PRIu32 " %s\n",  
           (  (  intptr_t ) buffer->user ),  
           buffer->block,   modified ? "(  modified )" : "" );
          
           if (  modified )
           sc = rtems_bdbuf_release_modified (  buffer );
           else
           sc = rtems_bdbuf_release (  buffer );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
          #if RTEMS_RFS_BUFFER_ERRORS
           printf (  "rtems-rfs: buffer-release: bdbuf-%s: %s(  %d )\n",  
           modified ? "modified" : "not-modified",  
           rtems_status_text (  sc ),   sc );
          #endif
           rc = EIO;
           }
          
           return rc;
          }
          
          #endif

libfs/src/rfs/rtems-rfs-buffer-devio.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-buffer-devio.c,  v 1.2 2010/03/27 04:04:40 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Buffer Routines.
           *
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include <rtems/rfs/rtems-rfs-buffer.h>
          #include <rtems/rfs/rtems-rfs-file-system.h>
          
          #if !RTEMS_RFS_USE_LIBBLOCK
          
          /**
           * Show errors.
           */
          #define RTEMS_RFS_BUFFER_ERRORS 1
          
          int
      36  rtems_rfs_buffer_deviceio_request (  rtems_rfs_buffer_handle* handle,  
           dev_t device,  
           rtems_rfs_buffer_block block,  
           bool read )
          {
          }
          
          int
      44  rtems_rfs_buffer_deviceio_release (  rtems_rfs_buffer_handle* handle,  
           dev_t device )
          {
          }
          
          int
      50  rtems_rfs_buffer_deviceio_handle_open (  rtems_rfs_buffer_handle* handle,  
           dev_t device )
          {
          }
          
          int
      56  rtems_rfs_buffer_device_handle_close (  rtems_rfs_buffer_handle* handle,  
           dev_t device )
          {
          }
          
          #endif

libfs/src/rfs/rtems-rfs-buffer.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-buffer.c,  v 1.7 2010/06/17 03:16:41 ralf Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Buffer Routines.
           *
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          #include <errno.h>
          
          #include <rtems/rfs/rtems-rfs-buffer.h>
          #include <rtems/rfs/rtems-rfs-file-system.h>
          
          /**
           * Scan the chain for a buffer that matches the block number.
           *
           * @param chain The chain to scan.
           * @param count The number of items on the chain.
           * @param block The block number to find.
           * @return rtems_rfs_buffer* The buffer if found else NULL.
           */
          static rtems_rfs_buffer*
      38  rtems_rfs_scan_chain (  rtems_chain_control* chain,  
           uint32_t* count,  
           rtems_rfs_buffer_block block )
          {
           rtems_rfs_buffer* buffer;
           rtems_chain_node* node;
          
           node = rtems_chain_last (  chain );
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_CHAINS ) )
           printf (  "rtems-rfs: buffer-scan: count=%" PRIu32 ",   block=%" PRIu32 ": ",   *count,   block );
          
           while (  !rtems_chain_is_head (  chain,   node ) )
           {
           buffer = (  rtems_rfs_buffer* ) node;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_CHAINS ) )
           printf (  "%" PRIuPTR " ",   (  (  intptr_t ) buffer->user ) );
          
           if (  (  (  rtems_rfs_buffer_block ) (  (  intptr_t )(  buffer->user ) ) ) == block )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_CHAINS ) )
           printf (  ": found block=%" PRIuPTR "\n",  
           (  (  intptr_t )(  buffer->user ) ) );
          
           (  *count )--;
           rtems_chain_extract (  node );
           rtems_chain_set_off_chain (  node );
           return buffer;
           }
           node = rtems_chain_previous (  node );
           }
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_CHAINS ) )
           printf (  ": not found\n" );
          
           return NULL;
          }
          
          int
      78  rtems_rfs_buffer_handle_request (  rtems_rfs_file_system* fs,  
           rtems_rfs_buffer_handle* handle,  
           rtems_rfs_buffer_block block,  
           bool read )
          {
           int rc;
          
           /*
           * If the handle has a buffer release it. This allows a handle to be reused
           * without needing to close then open it again.
           */
           if (  rtems_rfs_buffer_handle_has_block (  handle ) )
           {
           /*
           * Treat block 0 as special to handle the loading of the super block.
           */
           if (  block && (  rtems_rfs_buffer_bnum (  handle ) == block ) )
           return 0;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST ) )
           printf (  "rtems-rfs: buffer-request: handle has buffer: %" PRIu32 "\n",  
           rtems_rfs_buffer_bnum (  handle ) );
          
           rc = rtems_rfs_buffer_handle_release (  fs,   handle );
           if (  rc > 0 )
           return rc;
           handle->dirty = false;
           handle->bnum = 0;
           }
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST ) )
           printf (  "rtems-rfs: buffer-request: block=%" PRIu32 "\n",   block );
          
           /*
           * First check to see if the buffer has already been requested and is
           * currently attached to a handle. If it is share the access. A buffer could
           * be shared where different parts of the block have separate functions. An
           * example is an inode block and the file system needs to handle 2 inodes in
           * the same block at the same time.
           */
           if (  fs->buffers_count )
           {
           /*
           * Check the active buffer list for shared buffers.
           */
           handle->buffer = rtems_rfs_scan_chain (  &fs->buffers,  
           &fs->buffers_count,  
           block );
           if (  rtems_rfs_buffer_handle_has_block (  handle ) &&
           rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST ) )
           printf (  "rtems-rfs: buffer-request: buffer shared: refs: %d\n",  
           rtems_rfs_buffer_refs (  handle ) + 1 );
           }
          
           /*
           * If the buffer has not been found check the local cache of released
           * buffers. There are release and released modified lists to preserve the
           * state.
           */
           if (  !rtems_rfs_fs_no_local_cache (  fs ) &&
           !rtems_rfs_buffer_handle_has_block (  handle ) )
           {
           /*
           * Check the local cache of released buffers.
           */
           if (  fs->release_count )
           handle->buffer = rtems_rfs_scan_chain (  &fs->release,  
           &fs->release_count,  
           block );
          
           if (  !rtems_rfs_buffer_handle_has_block (  handle ) &&
           fs->release_modified_count )
           {
           handle->buffer = rtems_rfs_scan_chain (  &fs->release_modified,  
           &fs->release_modified_count,  
           block );
           /*
           * If we found a buffer retain the dirty buffer state.
           */
           if (  rtems_rfs_buffer_handle_has_block (  handle ) )
           rtems_rfs_buffer_mark_dirty (  handle );
           }
           }
          
           /*
           * If not located we request the buffer from the I/O layer.
           */
           if (  !rtems_rfs_buffer_handle_has_block (  handle ) )
           {
           rc = rtems_rfs_buffer_io_request (  fs,   block,   read,   &handle->buffer );
          
           rtems_chain_set_off_chain (  rtems_rfs_buffer_link(  handle ) );
          
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST ) )
           printf (  "rtems-rfs: buffer-request: block=%" PRIu32 ": bdbuf-%s: %d: %s\n",  
           block,   read ? "read" : "get",   rc,   strerror (  rc ) );
           return rc;
           }
           }
          
           /*
           * Increase the reference count of the buffer.
           */
           rtems_rfs_buffer_refs_up (  handle );
           rtems_chain_append (  &fs->buffers,   rtems_rfs_buffer_link (  handle ) );
           fs->buffers_count++;
          
           handle->buffer->user = (  void* ) (  (  intptr_t ) block );
           handle->bnum = block;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST ) )
           printf (  "rtems-rfs: buffer-request: block=%" PRIu32 " bdbuf-%s=%" PRIu32 " refs=%d\n",  
           block,   read ? "read" : "get",   handle->buffer->block,  
           handle->buffer->references );
          
           return 0;
          }
          
          int
     199  rtems_rfs_buffer_handle_release (  rtems_rfs_file_system* fs,  
           rtems_rfs_buffer_handle* handle )
          {
           int rc = 0;
          
           if (  rtems_rfs_buffer_handle_has_block (  handle ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_HANDLE_RELEASE ) )
           printf (  "rtems-rfs: buffer-release: block=%" PRIu32 " %s refs=%d %s\n",  
           rtems_rfs_buffer_bnum (  handle ),  
           rtems_rfs_buffer_dirty (  handle ) ? "(  dirty )" : "",  
           rtems_rfs_buffer_refs (  handle ),  
           rtems_rfs_buffer_refs (  handle ) == 0 ? "BAD REF COUNT" : "" );
          
           if (  rtems_rfs_buffer_refs (  handle ) > 0 )
           rtems_rfs_buffer_refs_down (  handle );
          
           if (  rtems_rfs_buffer_refs (  handle ) == 0 )
           {
           rtems_chain_extract (  rtems_rfs_buffer_link (  handle ) );
           fs->buffers_count--;
          
           if (  rtems_rfs_fs_no_local_cache (  fs ) )
           {
           handle->buffer->user = (  void* ) 0;
           rc = rtems_rfs_buffer_io_release (  handle->buffer,  
           rtems_rfs_buffer_dirty (  handle ) );
           }
           else
           {
           /*
           * If the total number of held buffers is higher than the configured
           * value remove a buffer from the queue with the most buffers and
           * release. The buffers are held on the queues with the newest at the
           * head.
           *
           * This code stops a large series of transactions causing all the
           * buffers in the cache being held in queues of this file system.
           */
           if (  (  fs->release_count +
           fs->release_modified_count ) >= fs->max_held_buffers )
           {
           rtems_rfs_buffer* buffer;
           bool modified;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_HANDLE_RELEASE ) )
           printf (  "rtems-rfs: buffer-release: local cache overflow:"
           " %" PRIu32 "\n",   fs->release_count + fs->release_modified_count );
          
           if (  fs->release_count > fs->release_modified_count )
           {
           buffer = (  rtems_rfs_buffer* ) rtems_chain_get (  &fs->release );
           fs->release_count--;
           modified = false;
           }
           else
           {
           buffer =
           (  rtems_rfs_buffer* ) rtems_chain_get (  &fs->release_modified );
           fs->release_modified_count--;
           modified = true;
           }
           buffer->user = (  void* ) 0;
           rc = rtems_rfs_buffer_io_release (  buffer,   modified );
           }
          
           if (  rtems_rfs_buffer_dirty (  handle ) )
           {
           rtems_chain_append (  &fs->release_modified,  
           rtems_rfs_buffer_link (  handle ) );
           fs->release_modified_count++;
           }
           else
           {
           rtems_chain_append (  &fs->release,   rtems_rfs_buffer_link (  handle ) );
           fs->release_count++;
           }
           }
           }
           handle->buffer = NULL;
           }
          
           return rc;
          }
          
          int
     285  rtems_rfs_buffer_open (  const char* name,   rtems_rfs_file_system* fs )
          {
           struct stat st;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_SYNC ) )
           printf (  "rtems-rfs: buffer-open: opening: %s\n",   name );
          
           if (  stat (  name,   &st ) < 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_OPEN ) )
           printf (  "rtems-rfs: buffer-open: stat '%s' failed: %s\n",  
           name,   strerror (  errno ) );
           return ENOENT;
           }
          
          #if RTEMS_RFS_USE_LIBBLOCK
           /*
           * Is the device a block device ?
           */
           if (  !S_ISBLK (  st.st_mode ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_OPEN ) )
           printf (  "rtems-rfs: buffer-open: '%s' is not a block device\n",   name );
           return EIO;
           }
          
           /*
           * Check that device is registred as a block device and lock it.
           */
           fs->disk = rtems_disk_obtain (  st.st_rdev );
           if (  !fs->disk )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_OPEN ) )
           printf (  "rtems-rfs: buffer-open: cannot obtain the disk\n" );
           return EIO;
           }
          #else
           fs->device = open (  name,   O_RDWR );
           if (  fs->device < 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_OPEN ) )
           printf (  "rtems-rfs: buffer-open: cannot open file\n" );
           }
           fs->media_size = st.st_size;
           strcat (  fs->name,   name );
          #endif
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_SYNC ) )
           printf (  "rtems-rfs: buffer-open: blks=%" PRId32 ",   blk-size=%" PRId32 "\n",  
           rtems_rfs_fs_media_blocks (  fs ),  
           rtems_rfs_fs_media_block_size (  fs ) );
          
           return 0;
          }
          
          int
     341  rtems_rfs_buffer_close (  rtems_rfs_file_system* fs )
          {
           int rc = 0;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_CLOSE ) )
           printf (  "rtems-rfs: buffer-close: closing\n" );
          
           /*
           * Change the block size to the media device size. It will release and sync
           * all buffers.
           */
           rc = rtems_rfs_buffer_setblksize (  fs,   rtems_rfs_fs_media_block_size (  fs ) );
          
           if (  (  rc > 0 ) && rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_CLOSE ) )
           printf (  "rtems-rfs: buffer-close: set media block size failed: %d: %s\n",  
           rc,   strerror (  rc ) );
          
          #if RTEMS_RFS_USE_LIBBLOCK
           rtems_disk_release (  fs->disk );
          #else
           if (  close (  fs->device ) < 0 )
           {
           rc = errno;
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_CLOSE ) )
           printf (  "rtems-rfs: buffer-close: file close failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           }
          #endif
          
           return rc;
          }
          
          int
     374  rtems_rfs_buffer_sync (  rtems_rfs_file_system* fs )
          {
           int result = 0;
          #if RTEMS_RFS_USE_LIBBLOCK
           rtems_status_code sc;
          #endif
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_SYNC ) )
           printf (  "rtems-rfs: buffer-sync: syncing\n" );
          
           /*
           * @todo Split in the separate files for each type.
           */
          #if RTEMS_RFS_USE_LIBBLOCK
           sc = rtems_bdbuf_syncdev (  rtems_rfs_fs_device (  fs ) );
           if (  sc != RTEMS_SUCCESSFUL )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_SYNC ) )
           printf (  "rtems-rfs: buffer-sync: device sync failed: %s\n",  
           rtems_status_text (  sc ) );
           result = EIO;
           }
           rtems_disk_release (  fs->disk );
          #else
           if (  fsync (  fs->device ) < 0 )
           {
           result = errno;
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_CLOSE ) )
           printf (  "rtems-rfs: buffer-sync: file sync failed: %d: %s\n",  
           result,   strerror (  result ) );
           }
          #endif
           return result;
          }
          
          int
     410  rtems_rfs_buffer_setblksize (  rtems_rfs_file_system* fs,   size_t size )
          {
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE ) )
           printf (  "rtems-rfs: buffer-setblksize: block size: %zu\n",   size );
          
           rc = rtems_rfs_buffers_release (  fs );
           if (  (  rc > 0 ) && rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE ) )
           printf (  "rtems-rfs: buffer-setblksize: buffer release failed: %d: %s\n",  
           rc,   strerror (  rc ) );
          
           rc = rtems_rfs_buffer_sync (  fs );
           if (  (  rc > 0 ) && rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE ) )
           printf (  "rtems-rfs: buffer-setblksize: device sync failed: %d: %s\n",  
           rc,   strerror (  rc ) );
          
          #if RTEMS_RFS_USE_LIBBLOCK
           rc = fs->disk->ioctl (  fs->disk,   RTEMS_BLKIO_SETBLKSIZE,   &size );
           if (  rc < 0 )
           rc = errno;
          #endif
           return rc;
          }
          
          static int
     436  rtems_rfs_release_chain (  rtems_chain_control* chain,  
           uint32_t* count,  
           bool modified )
          {
           rtems_rfs_buffer* buffer;
           int rrc = 0;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_CHAINS ) )
           printf (  "rtems-rfs: release-chain: count=%" PRIu32 "\n",   *count );
          
           while (  !rtems_chain_is_empty (  chain ) )
           {
           buffer = (  rtems_rfs_buffer* ) rtems_chain_get (  chain );
           (  *count )--;
          
           buffer->user = (  void* ) 0;
          
           rc = rtems_rfs_buffer_io_release (  buffer,   modified );
           if (  (  rc > 0 ) && (  rrc == 0 ) )
           rrc = rc;
           }
           return rrc;
          }
          
          int
     462  rtems_rfs_buffers_release (  rtems_rfs_file_system* fs )
          {
           int rrc = 0;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_BUFFER_RELEASE ) )
           printf (  "rtems-rfs: buffers-release: active:%" PRIu32 " "
           "release:%" PRIu32 " release-modified:%" PRIu32 "\n",  
           fs->buffers_count,   fs->release_count,   fs->release_modified_count );
          
           rc = rtems_rfs_release_chain (  &fs->release,  
           &fs->release_count,  
           false );
           if (  (  rc > 0 ) && (  rrc == 0 ) )
           rrc = rc;
           rc = rtems_rfs_release_chain (  &fs->release_modified,  
           &fs->release_modified_count,  
           true );
           if (  (  rc > 0 ) && (  rrc == 0 ) )
           rrc = rc;
          
           return rrc;
          }

libfs/src/rfs/rtems-rfs-dir-hash.c

       1  /*
           * $Id: rtems-rfs-dir-hash.c,  v 1.2 2010/03/27 04:04:40 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Directory Hash function.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/rfs/rtems-rfs-dir-hash.h>
          
          #ifdef __rtems__
          # include <machine/endian.h> /* attempt to define endianness */
          #endif
          #ifdef linux
          # include <endian.h> /* attempt to define endianness */
          #endif
          
          /*
           * My best guess at if you are big-endian or little-endian. This may
           * need adjustment.
           */
          #if (  defined(  __BYTE_ORDER ) && defined(  __LITTLE_ENDIAN ) && \
           __BYTE_ORDER == __LITTLE_ENDIAN ) || \
           (  defined(  i386 ) || defined(  __i386__ ) || defined(  __i486__ ) || \
           defined(  __i586__ ) || defined(  __i686__ ) || defined(  vax ) || defined(  MIPSEL ) )
          # define HASH_LITTLE_ENDIAN 1
          # define HASH_BIG_ENDIAN 0
          #elif (  defined(  __BYTE_ORDER ) && defined(  __BIG_ENDIAN ) && \
           __BYTE_ORDER == __BIG_ENDIAN ) || \
           (  defined(  sparc ) || defined(  POWERPC ) || defined(  mc68000 ) || defined(  sel ) )
          # define HASH_LITTLE_ENDIAN 0
          # define HASH_BIG_ENDIAN 1
          #else
          # define HASH_LITTLE_ENDIAN 0
          # define HASH_BIG_ENDIAN 0
          #endif
          
          #define hashsize(  n ) (  (  uint32_t )1<<(  n ) )
          #define hashmask(  n ) (  hashsize(  n )-1 )
          #define rot(  x,  k ) (  (  (  x )<<(  k ) ) | (  (  x )>>(  32-(  k ) ) ) )
          
          /*
           -------------------------------------------------------------------------------
           mix -- mix 3 32-bit values reversibly.
          
           This is reversible,   so any information in (  a,  b,  c ) before mix(   ) is still in
           (  a,  b,  c ) after mix(   ).
          
           If four pairs of (  a,  b,  c ) inputs are run through mix(   ),   or through mix(   ) in
           reverse,   there are at least 32 bits of the output that are sometimes the same
           for one pair and different for another pair. This was tested for:
          
           * pairs that differed by one bit,   by two bits,   in any combination of top bits
           of (  a,  b,  c ),   or in any combination of bottom bits of (  a,  b,  c ).
          
           * "differ" is defined as +,   -,   ^,   or ~^. For + and -,   I transformed the
           output delta to a Gray code (  a^(  a>>1 ) ) so a string of 1's (  as is commonly
           produced by subtraction ) look like a single 1-bit difference.
          
           * the base values were pseudorandom,   all zero but one bit set,   or all zero
           plus a counter that starts at zero.
          
           Some k values for my "a-=c; a^=rot(  c,  k ); c+=b;" arrangement that satisfy this
           are:
          
           4 6 8 16 19 4
           9 15 3 18 27 15
           14 9 3 7 17 3
          
           Well,   "9 15 3 18 27 15" didn't quite get 32 bits diffing for "differ" defined
           as + with a one-bit base and a two-bit delta. I used
           http://burtleburtle.net/bob/hash/avalanche.html to choose the operations,  
           constants,   and arrangements of the variables.
          
           This does not achieve avalanche. There are input bits of (  a,  b,  c ) that fail
           to affect some output bits of (  a,  b,  c ),   especially of a. The most thoroughly
           mixed value is c,   but it doesn't really even achieve avalanche in c.
          
           This allows some parallelism. Read-after-writes are good at doubling the
           number of bits affected,   so the goal of mixing pulls in the opposite
           direction as the goal of parallelism. I did what I could. Rotates seem to
           cost as much as shifts on every machine I could lay my hands on,   and rotates
           are much kinder to the top and bottom bits,   so I used rotates.
           -------------------------------------------------------------------------------
          */
          #define mix(  a,  b,  c ) \
           { \
           a -= c; a ^= rot(  c,   4 ); c += b; \
           b -= a; b ^= rot(  a,   6 ); a += c; \
           c -= b; c ^= rot(  b,   8 ); b += a; \
           a -= c; a ^= rot(  c,  16 ); c += b; \
           b -= a; b ^= rot(  a,  19 ); a += c; \
           c -= b; c ^= rot(  b,   4 ); b += a; \
           }
          
          /*
           -------------------------------------------------------------------------------
           final -- final mixing of 3 32-bit values (  a,  b,  c ) into c
          
           Pairs of (  a,  b,  c ) values differing in only a few bits will usually produce
           values of c that look totally different. This was tested for
          
           * pairs that differed by one bit,   by two bits,   in any combination of top bits
           of (  a,  b,  c ),   or in any combination of bottom bits of (  a,  b,  c ).
          
           * "differ" is defined as +,   -,   ^,   or ~^. For + and -,   I transformed the
           output delta to a Gray code (  a^(  a>>1 ) ) so a string of 1's (  as is commonly
           produced by subtraction ) look like a single 1-bit difference. * the base
           values were pseudorandom,   all zero but one bit set,   or all zero plus a
           counter that starts at zero.
          
           These constants passed:
           14 11 25 16 4 14 24
           12 14 25 16 4 14 24
           and these came close:
           4 8 15 26 3 22 24
           10 8 15 26 3 22 24
           11 8 15 26 3 22 24
           -------------------------------------------------------------------------------
          */
          #define final(  a,  b,  c ) \
           { \
           c ^= b; c -= rot(  b,  14 ); \
           a ^= c; a -= rot(  c,  11 ); \
           b ^= a; b -= rot(  a,  25 ); \
           c ^= b; c -= rot(  b,  16 ); \
           a ^= c; a -= rot(  c,  4 ); \
           b ^= a; b -= rot(  a,  14 ); \
           c ^= b; c -= rot(  b,  24 ); \
           }
          
          /**
           * The follow is the documentation from Bob Jenkin's hash function:
           *
           * http://burtleburtle.net/bob/hash/doobs.html
           *
           * The function hashlittle(   ) has been renamed.
           *
           * hashlittle(   ) -- hash a variable-length key into a 32-bit value
           *
           * k : the key (  the unaligned variable-length array of bytes )
           * length : the length of the key,   counting by bytes
           * initval : can be any 4-byte value
     151   *
           * Returns a 32-bit value. Every bit of the key affects every bit of the
           * return value. Two keys differing by one or two bits will have totally
           * different hash values.
           *
           * The best hash table sizes are powers of 2. There is no need to do mod a
           * prime (  mod is sooo slow! ). If you need less than 32 bits,   use a bitmask.
           * For example,   if you need only 10 bits,   do h = (  h & hashmask(  10 ) ); In which
           * case,   the hash table should have hashsize(  10 ) elements.
           *
           * If you are hashing n strings (  uint8_t ** )k,   do it like this: for (  i=0,   h=0;
           * i<n; ++i ) h = hashlittle(   k[i],   len[i],   h );
           *
           * By Bob Jenkins,   2006. bob_jenkins@burtleburtle.net. You may use this
           * code any way you wish,   private,   educational,   or commercial. It's free.
           *
           * Use for hash table lookup,   or anything where one collision in 2^^32 is
           * acceptable. Do NOT use for cryptographic purposes.
          */
          
          #define initval (  20010928 )
          uint32_t
          rtems_rfs_dir_hash (  const void *key,   size_t length )
          {
           uint32_t a,  b,  c; /* internal state */
           union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
          
           /* Set up the internal state */
           a = b = c = 0xdeadbeef + (  (  uint32_t )length ) + initval;
          
           u.ptr = key;
           if (  HASH_LITTLE_ENDIAN && (  (  u.i & 0x3 ) == 0 ) ) {
           const uint32_t *k = (  const uint32_t * )key; /* read 32-bit chunks */
           /*const uint8_t *k8;*/
          
           /*------ all but last block: aligned reads and affect 32 bits of (  a,  b,  c ) */
           while (  length > 12 )
           {
           a += k[0];
           b += k[1];
           c += k[2];
           mix(  a,  b,  c );
           length -= 12;
           k += 3;
           }
          
           /*----------------------------- handle the last (  probably partial ) block */
           /*
           * "k[2]&0xffffff" actually reads beyond the end of the string,   but
           * then masks off the part it's not allowed to read. Because the
           * string is aligned,   the masked-off tail is in the same word as the
           * rest of the string. Every machine with memory protection I've seen
           * does it on word boundaries,   so is OK with this. But VALGRIND will
           * still catch it and complain. The masking trick does make the hash
           * noticably faster for short strings (  like English words ).
           */
          #ifndef VALGRIND
          
           switch(  length )
           {
           case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
           case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
           case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
           case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
           case 8 : b+=k[1]; a+=k[0]; break;
           case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
           case 6 : b+=k[1]&0xffff; a+=k[0]; break;
           case 5 : b+=k[1]&0xff; a+=k[0]; break;
           case 4 : a+=k[0]; break;
           case 3 : a+=k[0]&0xffffff; break;
           case 2 : a+=k[0]&0xffff; break;
           case 1 : a+=k[0]&0xff; break;
           case 0 : return c; /* zero length strings require no mixing */
           }
          
          #else /* make valgrind happy */
          
           k8 = (  const uint8_t * )k;
           switch(  length )
           {
           case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
           case 11: c+=(  (  uint32_t )k8[10] )<<16; /* fall through */
           case 10: c+=(  (  uint32_t )k8[9] )<<8; /* fall through */
           case 9 : c+=k8[8]; /* fall through */
           case 8 : b+=k[1]; a+=k[0]; break;
           case 7 : b+=(  (  uint32_t )k8[6] )<<16; /* fall through */
           case 6 : b+=(  (  uint32_t )k8[5] )<<8; /* fall through */
           case 5 : b+=k8[4]; /* fall through */
           case 4 : a+=k[0]; break;
           case 3 : a+=(  (  uint32_t )k8[2] )<<16; /* fall through */
           case 2 : a+=(  (  uint32_t )k8[1] )<<8; /* fall through */
           case 1 : a+=k8[0]; break;
           case 0 : return c;
           }
          
          #endif /* !valgrind */
          
           } else if (  HASH_LITTLE_ENDIAN && (  (  u.i & 0x1 ) == 0 ) ) {
           const uint16_t *k = (  const uint16_t * )key; /* read 16-bit chunks */
           const uint8_t *k8;
          
           /*--------------- all but last block: aligned reads and different mixing */
           while (  length > 12 )
           {
           a += k[0] + (  (  (  uint32_t )k[1] )<<16 );
           b += k[2] + (  (  (  uint32_t )k[3] )<<16 );
           c += k[4] + (  (  (  uint32_t )k[5] )<<16 );
           mix(  a,  b,  c );
           length -= 12;
           k += 6;
           }
          
           /*----------------------------- handle the last (  probably partial ) block */
           k8 = (  const uint8_t * )k;
           switch(  length )
           {
           case 12: c+=k[4]+(  (  (  uint32_t )k[5] )<<16 );
           b+=k[2]+(  (  (  uint32_t )k[3] )<<16 );
           a+=k[0]+(  (  (  uint32_t )k[1] )<<16 );
           break;
           case 11: c+=(  (  uint32_t )k8[10] )<<16; /* fall through */
           case 10: c+=k[4];
           b+=k[2]+(  (  (  uint32_t )k[3] )<<16 );
           a+=k[0]+(  (  (  uint32_t )k[1] )<<16 );
           break;
           case 9 : c+=k8[8]; /* fall through */
           case 8 : b+=k[2]+(  (  (  uint32_t )k[3] )<<16 );
           a+=k[0]+(  (  (  uint32_t )k[1] )<<16 );
           break;
           case 7 : b+=(  (  uint32_t )k8[6] )<<16; /* fall through */
           case 6 : b+=k[2];
           a+=k[0]+(  (  (  uint32_t )k[1] )<<16 );
           break;
           case 5 : b+=k8[4]; /* fall through */
           case 4 : a+=k[0]+(  (  (  uint32_t )k[1] )<<16 );
           break;
           case 3 : a+=(  (  uint32_t )k8[2] )<<16; /* fall through */
           case 2 : a+=k[0];
           break;
           case 1 : a+=k8[0];
           break;
           case 0 : return c; /* zero length requires no mixing */
           }
          
           } else { /* need to read the key one byte at a time */
           const uint8_t *k = (  const uint8_t * )key;
          
           /*--------------- all but the last block: affect some 32 bits of (  a,  b,  c ) */
           while (  length > 12 )
           {
           a += k[0];
           a += (  (  uint32_t )k[1] )<<8;
           a += (  (  uint32_t )k[2] )<<16;
           a += (  (  uint32_t )k[3] )<<24;
           b += k[4];
           b += (  (  uint32_t )k[5] )<<8;
           b += (  (  uint32_t )k[6] )<<16;
           b += (  (  uint32_t )k[7] )<<24;
           c += k[8];
           c += (  (  uint32_t )k[9] )<<8;
           c += (  (  uint32_t )k[10] )<<16;
           c += (  (  uint32_t )k[11] )<<24;
           mix(  a,  b,  c );
           length -= 12;
           k += 12;
           }
          
           /*-------------------------------- last block: affect all 32 bits of (  c ) */
           switch(  length ) /* all the case statements fall through */
           {
           case 12: c+=(  (  uint32_t )k[11] )<<24;
           case 11: c+=(  (  uint32_t )k[10] )<<16;
           case 10: c+=(  (  uint32_t )k[9] )<<8;
           case 9 : c+=k[8];
           case 8 : b+=(  (  uint32_t )k[7] )<<24;
           case 7 : b+=(  (  uint32_t )k[6] )<<16;
           case 6 : b+=(  (  uint32_t )k[5] )<<8;
           case 5 : b+=k[4];
           case 4 : a+=(  (  uint32_t )k[3] )<<24;
           case 3 : a+=(  (  uint32_t )k[2] )<<16;
           case 2 : a+=(  (  uint32_t )k[1] )<<8;
           case 1 : a+=k[0];
           break;
           case 0 : return c;
           }
           }
          
           final(  a,  b,  c );
           return c;
          }
          

libfs/src/rfs/rtems-rfs-dir.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-dir.c,  v 1.8 2010/10/11 04:34:48 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Directory Routines.
           *
           * These functions manage blocks in the directory format. A directory entry is
           * a variable length record in the block. The entry consists of a length,   hash
           * and the string. The length allows the next entry to be located and the hash
           * allows a simple check to be performed wihtout a string compare. Directory
           * entries do not span a block and removal of an entry results in the space in
           * the block being compacted and the spare area being initialised to ones.
           *
           * The maximum length can be 1 or 2 bytes depending on the value in the
           * superblock.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #if SIZEOF_OFF_T == 8
          #define PRIdoff_t PRIo64
          #elif SIZEOF_OFF_T == 4
          #define PRIdoff_t PRIo32
          #else
          #error "unsupported size of off_t"
          #endif
          
          #include <rtems/rfs/rtems-rfs-block.h>
          #include <rtems/rfs/rtems-rfs-buffer.h>
          #include <rtems/rfs/rtems-rfs-file-system.h>
          #include <rtems/rfs/rtems-rfs-trace.h>
          #include <rtems/rfs/rtems-rfs-dir.h>
          #include <rtems/rfs/rtems-rfs-dir-hash.h>
          
          /**
           * Validate the directory entry data.
           */
          #define rtems_rfs_dir_entry_valid(  _f,   _l,   _i ) \
           (  (  (  _l ) <= RTEMS_RFS_DIR_ENTRY_SIZE ) || (  (  _l ) >= rtems_rfs_fs_max_name (  _f ) ) \
           || (  _i < RTEMS_RFS_ROOT_INO ) || (  _i > rtems_rfs_fs_inodes (  _f ) ) )
      55  
          int
          rtems_rfs_dir_lookup_ino (  rtems_rfs_file_system* fs,  
           rtems_rfs_inode_handle* inode,  
           const char* name,  
           int length,  
           rtems_rfs_ino* ino,  
           uint32_t* offset )
          {
           rtems_rfs_block_map map;
           rtems_rfs_buffer_handle entries;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_LOOKUP_INO ) )
           {
           int c;
           printf (  "rtems-rfs: dir-lookup-ino: lookup ino: root=%" PRId32 ",   path=",  
           inode->ino );
           for (  c = 0; c < length; c++ )
           printf (  "%c",   name[c] );
           printf (  ",   len=%d\n",   length );
           }
          
           *ino = RTEMS_RFS_EMPTY_INO;
           *offset = 0;
          
           rc = rtems_rfs_block_map_open (  fs,   inode,   &map );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_LOOKUP_INO ) )
           printf (  "rtems-rfs: dir-lookup-ino: map open failed for ino %" PRIu32 ": %d: %s",  
           rtems_rfs_inode_ino (  inode ),   rc,   strerror (  rc ) );
           return rc;
           }
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &entries );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_LOOKUP_INO ) )
           printf (  "rtems-rfs: dir-lookup-ino: handle open failed for ino %" PRIu32 ": %d: %s",  
           rtems_rfs_inode_ino (  inode ),   rc,   strerror (  rc ) );
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
           }
           else
           {
           rtems_rfs_block_no block;
           uint32_t hash;
          
           /*
           * Calculate the hash of the look up string.
           */
           hash = rtems_rfs_dir_hash (  name,   length );
          
           /*
           * Locate the first block. The map points to the start after open so just
           * seek 0. If an error the block will be 0.
           */
           rc = rtems_rfs_block_map_seek (  fs,   &map,   0,   &block );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_LOOKUP_INO ) )
           printf (  "rtems-rfs: dir-lookup-ino: block map find failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           if (  rc == ENXIO )
           rc = ENOENT;
           rtems_rfs_buffer_handle_close (  fs,   &entries );
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
           }
          
           while (  (  rc == 0 ) && block )
           {
           uint8_t* entry;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_LOOKUP_INO ) )
           printf (  "rtems-rfs: dir-lookup-ino: block read,   ino=%" PRIu32 " bno=%" PRId32 "\n",  
           rtems_rfs_inode_ino (  inode ),   map.bpos.bno );
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &entries,   block,   true );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_LOOKUP_INO ) )
           printf (  "rtems-rfs: dir-lookup-ino: block read,   ino=%" PRIu32 " block=%" PRId32 ": %d: %s\n",  
           rtems_rfs_inode_ino (  inode ),   block,   rc,   strerror (  rc ) );
           break;
           }
          
           /*
           * Search the block to see if the name matches. A hash of 0xffff or 0x0
           * means the entry is empty.
           */
          
           entry = rtems_rfs_buffer_data (  &entries );
          
           map.bpos.boff = 0;
          
           while (  map.bpos.boff < (  rtems_rfs_fs_block_size (  fs ) - RTEMS_RFS_DIR_ENTRY_SIZE ) )
           {
           uint32_t ehash;
           int elength;
          
           ehash = rtems_rfs_dir_entry_hash (  entry );
           elength = rtems_rfs_dir_entry_length (  entry );
           *ino = rtems_rfs_dir_entry_ino (  entry );
          
           if (  elength == RTEMS_RFS_DIR_ENTRY_EMPTY )
           break;
          
           if (  rtems_rfs_dir_entry_valid (  fs,   elength,   *ino ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_LOOKUP_INO ) )
           printf (  "rtems-rfs: dir-lookup-ino: "
           "bad length or ino for ino %" PRIu32 ": %u/%" PRId32 " @ %04" PRIx32 "\n",  
           rtems_rfs_inode_ino (  inode ),   elength,   *ino,   map.bpos.boff );
           rc = EIO;
           break;
           }
          
           if (  ehash == hash )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_LOOKUP_INO_CHECK ) )
           printf (  "rtems-rfs: dir-lookup-ino: "
           "checking entry for ino %" PRId32 ": bno=%04" PRIx32 "/off=%04" PRIx32
           " length:%d ino:%" PRId32 "\n",  
           rtems_rfs_inode_ino (  inode ),   map.bpos.bno,   map.bpos.boff,  
           elength,   rtems_rfs_dir_entry_ino (  entry ) );
          
           if (  memcmp (  entry + RTEMS_RFS_DIR_ENTRY_SIZE,   name,   length ) == 0 )
           {
           *offset = rtems_rfs_block_map_pos (  fs,   &map );
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_LOOKUP_INO_FOUND ) )
           printf (  "rtems-rfs: dir-lookup-ino: "
           "entry found in ino %" PRIu32 ",   ino=%" PRIu32 " offset=%" PRIu32 "\n",  
           rtems_rfs_inode_ino (  inode ),   *ino,   *offset );
          
           rtems_rfs_buffer_handle_close (  fs,   &entries );
           rtems_rfs_block_map_close (  fs,   &map );
           return 0;
           }
           }
          
           map.bpos.boff += elength;
           entry += elength;
           }
          
           if (  rc == 0 )
           {
           rc = rtems_rfs_block_map_next_block (  fs,   &map,   &block );
           if (  (  rc > 0 ) && (  rc != ENXIO ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_LOOKUP_INO ) )
           printf (  "rtems-rfs: dir-lookup-ino: "
           "block map next block failed in ino %" PRIu32 ": %d: %s\n",  
           rtems_rfs_inode_ino (  inode ),   rc,   strerror (  rc ) );
           }
           if (  rc == ENXIO )
           rc = ENOENT;
           }
           }
          
           if (  (  rc == 0 ) && (  block == 0 ) )
           {
           rc = EIO;
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_LOOKUP_INO ) )
           printf (  "rtems-rfs: dir-lookup-ino: block is 0 in ino %" PRIu32 ": %d: %s\n",  
           rtems_rfs_inode_ino (  inode ),   rc,   strerror (  rc ) );
           }
           }
          
           rtems_rfs_buffer_handle_close (  fs,   &entries );
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
          }
     230  
          int
          rtems_rfs_dir_add_entry (  rtems_rfs_file_system* fs,  
           rtems_rfs_inode_handle* dir,  
           const char* name,  
           size_t length,  
           rtems_rfs_ino ino )
          {
           rtems_rfs_block_map map;
           rtems_rfs_block_pos bpos;
           rtems_rfs_buffer_handle buffer;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_ADD_ENTRY ) )
           {
           int c;
           printf (  "rtems-rfs: dir-add-entry: dir=%" PRId32 ",   name=",  
           rtems_rfs_inode_ino (  dir ) );
           for (  c = 0; c < length; c++ )
           printf (  "%c",   name[c] );
           printf (  ",   len=%zd\n",   length );
           }
          
           rc = rtems_rfs_block_map_open (  fs,   dir,   &map );
           if (  rc > 0 )
           return rc;
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
           }
          
           /*
           * Search the map from the beginning to find any empty space.
           */
           rtems_rfs_block_set_bpos_zero (  &bpos );
          
           while (  true )
           {
           rtems_rfs_block_no block;
           uint8_t* entry;
           int offset;
           bool read = true;
          
           /*
           * Locate the first block. If an error the block will be 0. If the map is
           * empty which happens when creating a directory and adding the first entry
           * the seek will return ENXIO. In this case we need to grow the directory.
           */
           rc = rtems_rfs_block_map_find (  fs,   &map,   &bpos,   &block );
           if (  rc > 0 )
           {
           if (  rc != ENXIO )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_ADD_ENTRY ) )
           printf (  "rtems-rfs: dir-add-entry: "
           "block map find failed for ino %" PRIu32 ": %d: %s\n",  
           rtems_rfs_inode_ino (  dir ),   rc,   strerror (  rc ) );
           break;
           }
          
           /*
           * We have reached the end of the directory so add a block.
           */
           rc = rtems_rfs_block_map_grow (  fs,   &map,   1,   &block );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_ADD_ENTRY ) )
           printf (  "rtems-rfs: dir-add-entry: "
           "block map grow failed for ino %" PRIu32 ": %d: %s\n",  
           rtems_rfs_inode_ino (  dir ),   rc,   strerror (  rc ) );
           break;
           }
          
           read = false;
           }
          
           bpos.bno++;
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &buffer,   block,   read );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_ADD_ENTRY ) )
           printf (  "rtems-rfs: dir-add-entry: "
           "block buffer req failed for ino %" PRIu32 ": %d: %s\n",  
           rtems_rfs_inode_ino (  dir ),   rc,   strerror (  rc ) );
           break;
           }
          
           entry = rtems_rfs_buffer_data (  &buffer );
          
           if (  !read )
           memset (  entry,   0xff,   rtems_rfs_fs_block_size (  fs ) );
          
           offset = 0;
          
           while (  offset < (  rtems_rfs_fs_block_size (  fs ) - RTEMS_RFS_DIR_ENTRY_SIZE ) )
           {
           rtems_rfs_ino eino;
           int elength;
          
           elength = rtems_rfs_dir_entry_length (  entry );
           eino = rtems_rfs_dir_entry_ino (  entry );
          
           if (  elength == RTEMS_RFS_DIR_ENTRY_EMPTY )
           {
           if (  (  length + RTEMS_RFS_DIR_ENTRY_SIZE ) <
           (  rtems_rfs_fs_block_size (  fs ) - offset ) )
           {
           uint32_t hash;
           hash = rtems_rfs_dir_hash (  name,   length );
           rtems_rfs_dir_set_entry_hash (  entry,   hash );
           rtems_rfs_dir_set_entry_ino (  entry,   ino );
           rtems_rfs_dir_set_entry_length (  entry,  
           RTEMS_RFS_DIR_ENTRY_SIZE + length );
           memcpy (  entry + RTEMS_RFS_DIR_ENTRY_SIZE,   name,   length );
           rtems_rfs_buffer_mark_dirty (  &buffer );
           rtems_rfs_buffer_handle_close (  fs,   &buffer );
           rtems_rfs_block_map_close (  fs,   &map );
           return 0;
           }
          
           break;
           }
          
           if (  rtems_rfs_dir_entry_valid (  fs,   elength,   eino ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_ADD_ENTRY ) )
           printf (  "rtems-rfs: dir-add-entry: "
           "bad length or ino for ino %" PRIu32 ": %u/%" PRId32 " @ %04x\n",  
           rtems_rfs_inode_ino (  dir ),   elength,   eino,   offset );
           rtems_rfs_buffer_handle_close (  fs,   &buffer );
           rtems_rfs_block_map_close (  fs,   &map );
           return EIO;
           }
          
           entry += elength;
           offset += elength;
           }
           }
          
           rtems_rfs_buffer_handle_close (  fs,   &buffer );
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
          }
     377  
          int
          rtems_rfs_dir_del_entry (  rtems_rfs_file_system* fs,  
           rtems_rfs_inode_handle* dir,  
           rtems_rfs_ino ino,  
           uint32_t offset )
          {
           rtems_rfs_block_map map;
           rtems_rfs_block_no block;
           rtems_rfs_buffer_handle buffer;
           bool search;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_DEL_ENTRY ) )
           printf (  "rtems-rfs: dir-del-entry: dir=%" PRId32 ",   entry=%" PRId32 " offset=%" PRIu32 "\n",  
           rtems_rfs_inode_ino (  dir ),   ino,   offset );
          
           rc = rtems_rfs_block_map_open (  fs,   dir,   &map );
           if (  rc > 0 )
           return rc;
          
           rc = rtems_rfs_block_map_seek (  fs,   &map,   offset,   &block );
           if (  rc > 0 )
           {
           if (  rc == ENXIO )
           rc = ENOENT;
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
           }
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
           }
          
           /*
           * Only search if the offset is 0 else we are at that position.
           */
           search = offset ? false : true;
          
           while (  rc == 0 )
           {
           uint8_t* entry;
           int eoffset;
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &buffer,   block,   true );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_DEL_ENTRY ) )
           printf (  "rtems-rfs: dir-del-entry: "
           "block buffer req failed for ino %" PRIu32 ": %d: %s\n",  
           rtems_rfs_inode_ino (  dir ),   rc,   strerror (  rc ) );
           break;
           }
          
           /*
           * If we are searching start at the beginning of the block. If not searching
           * skip to the offset in the block.
           */
           if (  search )
           eoffset = 0;
           else
           eoffset = offset % rtems_rfs_fs_block_size (  fs );
          
           entry = rtems_rfs_buffer_data (  &buffer ) + eoffset;
          
           while (  eoffset < (  rtems_rfs_fs_block_size (  fs ) - RTEMS_RFS_DIR_ENTRY_SIZE ) )
           {
           rtems_rfs_ino eino;
           int elength;
          
           elength = rtems_rfs_dir_entry_length (  entry );
           eino = rtems_rfs_dir_entry_ino (  entry );
          
           if (  elength == RTEMS_RFS_DIR_ENTRY_EMPTY )
           break;
          
           if (  rtems_rfs_dir_entry_valid (  fs,   elength,   eino ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_DEL_ENTRY ) )
           printf (  "rtems-rfs: dir-del-entry: "
           "bad length or ino for ino %" PRIu32 ": %u/%" PRId32
           " @ %" PRIu32 ".%04x\n",  
           rtems_rfs_inode_ino (  dir ),   elength,   eino,   block,   eoffset );
           rc = EIO;
           break;
           }
          
           if (  ino == rtems_rfs_dir_entry_ino (  entry ) )
           {
           uint32_t remaining;
           remaining = rtems_rfs_fs_block_size (  fs ) - (  eoffset + elength );
           memmove (  entry,   entry + elength,   remaining );
           memset (  entry + remaining,   0xff,   elength );
          
           /*
           * If the remainder of the block is empty and this is the start of the
           * block and it is the last block in the map shrink the map.
           *
           * @note We could check again to see if the new end block in the map is
           * also empty. This way we could clean up an empty directory.
           */
           elength = rtems_rfs_dir_entry_length (  entry );
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_DEL_ENTRY ) )
           printf (  "rtems-rfs: dir-del-entry: "
           "last block free for ino %" PRIu32 ": elength=%i block=%" PRIu32
           " offset=%d last=%s\n",  
           ino,   elength,   block,   eoffset,  
           rtems_rfs_block_map_last (  &map ) ? "yes" : "no" );
          
           if (  (  elength == RTEMS_RFS_DIR_ENTRY_EMPTY ) &&
           (  eoffset == 0 ) && rtems_rfs_block_map_last (  &map ) )
           {
           rc = rtems_rfs_block_map_shrink (  fs,   &map,   1 );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_DEL_ENTRY ) )
           printf (  "rtems-rfs: dir-del-entry: "
           "block map shrink failed for ino %" PRIu32 ": %d: %s\n",  
           rtems_rfs_inode_ino (  dir ),   rc,   strerror (  rc ) );
           }
           }
          
           rtems_rfs_buffer_mark_dirty (  &buffer );
           rtems_rfs_buffer_handle_close (  fs,   &buffer );
           rtems_rfs_block_map_close (  fs,   &map );
           return 0;
           }
          
           if (  !search )
           {
           rc = EIO;
           break;
           }
          
           entry += elength;
           eoffset += elength;
           }
          
           if (  rc == 0 )
           {
           rc = rtems_rfs_block_map_next_block (  fs,   &map,   &block );
           if (  rc == ENXIO )
           rc = ENOENT;
           }
           }
          
           rtems_rfs_buffer_handle_close (  fs,   &buffer );
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
          }
     531  
          int
          rtems_rfs_dir_read (  rtems_rfs_file_system* fs,  
           rtems_rfs_inode_handle* dir,  
           rtems_rfs_pos_rel offset,  
           struct dirent* dirent,  
           size_t* length )
          {
           rtems_rfs_block_map map;
           rtems_rfs_buffer_handle buffer;
           rtems_rfs_block_no block;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_READ ) )
           printf (  "rtems-rfs: dir-read: dir=%" PRId32 " offset=%" PRId64 "\n",  
           rtems_rfs_inode_ino (  dir ),   offset );
          
           *length = 0;
          
           rc = rtems_rfs_block_map_open (  fs,   dir,   &map );
           if (  rc > 0 )
           return rc;
          
           if (  (  (  rtems_rfs_fs_block_size (  fs ) -
           (  offset % rtems_rfs_fs_block_size (  fs ) ) ) <= RTEMS_RFS_DIR_ENTRY_SIZE ) )
           offset = (  (  (  offset / rtems_rfs_fs_block_size (  fs ) ) + 1 ) *
           rtems_rfs_fs_block_size (  fs ) );
          
           rc = rtems_rfs_block_map_seek (  fs,   &map,   offset,   &block );
           if (  rc > 0 )
           {
           if (  rc == ENXIO )
           rc = ENOENT;
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
           }
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
           }
          
           /*
           * Look for an empty entry and if this is the last block that is the end of
           * the directory.
           */
           while (  rc == 0 )
           {
           uint8_t* entry;
           rtems_rfs_ino eino;
           int elength;
           int remaining;
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &buffer,   block,   true );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &buffer );
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
           }
          
           entry = rtems_rfs_buffer_data (  &buffer );
           entry += map.bpos.boff;
          
           elength = rtems_rfs_dir_entry_length (  entry );
           eino = rtems_rfs_dir_entry_ino (  entry );
          
           if (  elength != RTEMS_RFS_DIR_ENTRY_EMPTY )
           {
           if (  rtems_rfs_dir_entry_valid (  fs,   elength,   eino ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_READ ) )
           printf (  "rtems-rfs: dir-read: "
           "bad length or ino for ino %" PRIu32 ": %u/%" PRId32 " @ %04" PRIx32 "\n",  
           rtems_rfs_inode_ino (  dir ),   elength,   eino,   map.bpos.boff );
           rc = EIO;
           break;
           }
          
           memset (  dirent,   0,   sizeof (  struct dirent ) );
           dirent->d_off = offset;
           dirent->d_reclen = sizeof (  struct dirent );
          
           *length += elength;
          
           remaining = rtems_rfs_fs_block_size (  fs ) - (  map.bpos.boff + elength );
          
           if (  remaining <= RTEMS_RFS_DIR_ENTRY_SIZE )
           *length += remaining;
          
           elength -= RTEMS_RFS_DIR_ENTRY_SIZE;
           if (  elength > NAME_MAX )
           elength = NAME_MAX;
          
           memcpy (  dirent->d_name,   entry + RTEMS_RFS_DIR_ENTRY_SIZE,   elength );
          
           dirent->d_ino = rtems_rfs_dir_entry_ino (  entry );
           dirent->d_namlen = elength;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_READ ) )
           printf (  "rtems-rfs: dir-read: found off:%" PRIdoff_t " ino:%ld name=%s\n",  
           dirent->d_off,   dirent->d_ino,   dirent->d_name );
           break;
           }
          
           *length += rtems_rfs_fs_block_size (  fs ) - map.bpos.boff;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_READ ) )
           printf (  "rtems-rfs: dir-read: next block: off:%" PRId64 " length:%zd\n",  
           offset,   *length );
          
           rc = rtems_rfs_block_map_next_block (  fs,   &map,   &block );
           if (  rc == ENXIO )
           rc = ENOENT;
           }
          
           rtems_rfs_buffer_handle_close (  fs,   &buffer );
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
          }
     653  
          int
          rtems_rfs_dir_empty (  rtems_rfs_file_system* fs,  
           rtems_rfs_inode_handle* dir )
          {
           rtems_rfs_block_map map;
           rtems_rfs_buffer_handle buffer;
           rtems_rfs_block_no block;
           bool empty;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_READ ) )
           printf (  "rtems-rfs: dir-empty: dir=%" PRId32 "\n",   rtems_rfs_inode_ino (  dir ) );
          
           empty = true;
          
           rc = rtems_rfs_block_map_open (  fs,   dir,   &map );
           if (  rc > 0 )
           return rc;
          
           rc = rtems_rfs_block_map_seek (  fs,   &map,   0,   &block );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
           }
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
           }
          
           /*
           * Look for an empty entry and if this is the last block that is the end of
           * the directory.
           */
           while (  empty )
           {
           uint8_t* entry;
           int offset;
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &buffer,   block,   true );
           if (  rc > 0 )
           break;
          
           entry = rtems_rfs_buffer_data (  &buffer );
           offset = 0;
          
           while (  offset < (  rtems_rfs_fs_block_size (  fs ) - RTEMS_RFS_DIR_ENTRY_SIZE ) )
           {
           rtems_rfs_ino eino;
           int elength;
          
           elength = rtems_rfs_dir_entry_length (  entry );
           eino = rtems_rfs_dir_entry_ino (  entry );
          
           if (  elength == RTEMS_RFS_DIR_ENTRY_EMPTY )
           break;
          
           if (  rtems_rfs_dir_entry_valid (  fs,   elength,   eino ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_DIR_EMPTY ) )
           printf (  "rtems-rfs: dir-empty: "
           "bad length or ino for ino %" PRIu32 ": %u/%" PRIu32 " @ %04x\n",  
           rtems_rfs_inode_ino (  dir ),   elength,   eino,   offset );
           rc = EIO;
           break;
           }
          
           /*
           * Ignore the current (  . ) and parent (  .. ) entries. Anything else means
           * the directory is not empty.
           */
           if (  (  (  elength != (  RTEMS_RFS_DIR_ENTRY_SIZE + 1 ) ) ||
           (  entry[RTEMS_RFS_DIR_ENTRY_SIZE] != '.' ) ) &&
           (  (  elength != (  RTEMS_RFS_DIR_ENTRY_SIZE + 2 ) ) ||
           (  entry[RTEMS_RFS_DIR_ENTRY_SIZE] != '.' ) ||
           (  entry[RTEMS_RFS_DIR_ENTRY_SIZE + 1] != '.' ) ) )
           {
           empty = false;
           break;
           }
          
           entry += elength;
           offset += elength;
           }
          
           if (  empty )
           {
           rc = rtems_rfs_block_map_next_block (  fs,   &map,   &block );
           if (  rc > 0 )
           {
           if (  rc == ENXIO )
           rc = 0;
           break;
           }
           }
           }
          
           if (  (  rc == 0 ) && !empty )
           rc = ENOTEMPTY;
          
           rtems_rfs_buffer_handle_close (  fs,   &buffer );
           rtems_rfs_block_map_close (  fs,   &map );
           return rc;
          }

libfs/src/rfs/rtems-rfs-file-system.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-file-system.c,  v 1.6 2010/06/17 22:00:47 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Open
           *
           * Open the file system by reading the superblock and then the group data.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <rtems/rfs/rtems-rfs-data.h>
          #include <rtems/rfs/rtems-rfs-file-system.h>
          #include <rtems/rfs/rtems-rfs-inode.h>
          #include <rtems/rfs/rtems-rfs-trace.h>
          
          uint64_t
      32  rtems_rfs_fs_size (  rtems_rfs_file_system* fs )
          {
           uint64_t blocks = rtems_rfs_fs_blocks (  fs );
           uint64_t block_size = rtems_rfs_fs_block_size (  fs );
           return blocks * block_size;
          }
          
          uint64_t
      40  rtems_rfs_fs_media_size (  rtems_rfs_file_system* fs )
          {
           uint64_t media_blocks = (  uint64_t ) rtems_rfs_fs_media_blocks (  fs );
           uint64_t media_block_size = (  uint64_t ) rtems_rfs_fs_media_block_size (  fs );
           return media_blocks * media_block_size;
          }
          
          static int
      48  rtems_rfs_fs_read_superblock (  rtems_rfs_file_system* fs )
          {
           rtems_rfs_buffer_handle handle;
           uint8_t* sb;
           int group;
           int rc;
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &handle );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: read-superblock: handle open failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           return rc;
           }
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &handle,   0,   true );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: read-superblock: request failed%d: %s\n",  
           rc,   strerror (  rc ) );
           return rc;
           }
          
           sb = rtems_rfs_buffer_data (  &handle );
          
          #define read_sb(  _o ) rtems_rfs_read_u32 (  sb + (  _o ) )
          
           if (  read_sb (  RTEMS_RFS_SB_OFFSET_MAGIC ) != RTEMS_RFS_SB_MAGIC )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: read-superblock: invalid superblock,   bad magic\n" );
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           return EIO;
           }
          
           fs->blocks = read_sb (  RTEMS_RFS_SB_OFFSET_BLOCKS );
           fs->block_size = read_sb (  RTEMS_RFS_SB_OFFSET_BLOCK_SIZE );
          
           if (  rtems_rfs_fs_size(  fs ) > rtems_rfs_fs_media_size (  fs ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: read-superblock: invalid superblock block/size count\n" );
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           return EIO;
           }
          
           if (  (  read_sb (  RTEMS_RFS_SB_OFFSET_VERSION ) & RTEMS_RFS_VERSION_MASK ) !=
           (  RTEMS_RFS_VERSION * RTEMS_RFS_VERSION_MASK ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: read-superblock: incompatible version: %08" PRIx32 " (  %08" PRIx32 " )\n",  
           read_sb (  RTEMS_RFS_SB_OFFSET_VERSION ),   RTEMS_RFS_VERSION_MASK );
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           return EIO;
           }
          
           if (  read_sb (  RTEMS_RFS_SB_OFFSET_INODE_SIZE ) != RTEMS_RFS_INODE_SIZE )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: read-superblock: inode size mismatch: fs:%" PRId32 " target:%" PRId32 "\n",  
           read_sb (  RTEMS_RFS_SB_OFFSET_VERSION ),   RTEMS_RFS_VERSION_MASK );
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           return EIO;
           }
          
           fs->bad_blocks = read_sb (  RTEMS_RFS_SB_OFFSET_BAD_BLOCKS );
           fs->max_name_length = read_sb (  RTEMS_RFS_SB_OFFSET_MAX_NAME_LENGTH );
           fs->group_count = read_sb (  RTEMS_RFS_SB_OFFSET_GROUPS );
           fs->group_blocks = read_sb (  RTEMS_RFS_SB_OFFSET_GROUP_BLOCKS );
           fs->group_inodes = read_sb (  RTEMS_RFS_SB_OFFSET_GROUP_INODES );
          
           fs->blocks_per_block =
           rtems_rfs_fs_block_size (  fs ) / sizeof (  rtems_rfs_inode_block );
          
           fs->block_map_singly_blocks =
           fs->blocks_per_block * RTEMS_RFS_INODE_BLOCKS;
           fs->block_map_doubly_blocks =
           fs->blocks_per_block * fs->blocks_per_block * RTEMS_RFS_INODE_BLOCKS;
          
           fs->inodes = fs->group_count * fs->group_inodes;
          
           fs->inodes_per_block = fs->block_size / RTEMS_RFS_INODE_SIZE;
          
           if (  fs->group_blocks >
           rtems_rfs_bitmap_numof_bits (  rtems_rfs_fs_block_size (  fs ) ) )
           {
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: read-superblock: groups blocks larger than block bits\n" );
           return EIO;
           }
          
           rtems_rfs_buffer_handle_close (  fs,   &handle );
          
           /*
           * Change the block size to the value in the superblock.
           */
           rc = rtems_rfs_buffer_setblksize (  fs,   rtems_rfs_fs_block_size (  fs ) );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: read-superblock: invalid superblock block size%d: %s\n",  
           rc,   strerror (  rc ) );
           return rc;
           }
          
           fs->groups = calloc (  fs->group_count,   sizeof (  rtems_rfs_group ) );
          
           if (  !fs->groups )
           {
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: read-superblock: no memory for group table\n" );
           return ENOMEM;
           }
          
           /*
           * Perform each phase of group initialisation at the same time. This way we
           * know how far the initialisation has gone if an error occurs and we need to
           * close everything.
           */
           for (  group = 0; group < fs->group_count; group++ )
           {
           rc = rtems_rfs_group_open (  fs,  
           rtems_rfs_fs_block (  fs,   group,   0 ),  
           fs->group_blocks,  
           fs->group_inodes,  
           &fs->groups[group] );
           if (  rc > 0 )
           {
           int g;
           for (  g = 0; g < group; g++ )
           rtems_rfs_group_close (  fs,   &fs->groups[g] );
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: read-superblock: no memory for group table%d: %s\n",  
           rc,   strerror (  rc ) );
           return rc;
           }
           }
          
           return 0;
          }
          
          int
     196  rtems_rfs_fs_open (  const char* name,  
           void* user,  
           uint32_t flags,  
           rtems_rfs_file_system** fs )
          {
           rtems_rfs_group* group;
           size_t group_base;
           rtems_rfs_inode_handle inode;
           uint16_t mode;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: open: %s\n",   name );
          
           *fs = malloc (  sizeof (  rtems_rfs_file_system ) );
           if (  !*fs )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: open: no memory for file system data\n" );
           errno = ENOMEM;
           return -1;
           }
          
           memset (  *fs,   0,   sizeof (  rtems_rfs_file_system ) );
          
           (  *fs )->user = user;
           rtems_chain_initialize_empty (  &(  *fs )->buffers );
           rtems_chain_initialize_empty (  &(  *fs )->release );
           rtems_chain_initialize_empty (  &(  *fs )->release_modified );
           rtems_chain_initialize_empty (  &(  *fs )->file_shares );
          
           (  *fs )->max_held_buffers = RTEMS_RFS_FS_MAX_HELD_BUFFERS;
           (  *fs )->buffers_count = 0;
           (  *fs )->release_count = 0;
           (  *fs )->release_modified_count = 0;
           (  *fs )->flags = flags;
          
           group = &(  *fs )->groups[0];
           group_base = 0;
          
           /*
           * Open the buffer interface.
           */
           rc = rtems_rfs_buffer_open (  name,   *fs );
           if (  rc > 0 )
           {
           free (  *fs );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: open: buffer open failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           errno = rc;
           return -1;
           }
          
           rc = rtems_rfs_fs_read_superblock (  *fs );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_close (  *fs );
           free (  *fs );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: open: reading superblock: %d: %s\n",  
           rc,   strerror (  rc ) );
           errno = rc;
           return -1;
           }
          
           rc = rtems_rfs_inode_open (  *fs,   RTEMS_RFS_ROOT_INO,   &inode,   true );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_close (  *fs );
           free (  *fs );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: open: reading root inode: %d: %s\n",  
           rc,   strerror (  rc ) );
           errno = rc;
           return -1;
           }
          
           if (  (  (  *fs )->flags & RTEMS_RFS_FS_FORCE_OPEN ) == 0 )
           {
           mode = rtems_rfs_inode_get_mode (  &inode );
          
           if (  (  mode == 0xffff ) || !RTEMS_RFS_S_ISDIR (  mode ) )
           {
           rtems_rfs_inode_close (  *fs,   &inode );
           rtems_rfs_buffer_close (  *fs );
           free (  *fs );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: open: invalid root inode mode\n" );
           errno = EIO;
           return -1;
           }
           }
          
           rc = rtems_rfs_inode_close (  *fs,   &inode );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_close (  *fs );
           free (  *fs );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_OPEN ) )
           printf (  "rtems-rfs: open: closing root inode: %d: %s\n",   rc,   strerror (  rc ) );
           errno = rc;
           return -1;
           }
          
           errno = 0;
           return 0;
          }
          
          int
     306  rtems_rfs_fs_close (  rtems_rfs_file_system* fs )
          {
           int group;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_CLOSE ) )
           printf (  "rtems-rfs: close\n" );
          
           for (  group = 0; group < fs->group_count; group++ )
           rtems_rfs_group_close (  fs,   &fs->groups[group] );
          
           rtems_rfs_buffer_close (  fs );
          
           free (  fs );
           return 0;
          }

libfs/src/rfs/rtems-rfs-file.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-file.c,  v 1.6 2010/08/26 06:31:15 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems File Routines.
           *
           * These functions manage files.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <rtems/rfs/rtems-rfs-block-pos.h>
          #include <rtems/rfs/rtems-rfs-file.h>
          #include <rtems/rfs/rtems-rfs-file-system.h>
          #include <rtems/rfs/rtems-rfs-trace.h>
          
          int
      32  rtems_rfs_file_open (  rtems_rfs_file_system* fs,  
           rtems_rfs_ino ino,  
           uint32_t flags,  
           rtems_rfs_file_handle** file )
          {
           rtems_rfs_file_handle* handle;
           rtems_rfs_file_shared* shared;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_OPEN ) )
           printf (  "rtems-rfs: file-open: ino=%" PRId32 "\n",   ino );
          
           *file = NULL;
          
           /*
           * Allocate a new handle and initialise it. Do this before we deal with the
           * shared node data so we do not have to be concerned with reference
           * counting.
           */
           handle = malloc (  sizeof (  rtems_rfs_file_handle ) );
           if (  !handle )
           return ENOMEM;
          
           memset (  handle,   0,   sizeof (  rtems_rfs_file_handle ) );
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &handle->buffer );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_OPEN ) )
           printf (  "rtems-rfs: file-open: buffer handle open failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           free (  handle );
           return rc;
           }
          
           /*
           * Scan the file system data list of open files for this ino. If found up
           * the reference count and return the pointer to the data.
           */
           shared = rtems_rfs_file_get_shared (  fs,   ino );
           if (  shared )
           {
           shared->references++;
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_OPEN ) )
           printf (  "rtems-rfs: file-open: ino=%" PRId32 " shared\n",   ino );
           }
           else
           {
           /*
           * None exists so create. Copy in the shared parts of the inode we hold in
           * memory.
           */
           shared = malloc (  sizeof (  rtems_rfs_file_shared ) );
           if (  !shared )
           {
           rtems_rfs_buffer_handle_close (  fs,   &handle->buffer );
           free (  handle );
           return ENOMEM;
           }
          
           memset (  shared,   0,   sizeof (  rtems_rfs_file_shared ) );
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &shared->inode,   true );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_OPEN ) )
           printf (  "rtems-rfs: file-open: inode open failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           free (  shared );
           rtems_rfs_buffer_handle_close (  fs,   &handle->buffer );
           free (  handle );
           return rc;
           }
          
           rc = rtems_rfs_block_map_open (  fs,   &shared->inode,   &shared->map );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_OPEN ) )
           printf (  "rtems-rfs: file-open: block map open failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           rtems_rfs_inode_close (  fs,   &shared->inode );
           free (  shared );
           rtems_rfs_buffer_handle_close (  fs,   &handle->buffer );
           free (  handle );
           return rc;
           }
          
           shared->references = 1;
           shared->size.count = rtems_rfs_inode_get_block_count (  &shared->inode );
           shared->size.offset = rtems_rfs_inode_get_block_offset (  &shared->inode );
           shared->atime = rtems_rfs_inode_get_atime (  &shared->inode );
           shared->mtime = rtems_rfs_inode_get_mtime (  &shared->inode );
           shared->ctime = rtems_rfs_inode_get_ctime (  &shared->inode );
           shared->fs = fs;
          
           rtems_chain_append (  &fs->file_shares,   &shared->link );
          
           rtems_rfs_inode_unload (  fs,   &shared->inode,   false );
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_OPEN ) )
           printf (  "rtems-rfs: file-open: ino=%" PRId32 " share created\n",   ino );
           }
          
           handle->flags = flags;
           handle->shared = shared;
          
           *file = handle;
          
           return 0;
          }
          
          int
     144  rtems_rfs_file_close (  rtems_rfs_file_system* fs,  
           rtems_rfs_file_handle* handle )
          {
           int rrc;
           int rc;
          
           rrc = 0;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_CLOSE ) )
           printf (  "rtems-rfs: file-close: entry: ino=%" PRId32 "\n",  
           handle->shared->inode.ino );
          
           if (  handle->shared->references > 0 )
           handle->shared->references--;
          
           if (  handle->shared->references == 0 )
           {
           if (  !rtems_rfs_inode_is_loaded (  &handle->shared->inode ) )
           rrc = rtems_rfs_inode_load (  fs,   &handle->shared->inode );
          
           if (  rrc == 0 )
           {
           /*
           * @todo This could be clever and only update if different.
           */
           rtems_rfs_inode_set_atime (  &handle->shared->inode,  
           handle->shared->atime );
           rtems_rfs_inode_set_mtime (  &handle->shared->inode,  
           handle->shared->mtime );
           rtems_rfs_inode_set_ctime (  &handle->shared->inode,  
           handle->shared->ctime );
           handle->shared->map.size.count = handle->shared->size.count;
           handle->shared->map.size.offset = handle->shared->size.offset;
           }
          
           rc = rtems_rfs_block_map_close (  fs,   &handle->shared->map );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_CLOSE ) )
           printf (  "rtems-rfs: file-close: map close error: ino=%" PRId32 ": %d: %s\n",  
           handle->shared->inode.ino,   rc,   strerror (  rc ) );
           if (  rrc == 0 )
           rrc = rc;
           }
          
           rc = rtems_rfs_inode_close (  fs,   &handle->shared->inode );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_CLOSE ) )
           printf (  "rtems-rfs: file-close: inode close error: ino=%" PRId32 ": %d: %s\n",  
           handle->shared->inode.ino,   rc,   strerror (  rc ) );
           if (  rrc == 0 )
           rrc = rc;
           }
          
           rtems_chain_extract (  &handle->shared->link );
           free (  handle->shared );
           }
          
           rc = rtems_rfs_buffer_handle_close (  fs,   &handle->buffer );
           if (  (  rrc == 0 ) && (  rc > 0 ) )
           rrc = rc;
          
           if (  rrc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_CLOSE ) )
           printf (  "rtems-rfs: file-close: result: %d: %s\n",   rrc,   strerror (  rrc ) );
           }
          
           free (  handle );
          
           return rrc;
          }
          
          int
     219  rtems_rfs_file_io_start (  rtems_rfs_file_handle* handle,  
           size_t* available,  
           bool read )
          {
           size_t size;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_IO ) )
           printf (  "rtems-rfs: file-io: start: %s pos=%" PRIu32 ":%" PRIu32 "\n",  
           read ? "read" : "write",   handle->bpos.bno,   handle->bpos.boff );
          
           if (  !rtems_rfs_buffer_handle_has_block (  &handle->buffer ) )
           {
           rtems_rfs_buffer_block block;
           bool request_read;
           int rc;
          
           request_read = read;
          
           rc = rtems_rfs_block_map_find (  rtems_rfs_file_fs (  handle ),  
           rtems_rfs_file_map (  handle ),  
           rtems_rfs_file_bpos (  handle ),  
           &block );
           if (  rc > 0 )
           {
           /*
           * Has the read reached the EOF ?
           */
           if (  read && (  rc == ENXIO ) )
           {
           *available = 0;
           return 0;
           }
          
           if (  rc != ENXIO )
           return rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_IO ) )
           printf (  "rtems-rfs: file-io: start: grow\n" );
          
           rc = rtems_rfs_block_map_grow (  rtems_rfs_file_fs (  handle ),  
           rtems_rfs_file_map (  handle ),  
           1,   &block );
           if (  rc > 0 )
           return rc;
          
           request_read = false;
           }
           else
           {
           /*
           * If this is a write check if the write starts within a block or the
           * amount of data is less than a block size. If it is read the block
           * rather than getting a block to fill.
           */
           if (  !read &&
           (  rtems_rfs_file_block_offset (  handle ) ||
           (  *available < rtems_rfs_fs_block_size (  rtems_rfs_file_fs (  handle ) ) ) ) )
           request_read = true;
           }
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_IO ) )
           printf (  "rtems-rfs: file-io: start: block=%" PRIu32 " request-read=%s\n",  
           block,   request_read ? "yes" : "no" );
          
           rc = rtems_rfs_buffer_handle_request (  rtems_rfs_file_fs (  handle ),  
           rtems_rfs_file_buffer (  handle ),  
           block,   request_read );
           if (  rc > 0 )
           return rc;
           }
          
           if (  read
           && rtems_rfs_block_map_last (  rtems_rfs_file_map (  handle ) )
           && rtems_rfs_block_map_size_offset (  rtems_rfs_file_map (  handle ) ) )
           size = rtems_rfs_block_map_size_offset (  rtems_rfs_file_map (  handle ) );
           else
           size = rtems_rfs_fs_block_size (  rtems_rfs_file_fs (  handle ) );
          
           *available = size - rtems_rfs_file_block_offset (  handle );
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_IO ) )
           printf (  "rtems-rfs: file-io: start: available=%zu (  %zu )\n",  
           *available,   size );
          
           return 0;
          }
          
          int
     307  rtems_rfs_file_io_end (  rtems_rfs_file_handle* handle,  
           size_t size,  
           bool read )
          {
           bool atime;
           bool mtime;
           bool length;
           int rc = 0;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_IO ) )
           printf (  "rtems-rfs: file-io: end: %s size=%zu\n",  
           read ? "read" : "write",   size );
          
           if (  rtems_rfs_buffer_handle_has_block (  &handle->buffer ) )
           {
           if (  !read )
           rtems_rfs_buffer_mark_dirty (  rtems_rfs_file_buffer (  handle ) );
           rc = rtems_rfs_buffer_handle_release (  rtems_rfs_file_fs (  handle ),  
           rtems_rfs_file_buffer (  handle ) );
           if (  rc > 0 )
           {
           printf (  
           "rtems-rfs: file-io: end: error on release: %s size=%zu: %d: %s\n",  
           read ? "read" : "write",   size,   rc,   strerror (  rc ) );
          
           return rc;
           }
           }
          
           /*
           * Update the handle's position. Only a block size can be handled at a time
           * so no special maths is needed. If the offset is bigger than the block size
           * increase the block number and adjust the offset.
           *
           * If we are the last block and the position is past the current size update
           * the size with the new length. The map holds the block count.
           */
           handle->bpos.boff += size;
          
           if (  handle->bpos.boff >=
           rtems_rfs_fs_block_size (  rtems_rfs_file_fs (  handle ) ) )
           {
           handle->bpos.bno++;
           handle->bpos.boff -= rtems_rfs_fs_block_size (  rtems_rfs_file_fs (  handle ) );
           }
          
           length = false;
           mtime = false;
          
           if (  !read &&
           rtems_rfs_block_map_past_end (  rtems_rfs_file_map (  handle ),  
           rtems_rfs_file_bpos (  handle ) ) )
           {
           rtems_rfs_block_map_set_size_offset (  rtems_rfs_file_map (  handle ),  
           handle->bpos.boff );
           length = true;
           mtime = true;
           }
          
           atime = rtems_rfs_file_update_atime (  handle );
           mtime = rtems_rfs_file_update_mtime (  handle ) && mtime;
           length = rtems_rfs_file_update_length (  handle ) && length;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_IO ) )
           printf (  "rtems-rfs: file-io: end: pos=%" PRIu32 ":%" PRIu32 " %c %c %c\n",  
           handle->bpos.bno,   handle->bpos.boff,  
           atime ? 'A' : '-',   mtime ? 'M' : '-',   length ? 'L' : '-' );
          
           if (  atime || mtime )
           {
           time_t now = time (  NULL );
           if (  read && atime )
           handle->shared->atime = now;
           if (  !read && mtime )
           handle->shared->mtime = now;
           }
           if (  length )
           {
           handle->shared->size.count =
           rtems_rfs_block_map_count (  rtems_rfs_file_map (  handle ) );
           handle->shared->size.offset =
           rtems_rfs_block_map_size_offset (  rtems_rfs_file_map (  handle ) );
           }
          
           return rc;
          }
          
          int
     395  rtems_rfs_file_io_release (  rtems_rfs_file_handle* handle )
          {
           int rc = 0;
           if (  rtems_rfs_buffer_handle_has_block (  &handle->buffer ) )
           rc = rtems_rfs_buffer_handle_release (  rtems_rfs_file_fs (  handle ),  
           rtems_rfs_file_buffer (  handle ) );
           return rc;
          }
          
          int
     405  rtems_rfs_file_seek (  rtems_rfs_file_handle* handle,  
           rtems_rfs_pos pos,  
           rtems_rfs_pos* new_pos )
          {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_IO ) )
           printf (  "rtems-rfs: file-seek: new=%" PRIu64 "\n",   pos );
          
           /*
           * This call only sets the position if it is in a valid part of the file. The
           * user can request past the end of the file then write to extend the
           * file. The lseek entry states:
           *
           * "Although lseek(   ) may position the file offset beyond the end of the
           * file,   this function does not itself extend the size of the file."
           *
           * This means the file needs to set the file size to the pos only when a
           * write occurs.
           */
           if (  pos <= rtems_rfs_file_shared_get_size (  rtems_rfs_file_fs (  handle ),  
           handle->shared ) )
           rtems_rfs_file_set_bpos (  handle,   pos );
          
           *new_pos = pos;
           return 0;
          }
          
          int
     432  rtems_rfs_file_set_size (  rtems_rfs_file_handle* handle,  
           rtems_rfs_pos new_size )
          {
           rtems_rfs_block_map* map = rtems_rfs_file_map (  handle );
           rtems_rfs_pos size;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_FILE_IO ) )
           printf (  "rtems-rfs: file-set-size: size=%" PRIu64 "\n",   new_size );
          
           /*
           * Short cut for the common truncate on open call.
           */
           if (  new_size == 0 )
           {
           rc = rtems_rfs_block_map_free_all (  rtems_rfs_file_fs (  handle ),   map );
           if (  rc > 0 )
           return rc;
           }
           else
           {
           size = rtems_rfs_file_size (  handle );
          
           /*
           * If the file is same size do nothing else grow or shrink it ?
           */
           if (  size != new_size )
           {
           if (  size < new_size )
           {
           /*
           * Grow. Fill with 0's.
           */
           rtems_rfs_pos count;
           uint32_t length;
           bool read_block;
          
           count = new_size - size;
           length = rtems_rfs_fs_block_size (  rtems_rfs_file_fs (  handle ) );
           read_block = false;
          
           while (  count )
           {
           rtems_rfs_buffer_block block;
           rtems_rfs_block_pos bpos;
           uint8_t* dst;
          
           /*
           * Get the block position for the current end of the file as seen by
           * the map. If not found and the EOF grow the map then fill the block
           * with 0.
           */
           rtems_rfs_block_size_get_bpos (  rtems_rfs_block_map_size (  map ),   &bpos );
           rc = rtems_rfs_block_map_find (  rtems_rfs_file_fs (  handle ),  
           map,   &bpos,   &block );
           if (  rc > 0 )
           {
           /*
           * Have we reached the EOF ?
           */
           if (  rc != ENXIO )
           return rc;
          
           rc = rtems_rfs_block_map_grow (  rtems_rfs_file_fs (  handle ),  
           map,   1,   &block );
           if (  rc > 0 )
           return rc;
           }
          
           if (  count < (  length - bpos.boff ) )
           {
           length = count + bpos.boff;
           read_block = true;
           rtems_rfs_block_map_set_size_offset (  map,   length );
           }
           else
           {
           rtems_rfs_block_map_set_size_offset (  map,   0 );
           }
          
           /*
           * Only read the block if the length is not the block size.
           */
           rc = rtems_rfs_buffer_handle_request (  rtems_rfs_file_fs (  handle ),  
           rtems_rfs_file_buffer (  handle ),  
           block,   read_block );
           if (  rc > 0 )
           return rc;
          
           dst = rtems_rfs_buffer_data (  &handle->buffer );
           memset (  dst + bpos.boff,   0,   length - bpos.boff );
          
           rtems_rfs_buffer_mark_dirty (  rtems_rfs_file_buffer (  handle ) );
          
           rc = rtems_rfs_buffer_handle_release (  rtems_rfs_file_fs (  handle ),  
           rtems_rfs_file_buffer (  handle ) );
           if (  rc > 0 )
           return rc;
          
           count -= length - bpos.boff;
           }
           }
           else
           {
           /*
           * Shrink
           */
           rtems_rfs_block_no blocks;
           uint32_t offset;
          
           blocks =
           rtems_rfs_block_map_count (  map ) -
           (  (  (  new_size - 1 ) /
           rtems_rfs_fs_block_size (  rtems_rfs_file_fs (  handle ) ) ) + 1 );
          
           offset =
           new_size % rtems_rfs_fs_block_size (  rtems_rfs_file_fs (  handle ) );
          
           if (  blocks )
           {
           int rc;
           rc = rtems_rfs_block_map_shrink (  rtems_rfs_file_fs (  handle ),  
           rtems_rfs_file_map (  handle ),  
           blocks );
           if (  rc > 0 )
           return rc;
           }
          
           rtems_rfs_block_map_set_size_offset (  map,   offset );
          
           if (  rtems_rfs_block_pos_past_end (  rtems_rfs_file_bpos (  handle ),  
           rtems_rfs_block_map_size (  map ) ) )
           rtems_rfs_block_size_get_bpos (  rtems_rfs_block_map_size (  map ),  
           rtems_rfs_file_bpos (  handle ) );
           }
           }
           }
          
           handle->shared->size.count = rtems_rfs_block_map_count (  map );
           handle->shared->size.offset = rtems_rfs_block_map_size_offset (  map );
          
           if (  rtems_rfs_file_update_mtime (  handle ) )
           handle->shared->mtime = time (  NULL );
          
           return 0;
          }
          
          rtems_rfs_file_shared*
     580  rtems_rfs_file_get_shared (  rtems_rfs_file_system* fs,  
           rtems_rfs_ino ino )
          {
           rtems_chain_node* node;
           node = rtems_chain_first (  &fs->file_shares );
           while (  !rtems_chain_is_tail (  &fs->file_shares,   node ) )
           {
           rtems_rfs_file_shared* shared;
           shared = (  rtems_rfs_file_shared* ) node;
           if (  shared->inode.ino == ino )
           return shared;
           node = rtems_chain_next (  node );
           }
           return NULL;
          }

libfs/src/rfs/rtems-rfs-format.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-format.c,  v 1.8 2010/10/11 04:34:48 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Format
           *
           * Format the file system ready for use.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          #include <stdio.h>
          #include <inttypes.h>
          
          #include <rtems/rfs/rtems-rfs-data.h>
          #include <rtems/rfs/rtems-rfs-file-system.h>
          #include <rtems/rfs/rtems-rfs-inode.h>
          #include <rtems/rtems-rfs-format.h>
          #include <rtems/rfs/rtems-rfs-dir.h>
          
          /**
           * Return the number of gigabytes.
           */
          #define GIGS(  _g ) (  (  (  uint64_t )(  _g ) ) * 1024 * 1024 )
          
          /**
           * Return the number of bits that fit in the block size.
           */
          static int
      43  rtems_rfs_bits_per_block (  rtems_rfs_file_system* fs )
          {
           return rtems_rfs_bitmap_numof_bits (  rtems_rfs_fs_block_size (  fs ) );
          }
          
          /**
           * Return a rounded up integer quotient given a dividend and divisor. That is:
           * "quotient = dividend / divisor"
           */
          int
      53  rtems_rfs_rup_quotient (  uint32_t dividend,   uint32_t divisor )
          {
           if (  dividend == 0 )
           return 1;
           return (  (  dividend - 1 ) / divisor ) + 1;
          }
          
          /**
           * Return the number of inodes as a percentage of the total number that can fit
           * in a blocl.
           */
          static int
      65  rtems_rfs_inodes_from_percent (  rtems_rfs_file_system* fs,  
           int percentage )
          {
           int blocks;
           blocks = (  (  rtems_rfs_fs_blocks (  fs ) -
           RTEMS_RFS_SUPERBLOCK_SIZE ) * percentage ) / 100;
           blocks = rtems_rfs_rup_quotient (  blocks,   fs->group_count );
           return blocks * (  rtems_rfs_fs_block_size (  fs ) / RTEMS_RFS_INODE_SIZE );
          }
          
          /**
           * Return the inode overhead given a number of inodes.
           */
          static int
      79  rtems_rfs_inode_overhead (  rtems_rfs_file_system* fs )
          {
           int blocks;
           int bits_per_block;
           blocks = rtems_rfs_rup_quotient(  fs->group_inodes * RTEMS_RFS_INODE_SIZE,  
           rtems_rfs_fs_block_size (  fs ) );
           bits_per_block = rtems_rfs_bits_per_block (  fs );
           /*
           * There could be more bits than blocks,   eg 512K disk with 512 blocks.
           */
           if (  bits_per_block > (  rtems_rfs_fs_blocks (  fs ) - RTEMS_RFS_SUPERBLOCK_SIZE ) )
           bits_per_block = rtems_rfs_fs_blocks (  fs ) - RTEMS_RFS_SUPERBLOCK_SIZE;
           return (  (  blocks + 1 ) * 100 * 10 ) / bits_per_block;
          }
          
          static bool
      95  rtems_rfs_check_config (  rtems_rfs_file_system* fs,  
           const rtems_rfs_format_config* config )
          {
           fs->block_size = config->block_size;
           if (  !fs->block_size )
           {
           uint64_t total_size = rtems_rfs_fs_media_size (  fs );
          
           if (  total_size >= GIGS (  1 ) )
           {
           uint32_t gigs = (  total_size + GIGS (  1 ) ) / GIGS (  1 );
           int b;
           for (  b = 31; b > 0; b-- )
           if (  (  gigs & (  1 << b ) ) != 0 )
           break;
           fs->block_size = 1 << b;
           }
          
           if (  fs->block_size < 512 )
           fs->block_size = 512;
          
           if (  fs->block_size > (  4 * 1024 ) )
           fs->block_size = (  4 * 1024 );
           }
          
           if (  (  fs->block_size % rtems_rfs_fs_media_block_size (  fs ) ) != 0 )
           {
           printf (  "block size (  %zd ) is not a multiple of media block size (  %" PRId32 " )\n",  
           fs->block_size,   rtems_rfs_fs_media_block_size (  fs ) );
           return false;
           }
          
           fs->group_blocks = config->group_blocks;
           if (  !fs->group_blocks )
           {
           /*
           * The number of blocks per group is defined by the number of bits in a
           * block.
           */
           fs->group_blocks = rtems_rfs_bitmap_numof_bits (  fs->block_size );
           }
          
           if (  fs->group_blocks > rtems_rfs_bitmap_numof_bits (  fs->block_size ) )
           {
           printf (  "group block count is higher than bits in block\n" );
           return false;
           }
          
           fs->blocks = rtems_rfs_fs_media_size (  fs ) / fs->block_size;
          
           /*
           * The bits per block sets the upper limit for the number of blocks in a
           * group. The disk will be divided into groups which are the number of bits
           * per block.
           */
           fs->group_count = rtems_rfs_rup_quotient (  rtems_rfs_fs_blocks (  fs ),  
           rtems_rfs_bits_per_block (  fs ) );
          
           fs->group_inodes = config->group_inodes;
           if (  !fs->group_inodes )
           {
           int inode_overhead = RTEMS_RFS_INODE_OVERHEAD_PERCENTAGE;
          
           /*
           * The number of inodes per group is set as a percentage.
           */
           if (  config->inode_overhead )
           inode_overhead = config->inode_overhead;
          
           fs->group_inodes = rtems_rfs_inodes_from_percent (  fs,   inode_overhead );
           }
          
           /*
           * Round up to fill a block because the minimum allocation unit is a block.
           */
           fs->inodes_per_block = rtems_rfs_fs_block_size (  fs ) / RTEMS_RFS_INODE_SIZE;
           fs->group_inodes =
           rtems_rfs_rup_quotient (  fs->group_inodes,  
           fs->inodes_per_block ) * fs->inodes_per_block;
          
           if (  fs->group_inodes > rtems_rfs_bitmap_numof_bits (  fs->block_size ) )
           fs->group_inodes = rtems_rfs_bitmap_numof_bits (  fs->block_size );
          
           fs->max_name_length = config->max_name_length;
           if (  !fs->max_name_length )
           {
           fs->max_name_length = 512;
           }
          
           return true;
          }
          
          static bool
     188  rtems_rfs_write_group (  rtems_rfs_file_system* fs,  
           int group,  
           bool initialise_inodes,  
           bool verbose )
          {
           rtems_rfs_buffer_handle handle;
           rtems_rfs_bitmap_control bitmap;
           rtems_rfs_buffer_block group_base;
           size_t group_size;
           int blocks;
           int b;
           int rc;
          
           group_base = rtems_rfs_fs_block (  fs,   group,   0 );
          
           if (  group_base > rtems_rfs_fs_blocks (  fs ) )
           {
           printf (  "rtems-rfs: write-group: group %d base beyond disk limit\n",  
           group );
           return false;
           }
          
           group_size = fs->group_blocks;
          
           /*
           * Be nice to strange sizes of disks. These are embedded systems after all
           * and nice numbers do not always work out. Let the last block pick up the
           * remainder of the blocks.
           */
           if (  (  group_base + group_size ) > rtems_rfs_fs_blocks (  fs ) )
           group_size = rtems_rfs_fs_blocks (  fs ) - group_base;
          
           if (  verbose )
           printf (  "\rrtems-rfs: format: group %3d: base = %" PRId32 ",   size = %zd",  
           group,   group_base,   group_size );
          
           /*
           * Open a handle and request an empty buffer.
           */
           rc = rtems_rfs_buffer_handle_open (  fs,   &handle );
           if (  rc > 0 )
           {
           printf (  "\nrtems-rfs: write-group: handle open failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           return false;
           }
          
           if (  verbose )
           printf (  ",   blocks" );
          
           /*
           * Open the block bitmap using the new buffer.
           */
           rc = rtems_rfs_bitmap_open (  &bitmap,   fs,   &handle,   group_size,  
           group_base + RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           printf (  "\nrtems-rfs: write-group: group %3d: open block bitmap failed: %d: %s\n",  
           group,   rc,   strerror (  rc ) );
           return false;
           }
          
           /*
           * Force the whole buffer to a known state. The bit map may not occupy the
           * whole block.
           */
           memset (  rtems_rfs_buffer_data (  &handle ),   0xff,   rtems_rfs_fs_block_size (  fs ) );
          
           /*
           * Clear the bitmap.
           */
           rc = rtems_rfs_bitmap_map_clear_all (  &bitmap );
           if (  rc > 0 )
           {
           rtems_rfs_bitmap_close (  &bitmap );
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           printf (  "\nrtems-rfs: write-group: group %3d: block bitmap clear all failed: %d: %s\n",  
           group,   rc,   strerror (  rc ) );
           return false;
           }
          
           /*
           * Forced allocation of the block bitmap.
           */
           rtems_rfs_bitmap_map_set (  &bitmap,   RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK );
          
           /*
           * Forced allocation of the inode bitmap.
           */
           rtems_rfs_bitmap_map_set (  &bitmap,   RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK );
          
           /*
           * Determine the number of inodes blocks in the group.
           */
           blocks = rtems_rfs_rup_quotient (  fs->group_inodes,   fs->inodes_per_block );
          
           /*
           * Forced allocation of the inode blocks which follow the block bitmap.
           */
           for (  b = 0; b < blocks; b++ )
           rtems_rfs_bitmap_map_set (  &bitmap,   b + RTEMS_RFS_GROUP_INODE_BLOCK );
          
           /*
           * Close the block bitmap.
           */
           rc = rtems_rfs_bitmap_close (  &bitmap );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           printf (  "\nrtems-rfs: write-group: group %3d: close block bitmap failed: %d: %s\n",  
           group,   rc,   strerror (  rc ) );
           return false;
           }
          
           rtems_rfs_buffer_mark_dirty (  &handle );
          
           if (  verbose )
           printf (  ",   inodes" );
          
           /*
           * Open the inode bitmap using the old buffer. Should release any changes.
           */
           rc = rtems_rfs_bitmap_open (  &bitmap,   fs,   &handle,   group_size,  
           group_base + RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           printf (  "\nrtems-rfs: write-group: group %3d: open inode bitmap failed: %d: %s\n",  
           group,   rc,   strerror (  rc ) );
           return false;
           }
          
           /*
           * Force the whole buffer to a known state. The bit map may not occupy the
           * whole block.
           */
           memset (  rtems_rfs_buffer_data (  &handle ),   0x00,   rtems_rfs_fs_block_size (  fs ) );
          
           /*
           * Clear the inode bitmap.
           */
           rc = rtems_rfs_bitmap_map_clear_all (  &bitmap );
           if (  rc > 0 )
           {
           rtems_rfs_bitmap_close (  &bitmap );
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           printf (  "\nrtems-rfs: write-group: group %3d: inode bitmap" \
           " clear all failed: %d: %s\n",   group,   rc,   strerror (  rc ) );
           return false;
           }
          
           /*
           * Close the inode bitmap.
           */
           rc = rtems_rfs_bitmap_close (  &bitmap );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           printf (  "\nrtems-rfs: write-group: group %3d: close inode" \
           " bitmap failed: %d: %s\n",   group,   rc,   strerror (  rc ) );
           return false;
           }
          
           rtems_rfs_buffer_mark_dirty (  &handle );
          
           /*
           * Initialise the inode tables if required to do so.
           */
           if (  initialise_inodes )
           {
           for (  b = 0; b < blocks; b++ )
           {
           rc = rtems_rfs_buffer_handle_request (  fs,   &handle,  
           group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,  
           false );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           printf (  "\nrtems-rfs: write-group: group %3d: block %" PRId32 " request failed: %d: %s\n",  
           group,   group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,  
           rc,   strerror (  rc ) );
           return false;
           }
          
           /*
           * Force the whole buffer to a known state. The bit map may not occupy the
           * whole block.
           */
           memset (  rtems_rfs_buffer_data (  &handle ),   0xff,   rtems_rfs_fs_block_size (  fs ) );
          
           rtems_rfs_buffer_mark_dirty (  &handle );
           }
           }
          
           rc = rtems_rfs_buffer_handle_close (  fs,   &handle );
           if (  rc > 0 )
           {
           printf (  "\nrtems-rfs: write-group: buffer handle close failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           return false;
           }
          
           return true;
          }
          
          static bool
     395  rtems_rfs_write_superblock (  rtems_rfs_file_system* fs )
          {
           rtems_rfs_buffer_handle handle;
           uint8_t* sb;
           int rc;
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &handle );
           if (  rc > 0 )
           {
           printf (  "rtems-rfs: write-superblock: handle open failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           return false;
           }
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &handle,   0,   false );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           printf (  "rtems-rfs: write-superblock: request failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           return false;
           }
          
           sb = rtems_rfs_buffer_data (  &handle );
          
          #define write_sb(  _o,   _d ) rtems_rfs_write_u32(  sb + (  _o ),   _d )
          
           memset (  sb,   0xff,   rtems_rfs_fs_block_size (  fs ) );
          
           write_sb (  RTEMS_RFS_SB_OFFSET_MAGIC,   RTEMS_RFS_SB_MAGIC );
           write_sb (  RTEMS_RFS_SB_OFFSET_VERSION,   RTEMS_RFS_VERSION );
           write_sb (  RTEMS_RFS_SB_OFFSET_BLOCKS,   rtems_rfs_fs_blocks (  fs ) );
           write_sb (  RTEMS_RFS_SB_OFFSET_BLOCK_SIZE,   rtems_rfs_fs_block_size (  fs ) );
           write_sb (  RTEMS_RFS_SB_OFFSET_BAD_BLOCKS,   fs->bad_blocks );
           write_sb (  RTEMS_RFS_SB_OFFSET_MAX_NAME_LENGTH,   fs->max_name_length );
           write_sb (  RTEMS_RFS_SB_OFFSET_GROUPS,   fs->group_count );
           write_sb (  RTEMS_RFS_SB_OFFSET_GROUP_BLOCKS,   fs->group_blocks );
           write_sb (  RTEMS_RFS_SB_OFFSET_GROUP_INODES,   fs->group_inodes );
           write_sb (  RTEMS_RFS_SB_OFFSET_INODE_SIZE,   RTEMS_RFS_INODE_SIZE );
          
           rtems_rfs_buffer_mark_dirty (  &handle );
          
           rc = rtems_rfs_buffer_handle_release (  fs,   &handle );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &handle );
           printf (  "rtems-rfs: write-superblock: buffer release failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           return false;
           }
          
           rc = rtems_rfs_buffer_handle_close (  fs,   &handle );
           if (  rc > 0 )
           {
           printf (  "rtems-rfs: write-superblock: buffer handle close failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           return false;
           }
          
           return true;
          }
          
          static int
     458  rtems_rfs_write_root_dir (  const char* name )
          {
           rtems_rfs_file_system* fs;
           rtems_rfs_inode_handle inode;
           rtems_rfs_ino ino;
           int rc;
          
           /*
           * External API so returns -1.
           */
           rc = rtems_rfs_fs_open (  name,   NULL,   RTEMS_RFS_FS_FORCE_OPEN,   &fs );
           if (  rc < 0 )
           {
           printf (  "rtems-rfs: format: file system open failed: %d: %s\n",  
           errno,   strerror (  errno ) );
           return -1;
           }
          
           rc = rtems_rfs_inode_alloc (  fs,   RTEMS_RFS_ROOT_INO,   &ino );
           if (  rc > 0 )
           {
           printf (  "rtems-rfs: format: inode allocation failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           rtems_rfs_fs_close (  fs );
           return rc;
           }
          
           if (  ino != RTEMS_RFS_ROOT_INO )
           {
           printf (  "rtems-rfs: format: allocated inode not root ino: %" PRId32 "\n",   ino );
           rtems_rfs_fs_close (  fs );
           return rc;
           }
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc > 0 )
           {
           printf (  "rtems-rfs: format: inode open failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           rtems_rfs_group_bitmap_free (  fs,   true,   ino );
           rtems_rfs_fs_close (  fs );
           return rc;
           }
          
           rc = rtems_rfs_inode_initialise (  &inode,   0,  
           (  RTEMS_RFS_S_IFDIR | RTEMS_RFS_S_IRWXU |
           RTEMS_RFS_S_IXGRP | RTEMS_RFS_S_IXOTH ),  
           0,   0 );
           if (  rc > 0 )
           printf (  "rtems-rfs: format: inode initialise failed: %d: %s\n",  
           rc,   strerror (  rc ) );
          
           rc = rtems_rfs_dir_add_entry (  fs,   &inode,   ".",   1,   ino );
           if (  rc > 0 )
           printf (  "rtems-rfs: format: directory add failed: %d: %s\n",  
           rc,   strerror (  rc ) );
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc > 0 )
           printf (  "rtems-rfs: format: inode close failed: %d: %s\n",  
           rc,   strerror (  rc ) );
          
           rc = rtems_rfs_fs_close (  fs );
           if (  rc < 0 )
           printf (  "rtems-rfs: format: file system close failed: %d: %s\n",  
           errno,   strerror (  errno ) );
          
           return rc;
          }
          
          int
     529  rtems_rfs_format (  const char* name,   const rtems_rfs_format_config* config )
          {
           rtems_rfs_file_system fs;
           int group;
           int rc;
          
           if (  config->verbose )
           printf (  "rtems-rfs: format: %s\n",   name );
          
           memset (  &fs,   0,   sizeof (  rtems_rfs_file_system ) );
          
           rtems_chain_initialize_empty (  &fs.buffers );
           rtems_chain_initialize_empty (  &fs.release );
           rtems_chain_initialize_empty (  &fs.release_modified );
           rtems_chain_initialize_empty (  &fs.file_shares );
          
           fs.max_held_buffers = RTEMS_RFS_FS_MAX_HELD_BUFFERS;
          
           fs.release_count = 0;
           fs.release_modified_count = 0;
          
           fs.flags = RTEMS_RFS_FS_NO_LOCAL_CACHE;
          
           /*
           * Open the buffer interface.
           */
           rc = rtems_rfs_buffer_open (  name,   &fs );
           if (  rc > 0 )
           {
           printf (  "rtems-rfs: format: buffer open failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           return -1;
           }
          
           /*
           * Check the media.
           */
           if (  rtems_rfs_fs_media_block_size (  &fs ) == 0 )
           {
           printf (  "rtems-rfs: media block is invalid: %" PRIu32 "\n",  
           rtems_rfs_fs_media_block_size (  &fs ) );
           return -1;
           }
          
           /*
           * Check the configuration data.
           */
           if (  !rtems_rfs_check_config (  &fs,   config ) )
           return -1;
          
           if (  config->verbose )
           {
           printf (  "rtems-rfs: format: media size = %" PRIu64 "\n",  
           rtems_rfs_fs_media_size (  &fs ) );
           printf (  "rtems-rfs: format: media blocks = %" PRIu32 "\n",  
           rtems_rfs_fs_media_blocks (  &fs ) );
           printf (  "rtems-rfs: format: media block size = %" PRIu32 "\n",  
           rtems_rfs_fs_media_block_size (  &fs ) );
           printf (  "rtems-rfs: format: size = %" PRIu64 "\n",  
           rtems_rfs_fs_size (  &fs ) );
           printf (  "rtems-rfs: format: blocks = %zu\n",  
           rtems_rfs_fs_blocks (  &fs ) );
           printf (  "rtems-rfs: format: block size = %zu\n",  
           rtems_rfs_fs_block_size (  &fs ) );
           printf (  "rtems-rfs: format: bits per block = %u\n",  
           rtems_rfs_bits_per_block (  &fs ) );
           printf (  "rtems-rfs: format: inode size = %zu\n",   RTEMS_RFS_INODE_SIZE );
           printf (  "rtems-rfs: format: inodes = %zu (  %d.%d%% )\n",  
           fs.group_inodes * fs.group_count,  
           rtems_rfs_inode_overhead (  &fs ) / 10,  
           rtems_rfs_inode_overhead (  &fs ) % 10 );
           printf (  "rtems-rfs: format: groups = %u\n",   fs.group_count );
           printf (  "rtems-rfs: format: group blocks = %zu\n",   fs.group_blocks );
           printf (  "rtems-rfs: format: group inodes = %zu\n",   fs.group_inodes );
           }
          
           rc = rtems_rfs_buffer_setblksize (  &fs,   rtems_rfs_fs_block_size (  &fs ) );
           if (  rc > 0 )
           {
           printf (  "rtems-rfs: format: setting block size failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           return -1;
           }
          
           if (  !rtems_rfs_write_superblock (  &fs ) )
           {
           printf (  "rtems-rfs: format: superblock write failed\n" );
           return -1;
           }
          
           for (  group = 0; group < fs.group_count; group++ )
           if (  !rtems_rfs_write_group (  &fs,   group,  
           config->initialise_inodes,   config->verbose ) )
           return -1;
          
           if (  config->verbose )
           printf (  "\n" );
          
           rc = rtems_rfs_buffer_close (  &fs );
           if (  rc > 0 )
           {
           printf (  "rtems-rfs: format: buffer close failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           return -1;
           }
          
           rc = rtems_rfs_write_root_dir (  name );
           if (  rc > 0 )
           {
           printf (  "rtems-rfs: format: writing root dir failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           return -1;
           }
          
           return 0;
          }

libfs/src/rfs/rtems-rfs-group.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-group.c,  v 1.6 2010/10/11 04:34:48 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Group Routines.
           *
           * These functions open and close a group as well as manage bit allocations
           * within a group.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <rtems/rfs/rtems-rfs-file-system.h>
          #include <rtems/rfs/rtems-rfs-group.h>
          
          int
      31  rtems_rfs_group_open (  rtems_rfs_file_system* fs,  
           rtems_rfs_buffer_block base,  
           size_t size,  
           size_t inodes,  
           rtems_rfs_group* group )
          {
           int rc;
          
           if (  base >= rtems_rfs_fs_blocks (  fs ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_GROUP_OPEN ) )
           printf (  "rtems-rfs: group-open: base outside file system range: %d: %s\n",  
           EIO,   strerror (  EIO ) );
           return EIO;
           }
          
           if (  (  base + size ) >= rtems_rfs_fs_blocks (  fs ) )
           size = rtems_rfs_fs_blocks (  fs ) - base;
          
           /*
           * Limit the inodes to the same size as the blocks. This is what the
           * format does and if this is not done the accounting of inodes does
           * not work. If we are so pushed for inodes that this makes a difference
           * the format configuration needs reviewing.
           */
           if (  inodes > size )
           inodes = size;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_GROUP_OPEN ) )
           printf (  "rtems-rfs: group-open: base=%" PRId32 ",   blocks=%zd inodes=%zd\n",  
           base,   size,   inodes );
          
           group->base = base;
           group->size = size;
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &group->block_bitmap_buffer );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_GROUP_OPEN ) )
           printf (  "rtems-rfs: group-open: could not open block bitmap handle: %d: %s\n",  
           rc,   strerror (  rc ) );
           return rc;
           }
          
           rc = rtems_rfs_bitmap_open (  &group->block_bitmap,   fs,  
           &group->block_bitmap_buffer,   size,  
           group->base + RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &group->block_bitmap_buffer );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_GROUP_OPEN ) )
           printf (  "rtems-rfs: group-open: could not open block bitmap: %d: %s\n",  
           rc,   strerror (  rc ) );
           return rc;
           }
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &group->inode_bitmap_buffer );
           if (  rc > 0 )
           {
           rtems_rfs_bitmap_close (  &group->block_bitmap );
           rtems_rfs_buffer_handle_close (  fs,   &group->block_bitmap_buffer );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_GROUP_OPEN ) )
           printf (  "rtems-rfs: group-open: could not open inode bitmap handle: %d: %s\n",  
           rc,   strerror (  rc ) );
           return rc;
           }
          
           rc = rtems_rfs_bitmap_open (  &group->inode_bitmap,   fs,  
           &group->inode_bitmap_buffer,   inodes,  
           group->base + RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &group->inode_bitmap_buffer );
           rtems_rfs_bitmap_close (  &group->block_bitmap );
           rtems_rfs_buffer_handle_close (  fs,   &group->block_bitmap_buffer );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_GROUP_OPEN ) )
           printf (  "rtems-rfs: group-open: could not open inode bitmap: %d: %s\n",  
           rc,   strerror (  rc ) );
           return rc;
           }
          
           if (  rtems_rfs_fs_release_bitmaps (  fs ) )
           {
           rtems_rfs_bitmap_release_buffer (  fs,   &group->block_bitmap );
           rtems_rfs_bitmap_release_buffer (  fs,   &group->inode_bitmap );
           }
          
           return 0;
          }
          
          int
     122  rtems_rfs_group_close (  rtems_rfs_file_system* fs,   rtems_rfs_group* group )
          {
           int result = 0;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_GROUP_CLOSE ) )
           printf (  "rtems-rfs: group-close: base=%" PRId32 "\n",   group->base );
          
           /*
           * We need to close as much as possible and also return any error if one
           * occurs but this may result in one even more important error being lost but
           * we cannot OR the errors together so this is a reasonable compromise.
           */
           rc = rtems_rfs_bitmap_close (  &group->inode_bitmap );
           if (  rc > 0 )
           result = rc;
           rc = rtems_rfs_buffer_handle_close (  fs,   &group->inode_bitmap_buffer );
           if (  rc > 0 )
           result = rc;
           rc = rtems_rfs_bitmap_close (  &group->block_bitmap );
           if (  rc > 0 )
           result = rc;
           rc = rtems_rfs_buffer_handle_close (  fs,   &group->block_bitmap_buffer );
           if (  rc > 0 )
           result = rc;
          
           return result;
          }
          
          int
     152  rtems_rfs_group_bitmap_alloc (  rtems_rfs_file_system* fs,  
           rtems_rfs_bitmap_bit goal,  
           bool inode,  
           rtems_rfs_bitmap_bit* result )
          {
           int group_start;
           size_t size;
           rtems_rfs_bitmap_bit bit;
           int offset;
           bool updown;
           int direction;
          
           if (  inode )
           {
           size = fs->group_inodes;
           goal -= RTEMS_RFS_ROOT_INO;
           }
           else
           size = fs->group_blocks;
          
           group_start = goal / size;
           bit = (  rtems_rfs_bitmap_bit ) (  goal % size );
           offset = 0;
           updown = true;
           direction = 1;
          
           /*
           * Try the goal group first and if that group fails try the groups either
           * side until the whole file system has be tried.
           */
           while (  true )
           {
           rtems_rfs_bitmap_control* bitmap;
           int group;
           bool allocated = false;
           int rc;
          
           /*
           * We can start at any location and we move out from that point in each
           * direction. The offset grows until we find a free bit or we hit an end.
           */
           group = group_start + (  direction * offset );
           if (  offset )
           bit = direction > 0 ? 0 : size - 1;
          
           /*
           * If we are still looking up and down and if the group is out of range we
           * have reached one end. Stopping looking up and down and just move in the
           * one direction one group at a time.
           */
           if (  (  group < 0 ) || (  group >= fs->group_count ) )
           {
           if (  !updown )
           break;
           direction = direction > 0 ? -1 : 1;
           updown = false;
           continue;
           }
          
           if (  inode )
           bitmap = &fs->groups[group].inode_bitmap;
           else
           bitmap = &fs->groups[group].block_bitmap;
          
           rc = rtems_rfs_bitmap_map_alloc (  bitmap,   bit,   &allocated,   &bit );
           if (  rc > 0 )
           return rc;
          
           if (  rtems_rfs_fs_release_bitmaps (  fs ) )
           rtems_rfs_bitmap_release_buffer (  fs,   bitmap );
          
           if (  allocated )
           {
           if (  inode )
           *result = rtems_rfs_group_inode (  fs,   group,   bit );
           else
           *result = rtems_rfs_group_block (  &fs->groups[group],   bit );
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_GROUP_BITMAPS ) )
           printf (  "rtems-rfs: group-bitmap-alloc: %s allocated: %" PRId32 "\n",  
           inode ? "inode" : "block",   *result );
           return 0;
           }
          
           if (  updown )
           direction = direction > 0 ? -1 : 1;
          
           offset++;
           }
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_GROUP_BITMAPS ) )
           printf (  "rtems-rfs: group-bitmap-alloc: no blocks available\n" );
          
           return ENOSPC;
          }
          
          int
     248  rtems_rfs_group_bitmap_free (  rtems_rfs_file_system* fs,  
           bool inode,  
           rtems_rfs_bitmap_bit no )
          {
           rtems_rfs_bitmap_control* bitmap;
           unsigned int group;
           rtems_rfs_bitmap_bit bit;
           size_t size;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_GROUP_BITMAPS ) )
           printf (  "rtems-rfs: group-bitmap-free: %s free: %" PRId32 "\n",  
           inode ? "inode" : "block",   no );
          
           if (  inode )
           {
           no -= RTEMS_RFS_ROOT_INO;
           size = fs->group_inodes;
           }
           else
           {
           no -= RTEMS_RFS_SUPERBLOCK_SIZE;
           size = fs->group_blocks;
           }
          
           group = no / size;
           bit = (  rtems_rfs_bitmap_bit ) (  no % size );
          
           if (  inode )
           bitmap = &fs->groups[group].inode_bitmap;
           else
           bitmap = &fs->groups[group].block_bitmap;
          
           rc = rtems_rfs_bitmap_map_clear (  bitmap,   bit );
          
           rtems_rfs_bitmap_release_buffer (  fs,   bitmap );
          
           return rc;
          }
          
          int
     289  rtems_rfs_group_bitmap_test (  rtems_rfs_file_system* fs,  
           bool inode,  
           rtems_rfs_bitmap_bit no,  
           bool* state )
          {
           rtems_rfs_bitmap_control* bitmap;
           unsigned int group;
           rtems_rfs_bitmap_bit bit;
           size_t size;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_GROUP_BITMAPS ) )
           printf (  "rtems-rfs: group-bitmap-test: %s test: %" PRId32 "\n",  
           inode ? "inode" : "block",   no );
          
           if (  inode )
           {
           if (  (  no < RTEMS_RFS_ROOT_INO ) || (  no > rtems_rfs_fs_inodes (  fs ) ) )
           return EINVAL;
           no -= RTEMS_RFS_ROOT_INO;
           size = fs->group_inodes;
           }
           else
           {
           if (  no >= rtems_rfs_fs_blocks (  fs ) )
           return EINVAL;
           size = fs->group_blocks;
           }
          
           group = no / size;
           bit = (  rtems_rfs_bitmap_bit ) (  no % size );
          
           if (  inode )
           bitmap = &fs->groups[group].inode_bitmap;
           else
           bitmap = &fs->groups[group].block_bitmap;
          
           rc = rtems_rfs_bitmap_map_test (  bitmap,   bit,   state );
          
           rtems_rfs_bitmap_release_buffer (  fs,   bitmap );
          
           return rc;
          }
          
          int
     334  rtems_rfs_group_usage (  rtems_rfs_file_system* fs,  
           size_t* blocks,  
           size_t* inodes )
          {
           int g;
          
           *blocks = 0;
           *inodes = 0;
          
           for (  g = 0; g < fs->group_count; g++ )
           {
           rtems_rfs_group* group = &fs->groups[g];
           *blocks +=
           rtems_rfs_bitmap_map_size(  &group->block_bitmap ) -
           rtems_rfs_bitmap_map_free (  &group->block_bitmap );
           *inodes +=
           rtems_rfs_bitmap_map_size (  &group->inode_bitmap ) -
           rtems_rfs_bitmap_map_free (  &group->inode_bitmap );
           }
          
           if (  *blocks > rtems_rfs_fs_blocks (  fs ) )
           *blocks = rtems_rfs_fs_blocks (  fs );
           if (  *inodes > rtems_rfs_fs_inodes (  fs ) )
           *inodes = rtems_rfs_fs_inodes (  fs );
          
           return 0;
          }
          

libfs/src/rfs/rtems-rfs-inode.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-inode.c,  v 1.5 2010/10/11 04:34:48 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Inode Routines.
           *
           * These functions manage inodes in the RFS file system. An inode is part of a
           * block that reside after the bitmaps in the group.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <rtems/rfs/rtems-rfs-block.h>
          #include <rtems/rfs/rtems-rfs-file-system.h>
          #include <rtems/rfs/rtems-rfs-inode.h>
          #include <rtems/rfs/rtems-rfs-dir.h>
          
          int
      33  rtems_rfs_inode_alloc (  rtems_rfs_file_system* fs,  
           rtems_rfs_bitmap_bit goal,  
           rtems_rfs_ino* ino )
          {
           rtems_rfs_bitmap_bit bit;
           int rc;
           rc = rtems_rfs_group_bitmap_alloc (  fs,   goal,   true,   &bit );
           *ino = bit;
           return rc;
          }
          
          int
      45  rtems_rfs_inode_free (  rtems_rfs_file_system* fs,  
           rtems_rfs_ino ino )
          {
           rtems_rfs_bitmap_bit bit;
           bit = ino;
           return rtems_rfs_group_bitmap_free (  fs,   true,   bit );
          }
          
          int
      54  rtems_rfs_inode_open (  rtems_rfs_file_system* fs,  
           rtems_rfs_ino ino,  
           rtems_rfs_inode_handle* handle,  
           bool load )
          {
           int group;
           int gino;
           int index;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_INODE_OPEN ) )
           printf (  "rtems-rfs: inode-open: ino: %" PRIu32 "\n",   ino );
          
           if (  ino == RTEMS_RFS_EMPTY_INO )
           return EINVAL;
          
           if (  (  ino - RTEMS_RFS_ROOT_INO ) > rtems_rfs_fs_inodes (  fs ) )
           return EINVAL;
          
           handle->ino = ino;
           handle->node = NULL;
           handle->loads = 0;
          
           gino = ino - RTEMS_RFS_ROOT_INO;
           group = gino / fs->group_inodes;
           gino = gino % fs->group_inodes;
           index = (  gino / fs->inodes_per_block ) + RTEMS_RFS_GROUP_INODE_BLOCK;
          
           handle->offset = gino % fs->inodes_per_block;
           handle->block = rtems_rfs_group_block (  &fs->groups[group],   index );
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &handle->buffer );
           if (  (  rc == 0 ) && load )
           rc = rtems_rfs_inode_load (  fs,   handle );
           return rc;
          }
          
          int
      92  rtems_rfs_inode_close (  rtems_rfs_file_system* fs,  
           rtems_rfs_inode_handle* handle )
          {
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_INODE_CLOSE ) )
           printf (  "rtems-rfs: inode-close: ino: %" PRIu32 "\n",   handle->ino );
          
           rc = rtems_rfs_inode_unload (  fs,   handle,   true );
          
           if (  (  rc == 0 ) && (  handle->loads > 0 ) )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_INODE_CLOSE ) )
           printf (  "rtems-rfs: inode-close: bad loads number: %d\n",  
           handle->loads );
           rc = EIO;
           }
          
           handle->ino = 0;
           return rc;
          }
          
          int
     115  rtems_rfs_inode_load (  rtems_rfs_file_system* fs,  
           rtems_rfs_inode_handle* handle )
          {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_INODE_LOAD ) )
           printf (  "rtems-rfs: inode-load: ino=%" PRIu32 " loads=%i loaded=%s\n",  
           handle->ino,   handle->loads,  
           rtems_rfs_inode_is_loaded (  handle ) ? "yes" : "no" );
          
           /*
           * An inode does not move so once loaded no need to do again.
           */
          
           if (  !rtems_rfs_inode_is_loaded (  handle ) )
           {
           int rc;
          
           rc = rtems_rfs_buffer_handle_request (  fs,  &handle->buffer,  
           handle->block,   true );
           if (  rc > 0 )
           return rc;
          
           handle->node = rtems_rfs_buffer_data (  &handle->buffer );
           handle->node += handle->offset;
           }
          
           handle->loads++;
          
           return 0;
          }
          
          int
     146  rtems_rfs_inode_unload (  rtems_rfs_file_system* fs,  
           rtems_rfs_inode_handle* handle,  
           bool update_ctime )
          {
           int rc = 0;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_INODE_UNLOAD ) )
           printf (  "rtems-rfs: inode-unload: ino=%" PRIu32 " loads=%i loaded=%s\n",  
           handle->ino,   handle->loads,  
           rtems_rfs_inode_is_loaded (  handle ) ? "yes" : "no" );
          
           if (  rtems_rfs_inode_is_loaded (  handle ) )
           {
           if (  handle->loads == 0 )
           return EIO;
          
           handle->loads--;
          
           if (  handle->loads == 0 )
           {
           /*
           * If the buffer is dirty it will be release. Also set the ctime.
           */
           if (  rtems_rfs_buffer_dirty (  &handle->buffer ) && update_ctime )
           rtems_rfs_inode_set_ctime (  handle,   time (  NULL ) );
           rc = rtems_rfs_buffer_handle_release (  fs,   &handle->buffer );
           handle->node = NULL;
           }
           }
          
           return rc;
          }
          
          int
     180  rtems_rfs_inode_create (  rtems_rfs_file_system* fs,  
           rtems_rfs_ino parent,  
           const char* name,  
           size_t length,  
           uint16_t mode,  
           uint16_t links,  
           uid_t uid,  
           gid_t gid,  
           rtems_rfs_ino* ino )
          {
           rtems_rfs_inode_handle parent_inode;
           rtems_rfs_inode_handle inode;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_INODE_CREATE ) )
           {
           const char* type = "unknown";
           int c;
           if (  RTEMS_RFS_S_ISDIR (  mode ) )
           type = "dir";
           else if (  RTEMS_RFS_S_ISCHR (  mode ) )
           type = "char";
           else if (  RTEMS_RFS_S_ISBLK (  mode ) )
           type = "block";
           else if (  RTEMS_RFS_S_ISREG (  mode ) )
           type = "file";
           else if (  RTEMS_RFS_S_ISLNK (  mode ) )
           type = "link";
           printf(  "rtems-rfs: inode-create: parent:%" PRIu32 " name:",   parent );
           for (  c = 0; c < length; c++ )
           printf (  "%c",   name[c] );
           printf (  " type:%s mode:%04x (  %03o )\n",   type,   mode,   mode & (  (  1 << 10 ) - 1 ) );
           }
          
           rc = rtems_rfs_inode_alloc (  fs,   parent,   ino );
           if (  rc > 0 )
           return rc;
          
           rc = rtems_rfs_inode_open (  fs,   *ino,   &inode,   true );
           if (  rc > 0 )
           {
           rtems_rfs_inode_free (  fs,   *ino );
           return rc;
           }
          
           rc = rtems_rfs_inode_initialise (  &inode,   links,   mode,   uid,   gid );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_inode_free (  fs,   *ino );
           return rc;
           }
          
           /*
           * Only handle the specifics of a directory. Let caller handle the others.
           *
           * The inode delete will free the inode.
           */
           if (  RTEMS_RFS_S_ISDIR (  mode ) )
           {
           rc = rtems_rfs_dir_add_entry (  fs,   &inode,   ".",   1,   *ino );
           if (  rc == 0 )
           rc = rtems_rfs_dir_add_entry (  fs,   &inode,   "..",   2,   parent );
           if (  rc > 0 )
           {
           rtems_rfs_inode_delete (  fs,   &inode );
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
           }
          
           rc = rtems_rfs_inode_open (  fs,   parent,   &parent_inode,   true );
           if (  rc > 0 )
           {
           rtems_rfs_inode_delete (  fs,   &inode );
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           rc = rtems_rfs_dir_add_entry (  fs,   &parent_inode,   name,   length,   *ino );
           if (  rc > 0 )
           {
           rtems_rfs_inode_delete (  fs,   &inode );
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_inode_close (  fs,   &parent_inode );
           return rc;
           }
          
           /*
           * If the node is a directory update the parent link count as the
           * new directory has the '..' link that points to the parent.
           */
           if (  RTEMS_RFS_S_ISDIR (  mode ) )
           rtems_rfs_inode_set_links (  &parent_inode,  
           rtems_rfs_inode_get_links (  &parent_inode ) + 1 );
          
           rc = rtems_rfs_inode_close (  fs,   &parent_inode );
           if (  rc > 0 )
           {
           rtems_rfs_inode_delete (  fs,   &inode );
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc > 0 )
           {
           rtems_rfs_inode_free (  fs,   *ino );
           return rc;
           }
          
           return 0;
          }
          
          int
     295  rtems_rfs_inode_delete (  rtems_rfs_file_system* fs,  
           rtems_rfs_inode_handle* handle )
          {
           int rc = 0;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_INODE_DELETE ) )
           printf(  "rtems-rfs: inode-delete: ino:%" PRIu32 " loaded:%s\n",  
           rtems_rfs_inode_ino (  handle ),  
           rtems_rfs_inode_is_loaded (  handle ) ? "yes" : "no" );
          
           if (  rtems_rfs_inode_is_loaded (  handle ) )
           {
           rtems_rfs_block_map map;
          
           /*
           * Free the ino number.
           */
           rc = rtems_rfs_inode_free (  fs,   handle->ino );
           if (  rc > 0 )
           return rc;
          
           /*
           * Free the blocks the inode may have attached.
           */
           rc = rtems_rfs_block_map_open (  fs,   handle,   &map );
           if (  rc == 0 )
           {
           int rrc;
           rrc = rtems_rfs_block_map_free_all (  fs,   &map );
           rc = rtems_rfs_block_map_close (  fs,   &map );
           if (  rc > 0 )
           rrc = rc;
           memset (  handle->node,   0xff,   RTEMS_RFS_INODE_SIZE );
           rtems_rfs_buffer_mark_dirty (  &handle->buffer );
           /*
           * Do the release here to avoid the ctime field being set on a
           * close. Also if there loads is greater then one then other loads
           * active. Forcing the loads count to 0.
           */
           rc = rtems_rfs_buffer_handle_release (  fs,   &handle->buffer );
           handle->loads = 0;
           handle->node = NULL;
           }
           }
           return rc;
          }
          
          int
     343  rtems_rfs_inode_initialise (  rtems_rfs_inode_handle* handle,  
           uint16_t links,  
           uint16_t mode,  
           uid_t uid,  
           gid_t gid )
          {
           int b;
           rtems_rfs_inode_set_links (  handle,   links );
           rtems_rfs_inode_set_flags (  handle,   0 );
           rtems_rfs_inode_set_mode (  handle,   mode );
           rtems_rfs_inode_set_uid_gid (  handle,   uid,   gid );
           rtems_rfs_inode_set_block_offset (  handle,   0 );
           rtems_rfs_inode_set_block_count (  handle,   0 );
           for (  b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++ )
           rtems_rfs_inode_set_block (  handle,   b,   0 );
           rtems_rfs_inode_set_last_map_block (  handle,   0 );
           rtems_rfs_inode_set_last_data_block (  handle,   0 );
           return rtems_rfs_inode_time_stamp_now (  handle,   true,   true );
          }
          
          int
     364  rtems_rfs_inode_time_stamp_now (  rtems_rfs_inode_handle* handle,  
           bool atime,  
           bool mtime )
          {
           time_t now;
           if (  !rtems_rfs_inode_is_loaded (  handle ) )
           return ENXIO;
           now = time (  NULL );
           if (  atime )
           rtems_rfs_inode_set_atime (  handle,   now );
           if (  mtime )
           rtems_rfs_inode_set_mtime (  handle,   now );
           return 0;
          }
          
          rtems_rfs_pos
     380  rtems_rfs_inode_get_size (  rtems_rfs_file_system* fs,  
           rtems_rfs_inode_handle* handle )
          {
           rtems_rfs_block_size size;
           size.count = rtems_rfs_inode_get_block_count (  handle );
           size.offset = rtems_rfs_inode_get_block_offset (  handle );
           return rtems_rfs_block_get_size (  fs,   &size );
          }

libfs/src/rfs/rtems-rfs-link.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-link.c,  v 1.4 2010/06/15 23:34:56 ralf Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Link Routines.
           *
           * These functions manage links. A link is the addition of a directory entry in
           * a parent directory and incrementing the links count in the inode.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <rtems/rfs/rtems-rfs-block.h>
          #include <rtems/rfs/rtems-rfs-buffer.h>
          #include <rtems/rfs/rtems-rfs-file-system.h>
          #include <rtems/rfs/rtems-rfs-trace.h>
          #include <rtems/rfs/rtems-rfs-dir.h>
          #include <rtems/rfs/rtems-rfs-dir-hash.h>
          #include <rtems/rfs/rtems-rfs-link.h>
          
          int
      36  rtems_rfs_link (  rtems_rfs_file_system* fs,  
           const char* name,  
           int length,  
           rtems_rfs_ino parent,  
           rtems_rfs_ino target,  
           bool link_dir )
          {
           rtems_rfs_inode_handle parent_inode;
           rtems_rfs_inode_handle target_inode;
           uint16_t links;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_LINK ) )
           {
           int c;
           printf (  "rtems-rfs: link: parent(  %" PRIu32 " ) -> ",   parent );
           for (  c = 0; c < length; c++ )
           printf (  "%c",   name[c] );
           printf (  "(  %" PRIu32 " )\n",   target );
           }
          
           rc = rtems_rfs_inode_open (  fs,   target,   &target_inode,   true );
           if (  rc )
           return rc;
          
           /*
           * If the target inode is a directory and we cannot link directories
           * return a not supported error code.
           */
           if (  !link_dir && S_ISDIR (  rtems_rfs_inode_get_mode (  &target_inode ) ) )
           {
           rtems_rfs_inode_close (  fs,   &target_inode );
           return ENOTSUP;
           }
          
           rc = rtems_rfs_inode_open (  fs,   parent,   &parent_inode,   true );
           if (  rc )
           {
           rtems_rfs_inode_close (  fs,   &target_inode );
           return rc;
           }
          
           rc = rtems_rfs_dir_add_entry (  fs,   &parent_inode,   name,   length,   target );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &parent_inode );
           rtems_rfs_inode_close (  fs,   &target_inode );
           return rc;
           }
          
           links = rtems_rfs_inode_get_links (  &target_inode ) + 1;
           rtems_rfs_inode_set_links (  &target_inode,   links );
          
           rc = rtems_rfs_inode_time_stamp_now (  &parent_inode,   true,   true );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &parent_inode );
           rtems_rfs_inode_close (  fs,   &target_inode );
           return rc;
           }
          
           rc = rtems_rfs_inode_close (  fs,   &parent_inode );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &target_inode );
           return rc;
           }
          
           rc = rtems_rfs_inode_close (  fs,   &target_inode );
          
           return rc;
          }
          
          int
     110  rtems_rfs_unlink (  rtems_rfs_file_system* fs,  
           rtems_rfs_ino parent,  
           rtems_rfs_ino target,  
           uint32_t doff,  
           rtems_rfs_unlink_dir dir_mode )
          {
           rtems_rfs_inode_handle parent_inode;
           rtems_rfs_inode_handle target_inode;
           uint16_t links;
           bool dir;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_UNLINK ) )
           printf (  "rtems-rfs: unlink: parent(  %" PRIu32 " ) -X-> (  %" PRIu32 " )\n",   parent,   target );
          
           rc = rtems_rfs_inode_open (  fs,   target,   &target_inode,   true );
           if (  rc )
           return rc;
          
           /*
           * If a directory process the unlink mode.
           */
          
           dir = RTEMS_RFS_S_ISDIR (  rtems_rfs_inode_get_mode (  &target_inode ) );
           if (  dir )
           {
           switch (  dir_mode )
           {
           case rtems_rfs_unlink_dir_denied:
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_UNLINK ) )
           printf (  "rtems-rfs: link is a directory\n" );
           rtems_rfs_inode_close (  fs,   &target_inode );
           return EISDIR;
          
           case rtems_rfs_unlink_dir_if_empty:
           rc = rtems_rfs_dir_empty (  fs,   &target_inode );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_UNLINK ) )
           printf (  "rtems-rfs: dir-empty: %d: %s\n",   rc,   strerror (  rc ) );
           rtems_rfs_inode_close (  fs,   &target_inode );
           return rc;
           }
           break;
          
           default:
           break;
           }
           }
          
           rc = rtems_rfs_inode_open (  fs,   parent,   &parent_inode,   true );
           if (  rc )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_UNLINK ) )
           printf (  "rtems-rfs: link: inode-open failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           rtems_rfs_inode_close (  fs,   &target_inode );
           return rc;
           }
          
           rc = rtems_rfs_dir_del_entry (  fs,   &parent_inode,   target,   doff );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_UNLINK ) )
           printf (  "rtems-rfs: unlink: dir-del failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           rtems_rfs_inode_close (  fs,   &parent_inode );
           rtems_rfs_inode_close (  fs,   &target_inode );
           return rc;
           }
          
           links = rtems_rfs_inode_get_links (  &target_inode );
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_UNLINK ) )
           printf (  "rtems-rfs: unlink: target:%" PRIu32 " links:%u\n",   target,   links );
          
           if (  links > 1 )
           {
           links--;
           rtems_rfs_inode_set_links (  &target_inode,   links );
           }
           else
           {
           /*
           * Erasing the inode releases all blocks attached to it.
           */
           rc = rtems_rfs_inode_delete (  fs,   &target_inode );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_UNLINK ) )
           printf (  "rtems-rfs: unlink: inode-del failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           rtems_rfs_inode_close (  fs,   &parent_inode );
           rtems_rfs_inode_close (  fs,   &target_inode );
           return rc;
           }
          
           if (  dir )
           {
           links = rtems_rfs_inode_get_links (  &parent_inode );
           if (  links > 1 )
           links--;
           rtems_rfs_inode_set_links (  &parent_inode,   links );
           }
           }
          
           rc = rtems_rfs_inode_time_stamp_now (  &parent_inode,   true,   true );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_UNLINK ) )
           printf (  "rtems-rfs: link: inode-time-stamp failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           rtems_rfs_inode_close (  fs,   &parent_inode );
           rtems_rfs_inode_close (  fs,   &target_inode );
           return rc;
           }
          
           rc = rtems_rfs_inode_close (  fs,   &parent_inode );
           if (  rc > 0 )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_UNLINK ) )
           printf (  "rtems-rfs: link: parent inode-close failed: %d: %s\n",  
           rc,   strerror (  rc ) );
           rtems_rfs_inode_close (  fs,   &target_inode );
           return rc;
           }
          
           rc = rtems_rfs_inode_close (  fs,   &target_inode );
          
           if (  (  rc > 0 ) && rtems_rfs_trace (  RTEMS_RFS_TRACE_UNLINK ) )
           printf (  "rtems-rfs: link: target inode-close failed: %d: %s\n",  
           rc,   strerror (  rc ) );
          
           return rc;
          }
          
          int
     247  rtems_rfs_symlink (  rtems_rfs_file_system* fs,  
           const char* name,  
           int length,  
           const char* link,  
           int link_length,  
           uid_t uid,  
           gid_t gid,  
           rtems_rfs_ino parent )
          {
           rtems_rfs_inode_handle inode;
           rtems_rfs_ino ino;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_SYMLINK ) )
           {
           int c;
           printf (  "rtems-rfs: symlink: parent:%" PRIu32 " name:",   parent );
           for (  c = 0; c < length; c++ )
           printf (  "%c",   name[c] );
           printf (  " link:" );
           for (  c = 0; c < link_length; c++ )
           printf (  "%c",   link[c] );
           }
          
           if (  link_length >= rtems_rfs_fs_block_size (  fs ) )
           return ENAMETOOLONG;
          
           rc = rtems_rfs_inode_create (  fs,   parent,   name,   strlen (  name ),  
           RTEMS_RFS_S_SYMLINK,  
           1,   uid,   gid,   &ino );
           if (  rc > 0 )
           return rc;
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc > 0 )
           return rc;
          
           /*
           * If the link length is less than the length of data union in the inode
           * place the link into the data area else allocate a block and write the link
           * to that.
           */
           if (  link_length < RTEMS_RFS_INODE_DATA_NAME_SIZE )
           {
           memset (  inode.node->data.name,   0,   RTEMS_RFS_INODE_DATA_NAME_SIZE );
           memcpy (  inode.node->data.name,   link,   link_length );
           rtems_rfs_inode_set_block_count (  &inode,   0 );
           }
           else
           {
           rtems_rfs_block_map map;
           rtems_rfs_block_no block;
           rtems_rfs_buffer_handle buffer;
           uint8_t* data;
          
           rc = rtems_rfs_block_map_open (  fs,   &inode,   &map );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           rc = rtems_rfs_block_map_grow (  fs,   &map,   1,   &block );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &buffer,   block,   false );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           data = rtems_rfs_buffer_data (  &buffer );
          
           memset (  data,   0xff,   rtems_rfs_fs_block_size (  fs ) );
           memcpy (  data,   link,   link_length );
          
           rc = rtems_rfs_buffer_handle_close (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           rc = rtems_rfs_block_map_close (  fs,   &map );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
           }
          
           rtems_rfs_inode_set_block_offset (  &inode,   link_length );
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
          
           return rc;
          }
          
          int
     362  rtems_rfs_symlink_read (  rtems_rfs_file_system* fs,  
           rtems_rfs_ino link,  
           char* path,  
           size_t size,  
           size_t* length )
          {
           rtems_rfs_inode_handle inode;
           int rc;
          
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_SYMLINK_READ ) )
           printf (  "rtems-rfs: symlink-read: link:%" PRIu32 "\n",   link );
          
           rc = rtems_rfs_inode_open (  fs,   link,   &inode,   true );
           if (  rc )
           return rc;
          
           if (  !RTEMS_RFS_S_ISLNK (  rtems_rfs_inode_get_mode (  &inode ) ) )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           return EINVAL;
           }
          
           *length = rtems_rfs_inode_get_block_offset (  &inode );
          
           if (  size < *length )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           return EINVAL;
           }
          
           if (  rtems_rfs_inode_get_block_count (  &inode ) == 0 )
           {
           memcpy (  path,   inode.node->data.name,   *length );
           }
           else
           {
           rtems_rfs_block_map map;
           rtems_rfs_block_no block;
           rtems_rfs_buffer_handle buffer;
           char* data;
          
           rc = rtems_rfs_block_map_open (  fs,   &inode,   &map );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           rc = rtems_rfs_block_map_seek (  fs,   &map,   0,   &block );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &buffer,   block,   false );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           data = rtems_rfs_buffer_data (  &buffer );
           memcpy (  path,   data,   *length );
          
           rc = rtems_rfs_buffer_handle_close (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_block_map_close (  fs,   &map );
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
          
           rc = rtems_rfs_block_map_close (  fs,   &map );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           return rc;
           }
           }
          
           path[*length] = '\0';
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
          
           return rc;
          }

libfs/src/rfs/rtems-rfs-mutex.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-mutex.c,  v 1.2 2010/03/27 04:04:40 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File System Mutex.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/rfs/rtems-rfs-mutex.h>
          
          #if __rtems__
          /**
           * RTEMS_RFS Mutex Attributes
           *
           * @warning Do not configure as inherit priority. If a driver is in the driver
           * initialisation table this locked semaphore will have the IDLE task
           * as the holder and a blocking task will raise the priority of the
           * IDLE task which can cause unsual side effects like not work.
           */
          #define RTEMS_RFS_MUTEX_ATTRIBS \
           (  RTEMS_PRIORITY | RTEMS_SIMPLE_BINARY_SEMAPHORE | \
           RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL )
          #endif
      37  
          int
          rtems_rfs_mutex_create (  rtems_rfs_mutex* mutex )
          {
          #if __rtems__
           rtems_status_code sc;
           sc = rtems_semaphore_create (  rtems_build_name (  'R',   'F',   'S',   'm' ),  
           1,   RTEMS_RFS_MUTEX_ATTRIBS,   0,  
           mutex );
           if (  sc != RTEMS_SUCCESSFUL )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_MUTEX ) )
           printf (  "rtems-rfs: mutex: open failed: %s\n",  
           rtems_status_text (  sc ) );
           return EIO;
           }
          #endif
           return 0;
          }
      56  
          int
          rtems_rfs_mutex_destroy (  rtems_rfs_mutex* mutex )
          {
          #if __rtems__
           rtems_status_code sc;
           sc = rtems_semaphore_delete (  *mutex );
           if (  sc != RTEMS_SUCCESSFUL )
           {
           if (  rtems_rfs_trace (  RTEMS_RFS_TRACE_MUTEX ) )
           printf (  "rtems-rfs: mutex: close failed: %s\n",  
           rtems_status_text (  sc ) );
           return EIO;
           }
          #endif
           return 0;
          }

libfs/src/rfs/rtems-rfs-rtems-dev.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-rtems-dev.c,  v 1.4 2010/07/01 20:18:41 joel Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS RFS Device Interface.
           *
           * This file contains the set of handlers used to map operations on RFS device
           * nodes onto calls to the RTEMS Classic API IO Manager.
           *
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include "rtems-rfs-rtems.h"
          
          /*
           * Convert RTEMS status to a UNIX errno
           */
      31  extern int rtems_deviceio_errno (  rtems_status_code code );
          
          /**
           * This handler maps an open(   ) operation onto rtems_io_open(   ).
           *
           * @param iop
           * @param pathname
           * @param flag
           * @param mode
           * @return int
           */
          static int
      43  rtems_rfs_rtems_device_open (   rtems_libio_t *iop,  
           const char *pathname,  
           uint32_t flag,  
           uint32_t mode )
          {
           rtems_libio_open_close_args_t args;
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  &iop->pathinfo );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_iop_ino (  iop );
           rtems_rfs_inode_handle inode;
           int major;
           int minor;
           rtems_status_code status;
           int rc;
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "device_open: opening inode",   rc );
           }
          
           major = rtems_rfs_inode_get_block (  &inode,   0 );
           minor = rtems_rfs_inode_get_block (  &inode,   1 );
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "device_open: closing inode",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
          
           iop->data0 = major;
           iop->data1 = (  void* )(  (  intptr_t ) minor );
          
           args.iop = iop;
           args.flags = iop->flags;
           args.mode = mode;
          
           status = rtems_io_open (  major,   minor,   (  void * ) &args );
          
           return rtems_deviceio_errno (  status );
          }
          
          /**
           * This handler maps a close(   ) operation onto rtems_io_close(   ).
           *
           * @param iop
           * @return int
           */
          
          static int
      98  rtems_rfs_rtems_device_close (  rtems_libio_t* iop )
          {
           rtems_libio_open_close_args_t args;
           rtems_status_code status;
           int major;
           int minor;
          
           major = (  int ) iop->data0;
           minor = (  intptr_t ) iop->data1;
          
           args.iop = iop;
           args.flags = 0;
           args.mode = 0;
          
           status = rtems_io_close (  major,   minor,   (  void * ) &args );
          
           return rtems_deviceio_errno (  status );
          }
          
          /**
           * This handler maps a read(   ) operation onto rtems_io_read(   ).
           *
           * @param iop
           * @param buffer
           * @param count
           * @return ssize_t
           */
          
          static ssize_t
     127  rtems_rfs_rtems_device_read (  rtems_libio_t* iop,   void* buffer,   size_t count )
          {
           rtems_libio_rw_args_t args;
           rtems_status_code status;
           int major;
           int minor;
          
           major = (  int ) iop->data0;
           minor = (  intptr_t ) iop->data1;
          
           args.iop = iop;
           args.offset = iop->offset;
           args.buffer = buffer;
           args.count = count;
           args.flags = iop->flags;
           args.bytes_moved = 0;
          
           status = rtems_io_read (  major,   minor,   (  void * ) &args );
           if (  status )
           return rtems_deviceio_errno (  status );
          
           return (  ssize_t ) args.bytes_moved;
          }
          
          /*
           * This handler maps a write(   ) operation onto rtems_io_write(   ).
           *
           * @param iop
           * @param buffer
           * @param count
           * @return ssize_t
           */
          
          static ssize_t
     161  rtems_rfs_rtems_device_write (  rtems_libio_t* iop,  
           const void* buffer,  
           size_t count )
          {
           rtems_libio_rw_args_t args;
           rtems_status_code status;
           int major;
           int minor;
          
           major = (  int ) iop->data0;
           minor = (  intptr_t ) iop->data1;
          
           args.iop = iop;
           args.offset = iop->offset;
           args.buffer = (  void * ) buffer;
           args.count = count;
           args.flags = iop->flags;
           args.bytes_moved = 0;
          
           status = rtems_io_write (  major,   minor,   (  void * ) &args );
           if (  status )
           return rtems_deviceio_errno (  status );
          
           return (  ssize_t ) args.bytes_moved;
          }
          
          /**
           * This handler maps an ioctl(   ) operation onto rtems_io_ioctl(   ).
           *
           * @param iop
           * @param command
           * @param buffer
           * @return int
           */
          
          static int
     197  rtems_rfs_rtems_device_ioctl (  rtems_libio_t* iop,  
           uint32_t command,  
           void* buffer )
          {
           rtems_libio_ioctl_args_t args;
           rtems_status_code status;
           int major;
           int minor;
          
           major = (  int ) iop->data0;
           minor = (  intptr_t ) iop->data1;
          
           args.iop = iop;
           args.command = command;
           args.buffer = buffer;
          
           status = rtems_io_control (  major,   minor,   (  void * ) &args );
           if (  status )
           return rtems_deviceio_errno (  status );
          
           return args.ioctl_return;
          }
          
          /**
           * This handler eats all lseek(   ) operations and does not create an error. It
           * assumes all devices can handle the seek. The writes fail.
           *
           * @param iop
           * @param offset
           * @param whence
           * @return rtems_off64_t
           */
          
          static rtems_off64_t
     231  rtems_rfs_rtems_device_lseek (  rtems_libio_t* iop,  
           rtems_off64_t offset,  
           int whence )
          {
           return offset;
          }
          
          /**
           * The consumes the truncate call. You cannot truncate device files.
           *
           * @param iop
           * @param length
           * @return int
           */
          
          static int
     247  rtems_rfs_rtems_device_ftruncate (  rtems_libio_t* iop,   rtems_off64_t length )
          {
           return 0;
          }
          
          /*
           * Handler table for RFS device nodes
           */
          
          const rtems_filesystem_file_handlers_r rtems_rfs_rtems_device_handlers = {
           .open_h = rtems_rfs_rtems_device_open,  
           .close_h = rtems_rfs_rtems_device_close,  
           .read_h = rtems_rfs_rtems_device_read,  
           .write_h = rtems_rfs_rtems_device_write,  
           .ioctl_h = rtems_rfs_rtems_device_ioctl,  
           .lseek_h = rtems_rfs_rtems_device_lseek,  
           .fstat_h = rtems_rfs_rtems_stat,  
           .fchmod_h = rtems_rfs_rtems_fchmod,  
           .ftruncate_h = rtems_rfs_rtems_device_ftruncate,  
           .fpathconf_h = rtems_filesystem_default_fpathconf,  
           .fsync_h = rtems_filesystem_default_fsync,  
           .fdatasync_h = rtems_filesystem_default_fdatasync,  
           .fcntl_h = rtems_filesystem_default_fcntl,  
           .rmnod_h = rtems_rfs_rtems_rmnod
          };

libfs/src/rfs/rtems-rfs-rtems-dir.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-rtems-dir.c,  v 1.7 2010/10/11 04:34:48 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS RFS Directory Access Routines
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <stdlib.h>
          #include <stdio.h>
          #include <unistd.h>
          
          #include <rtems/rfs/rtems-rfs-dir.h>
          #include <rtems/rfs/rtems-rfs-link.h>
          #include "rtems-rfs-rtems.h"
          
          /**
           * This rountine will verify that the node being opened as a directory is in
           * fact a directory node. If it is then the offset into the directory will be
           * set to 0 to position to the first directory entry.
           *
           * @param iop
           * @param pathname
           * @param flag
           * @param mode
           * @@return int
           */
          static int
      47  rtems_rfs_rtems_dir_open (  rtems_libio_t* iop,  
           const char* pathname,  
           uint32_t flag,  
           uint32_t mode )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  &iop->pathinfo );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_iop_ino (  iop );
           rtems_rfs_inode_handle inode;
           int rc;
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "dir_open: opening inode",   rc );
           }
          
           if (  !RTEMS_RFS_S_ISDIR (  rtems_rfs_inode_get_mode (  &inode ) ) )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "dir_open: not dir",   ENOTDIR );
           }
          
           iop->offset = 0;
          
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return 0;
          }
          
          /**
           * This routine will be called by the generic close routine to cleanup any
           * resources that have been allocated for the management of the file
           *
           * @param iop
           * @retval 0 Always no error.
           */
          static int
      88  rtems_rfs_rtems_dir_close (  rtems_libio_t* iop )
          {
           /*
           * The RFS does not hold any resources. Nothing to do.
           */
           return 0;
          }
          
          /**
           * This routine will read the next directory entry based on the directory
           * offset. The offset should be equal to -n- time the size of an individual
           * dirent structure. If n is not an integer multiple of the sizeof a dirent
           * structure,   an integer division will be performed to determine directory
           * entry that will be returned in the buffer. Count should reflect -m- times
           * the sizeof dirent bytes to be placed in the buffer. If there are not -m-
           * dirent elements from the current directory position to the end of the
           * exisiting file,   the remaining entries will be placed in the buffer and the
           * returned value will be equal to -m actual- times the size of a directory
           * entry.
           */
          static ssize_t
     109  rtems_rfs_rtems_dir_read (  rtems_libio_t* iop,  
           void* buffer,  
           size_t count )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  &iop->pathinfo );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_iop_ino (  iop );
           rtems_rfs_inode_handle inode;
           struct dirent* dirent;
           ssize_t bytes_transferred;
           int d;
           int rc;
          
           count = count / sizeof (  struct dirent );
           dirent = buffer;
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "dir_read: read inode",   rc );
           }
          
           bytes_transferred = 0;
          
           for (  d = 0; d < count; d++,   dirent++ )
           {
           size_t size;
           rc = rtems_rfs_dir_read (  fs,   &inode,   iop->offset,   dirent,   &size );
           if (  rc == ENOENT )
           {
           rc = 0;
           break;
           }
           if (  rc > 0 )
           {
           bytes_transferred = rtems_rfs_rtems_error (  "dir_read: dir read",   rc );
           break;
           }
           iop->offset += size;
           bytes_transferred += sizeof (  struct dirent );
           }
          
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
          
           return bytes_transferred;
          }
          
          /**
           * This routine will behave in one of three ways based on the state of argument
           * whence. Based on the state of its value the offset argument will be
           * interpreted using one of the following methods:
           *
           * SEEK_SET - offset is the absolute byte offset from the start of the
           * logical start of the dirent sequence that represents the
           * directory
           * SEEK_CUR - offset is used as the relative byte offset from the current
           * directory position index held in the iop structure
           * SEEK_END - N/A --> This will cause an assert.
           *
           * @param iop
           * @param offset
           * @param whence
           * return rtems_off64_t
           */
          static rtems_off64_t
     177  rtems_rfs_rtems_dir_lseek (  rtems_libio_t* iop,  
           rtems_off64_t offset,  
           int whence )
          {
           switch (  whence )
           {
           case SEEK_SET: /* absolute move from the start of the file */
           case SEEK_CUR: /* relative move */
           break;
          
           case SEEK_END: /* Movement past the end of the directory via lseek */
           /* is not a permitted operation */
           default:
           return rtems_rfs_rtems_error (  "dir_lseek: bad whence",   EINVAL );
           break;
           }
           return 0;
          }
          
          static int
     197  rtems_rfs_rtems_dir_rmnod (  rtems_filesystem_location_info_t* parent_pathloc,  
           rtems_filesystem_location_info_t* pathloc )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (  parent_pathloc );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (  pathloc );
           uint32_t doff = rtems_rfs_rtems_get_pathloc_doff (  pathloc );
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_DIR_RMNOD ) )
           printf (  "rtems-rfs: dir-rmnod: parent:%" PRId32 " doff:%" PRIu32 ",   ino:%" PRId32 "\n",  
           parent,   doff,   ino );
          
           if (  ino == RTEMS_RFS_ROOT_INO )
           return rtems_rfs_rtems_error (  "dir_rmnod: root inode",   EBUSY );
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_unlink (  fs,   parent,   ino,   doff,   rtems_rfs_unlink_dir_if_empty );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "dir_rmnod: unlinking",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
           return 0;
          }
          
          /*
           * Set of operations handlers for operations on directories.
           */
          
          const rtems_filesystem_file_handlers_r rtems_rfs_rtems_dir_handlers = {
           .open_h = rtems_rfs_rtems_dir_open,  
           .close_h = rtems_rfs_rtems_dir_close,  
           .read_h = rtems_rfs_rtems_dir_read,  
           .write_h = rtems_filesystem_default_write,  
           .ioctl_h = rtems_filesystem_default_ioctl,  
           .lseek_h = rtems_rfs_rtems_dir_lseek,  
           .fstat_h = rtems_rfs_rtems_stat,  
           .fchmod_h = rtems_rfs_rtems_fchmod,  
           .ftruncate_h = rtems_filesystem_default_ftruncate,  
           .fpathconf_h = rtems_filesystem_default_fpathconf,  
           .fsync_h = rtems_filesystem_default_fsync,  
           .fdatasync_h = rtems_rfs_rtems_fdatasync,  
           .fcntl_h = rtems_filesystem_default_fcntl,  
           .rmnod_h = rtems_rfs_rtems_dir_rmnod
          };

libfs/src/rfs/rtems-rfs-rtems-file.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-rtems-file.c,  v 1.9 2010/10/18 22:39:35 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS RFS File Handlers
           *
           * This file contains the set of handlers used to process operations on
           * RFS file nodes.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <rtems/rfs/rtems-rfs-file.h>
          #include "rtems-rfs-rtems.h"
          
          /**
           * This routine processes the open(   ) system call. Note that there is nothing
           * special to be done at open(   ) time.
           *
           * @param iop
           * @param pathname
           * @param flag
           * @param mode
           * @return int
           */
          
          static int
      42  rtems_rfs_rtems_file_open (  rtems_libio_t* iop,  
           const char* pathname,  
           uint32_t flag,  
           uint32_t mode )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  &iop->pathinfo );
           rtems_rfs_ino ino;
           rtems_rfs_file_handle* file;
           uint32_t flags;
           int rc;
          
           flags = 0;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN ) )
           printf(  "rtems-rfs: file-open: path:%s ino:%" PRId32 " flags:%04" PRIx32 " mode:%04" PRIx32 "\n",  
           pathname,   ino,   flags,   mode );
          
           rtems_rfs_rtems_lock (  fs );
          
           ino = rtems_rfs_rtems_get_iop_ino (  iop );
          
           rc = rtems_rfs_file_open (  fs,   ino,   flags,   &file );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "file-open: open",   rc );
           }
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN ) )
           printf(  "rtems-rfs: file-open: handle:%p\n",   file );
          
           iop->pathinfo.node_access = file;
          
           rtems_rfs_rtems_unlock (  fs );
           return 0;
          }
          
          /**
           * This routine processes the close(   ) system call. Note that there is nothing
           * to flush at this point.
           *
           * @param iop
           * @return int
           */
          static int
      87  rtems_rfs_rtems_file_close (  rtems_libio_t* iop )
          {
           rtems_rfs_file_handle* file = iop->pathinfo.node_access;
           rtems_rfs_file_system* fs = rtems_rfs_file_fs (  file );
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_FILE_CLOSE ) )
           printf(  "rtems-rfs: file-close: handle:%p\n",   file );
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_file_close (  fs,   file );
           if (  rc > 0 )
           rc = rtems_rfs_rtems_error (  "file-close: file close",   rc );
          
           rtems_rfs_rtems_unlock (  fs );
           return rc;
          }
          
          /**
           * This routine processes the read(   ) system call.
           *
           * @param iop
           * @param buffer
           * @param count
           * @return int
           */
          ssize_t
     115  rtems_rfs_rtems_file_read (  rtems_libio_t* iop,  
           void* buffer,  
           size_t count )
          {
           rtems_rfs_file_handle* file = iop->pathinfo.node_access;
           rtems_rfs_pos pos;
           uint8_t* data = buffer;
           ssize_t read = 0;
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_FILE_READ ) )
           printf(  "rtems-rfs: file-read: handle:%p count:%zd\n",   file,   count );
          
           rtems_rfs_rtems_lock (  rtems_rfs_file_fs (  file ) );
          
           pos = iop->offset;
          
           if (  pos < rtems_rfs_file_size (  file ) )
           {
           while (  count )
           {
           size_t size;
          
           rc = rtems_rfs_file_io_start (  file,   &size,   true );
           if (  rc > 0 )
           {
           read = rtems_rfs_rtems_error (  "file-read: read: io-start",   rc );
           break;
           }
          
           if (  size == 0 )
           break;
          
           if (  size > count )
           size = count;
          
           memcpy (  data,   rtems_rfs_file_data (  file ),   size );
          
           data += size;
           count -= size;
           read += size;
          
           rc = rtems_rfs_file_io_end (  file,   size,   true );
           if (  rc > 0 )
           {
           read = rtems_rfs_rtems_error (  "file-read: read: io-end",   rc );
           break;
           }
           }
           }
          
           rtems_rfs_rtems_unlock (  rtems_rfs_file_fs (  file ) );
          
           return read;
          }
          
          /**
           * This routine processes the write(   ) system call.
           *
           * @param iop
           * @param buffer
           * @param count
           * @return ssize_t
           */
          ssize_t
     180  rtems_rfs_rtems_file_write (  rtems_libio_t* iop,  
           const void* buffer,  
           size_t count )
          {
           rtems_rfs_file_handle* file = iop->pathinfo.node_access;
           rtems_rfs_pos pos;
           const uint8_t* data = buffer;
           ssize_t write = 0;
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_FILE_WRITE ) )
           printf(  "rtems-rfs: file-write: handle:%p count:%zd\n",   file,   count );
          
           rtems_rfs_rtems_lock (  rtems_rfs_file_fs (  file ) );
          
           pos = iop->offset;
          
           /*
           * If the iop position is past the physical end of the file we need to set the
           * file size to the new length before writing.
           */
          
           if (  pos > rtems_rfs_file_size (  file ) )
           {
           rc = rtems_rfs_file_set_size (  file,   pos );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  rtems_rfs_file_fs (  file ) );
           return rtems_rfs_rtems_error (  "file-write: write extend",   rc );
           }
           rtems_rfs_file_set_bpos (  file,   pos );
           }
          
           while (  count )
           {
           size_t size = count;
          
           rc = rtems_rfs_file_io_start (  file,   &size,   false );
           if (  rc )
           {
           write = rtems_rfs_rtems_error (  "file-write: write open",   rc );
           break;
           }
          
           if (  size > count )
           size = count;
          
           memcpy (  rtems_rfs_file_data (  file ),   data,   size );
          
           data += size;
           count -= size;
           write += size;
          
           rc = rtems_rfs_file_io_end (  file,   size,   false );
           if (  rc )
           {
           write = rtems_rfs_rtems_error (  "file-write: write close",   rc );
           break;
           }
           }
          
           iop->size = rtems_rfs_file_size (  file );
          
           rtems_rfs_rtems_unlock (  rtems_rfs_file_fs (  file ) );
          
           return write;
          }
          
          /**
           * This routine processes the ioctl(   ) system call.
           *
           * @note No ioctl(   )'s are currently supported for RFS files.
           *
           * @param iop
           * @param command
           * @param buffer
           */
          
          int
     259  rtems_rfs_rtems_file_ioctl (  rtems_libio_t* iop,   uint32_t command,   void* buffer )
          {
           return 0;
          }
          
          /**
           * This routine processes the lseek(   ) system call.
           *
           * @param iop
           * @param offset
           * @param whence
           * @return rtems_off64_t
           */
          rtems_off64_t
     273  rtems_rfs_rtems_file_lseek (  rtems_libio_t* iop,  
           rtems_off64_t offset,  
           int whence )
          {
           rtems_rfs_file_handle* file = iop->pathinfo.node_access;
           rtems_rfs_pos pos;
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_FILE_LSEEK ) )
           printf(  "rtems-rfs: file-lseek: handle:%p offset:%Ld\n",   file,   offset );
          
           rtems_rfs_rtems_lock (  rtems_rfs_file_fs (  file ) );
          
           pos = iop->offset;
          
           rc = rtems_rfs_file_seek (  file,   pos,   &pos );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  rtems_rfs_file_fs (  file ) );
           return rtems_rfs_rtems_error (  "file_lseek: lseek",   rc );
           }
          
           rtems_rfs_rtems_unlock (  rtems_rfs_file_fs (  file ) );
          
           return iop->offset;
          }
          
          /**
           * This routine processes the ftruncate(   ) system call.
           *
           * @param iop
           * @param length
           * @return int
           */
          int
     308  rtems_rfs_rtems_file_ftruncate (  rtems_libio_t* iop,  
           rtems_off64_t length )
          {
           rtems_rfs_file_handle* file = iop->pathinfo.node_access;
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_FILE_FTRUNC ) )
           printf(  "rtems-rfs: file-ftrunc: handle:%p length:%Ld\n",   file,   length );
          
           rtems_rfs_rtems_lock (  rtems_rfs_file_fs (  file ) );
          
           rc = rtems_rfs_file_set_size (  file,   length );
           if (  rc )
           rc = rtems_rfs_rtems_error (  "file_ftruncate: set size",   rc );
          
           iop->size = rtems_rfs_file_size (  file );
          
           rtems_rfs_rtems_unlock (  rtems_rfs_file_fs (  file ) );
          
           return rc;
          }
          
          /*
           * Set of operations handlers for operations on RFS files.
           */
          
          const rtems_filesystem_file_handlers_r rtems_rfs_rtems_file_handlers = {
           .open_h = rtems_rfs_rtems_file_open,  
           .close_h = rtems_rfs_rtems_file_close,  
           .read_h = rtems_rfs_rtems_file_read,  
           .write_h = rtems_rfs_rtems_file_write,  
           .ioctl_h = rtems_rfs_rtems_file_ioctl,  
           .lseek_h = rtems_rfs_rtems_file_lseek,  
           .fstat_h = rtems_rfs_rtems_stat,  
           .fchmod_h = rtems_rfs_rtems_fchmod,  
           .ftruncate_h = rtems_rfs_rtems_file_ftruncate,  
           .fpathconf_h = rtems_filesystem_default_fpathconf,  
           .fsync_h = rtems_rfs_rtems_fdatasync,  
           .fdatasync_h = rtems_rfs_rtems_fdatasync,  
           .fcntl_h = rtems_filesystem_default_fcntl,  
           .rmnod_h = rtems_rfs_rtems_rmnod
          };

libfs/src/rfs/rtems-rfs-rtems-utils.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-rtems-utils.c,  v 1.2 2010/03/27 04:04:40 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * Set of utility functions to support RTEMS RFS on RTEMS.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <stdlib.h>
          
          #include "rtems-rfs-rtems.h"
          
          bool
      29  rtems_rfs_rtems_eval_perms (  rtems_rfs_inode_handle* inode,   int flags )
          {
           uid_t st_uid;
           gid_t st_gid;
           uint16_t uid;
           uint16_t gid;
           uint16_t mode;
           int flags_to_test;
          
           uid = rtems_rfs_inode_get_uid (  inode );
           gid = rtems_rfs_inode_get_gid (  inode );
           mode = rtems_rfs_inode_get_mode (  inode );
          
          #if defined (  RTEMS_POSIX_API )
           st_uid = geteuid (   );
           st_gid = getegid (   );
          #else
           st_uid = uid;
           st_gid = gid;
          #endif
          
           /*
           * Check if I am owner or a group member or someone else.
           */
           flags_to_test = flags;
          
           if (  (  st_uid == 0 ) || (  st_uid == uid ) )
           flags_to_test |= flags << 6;
           if (  (  st_uid == 0 ) || (  st_gid == gid ) )
           flags_to_test |= flags << 3;
           else
           /* must be other - already set above */;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_PERMS ) )
           printf (  "rtems-rfs: eval-perms: uid=%d gid=%d iuid=%d igid=%d " \
           "flags=%o flags_to_test=%o mode=%o (  %o )\n",  
           st_uid,   st_gid,   uid,   gid,  
           flags,   flags_to_test,   mode & 0777,  
           flags_to_test & (  mode & 0777 ) );
          
           /*
           * If all of the flags are set we have permission
           * to do this.
           */
           if (  (  flags_to_test & (  mode & 0777 ) ) != 0 )
           return true;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_PERMS ) )
           printf(  "rtems-rfs: eval-perms: perms failed\n" );
          
           return false;
          }
          
          /*
           * The following sets the handlers based on the type of inode.
           */
          
          bool
      87  rtems_rfs_rtems_set_handlers (  rtems_filesystem_location_info_t* loc,  
           rtems_rfs_inode_handle* inode )
          {
           uint16_t mode = rtems_rfs_inode_get_mode (  inode );
           loc->handlers = NULL;
           if (  RTEMS_RFS_S_ISDIR (  mode ) )
           loc->handlers = rtems_rfs_rtems_handlers (  dir );
           else if (  RTEMS_RFS_S_ISCHR (  mode ) || RTEMS_RFS_S_ISBLK(  mode ) )
           loc->handlers = rtems_rfs_rtems_handlers (  device );
           else if (  RTEMS_RFS_S_ISLNK (  mode ) )
           loc->handlers = rtems_rfs_rtems_handlers (  link );
           else if (  RTEMS_RFS_S_ISREG (  mode ) )
           loc->handlers = rtems_rfs_rtems_handlers (  file );
           else
           {
           printf (  "rtems-rfs: mode type unknown: %04x\n",   mode );
           return false;
           }
           return true;
          }
          
          uint16_t
     109  rtems_rfs_rtems_imode (  mode_t mode )
          {
           /*
           * Mapping matches RTEMS so no need to change.
           */
           return mode;
          }
          
          mode_t
     118  rtems_rfs_rtems_mode (  int imode )
          {
           /*
           * Mapping matches RTEMS so no need to change.
           */
           return imode;
          }
          
          /*
           * Only provide if there is no macro version.
           */
          #if !defined (  rtems_rfs_rtems_error )
          int
     131  rtems_rfs_rtems_error (  const char* mesg,   int error )
          {
           if (  error )
           printf (  "rtems-rfs: %s: %d: %s\n",   mesg,   error,   strerror (  error ) );
           errno = error;
           return error == 0 ? 0 : -1;
          }
          #endif
          
          #if RTEMS_RFS_RTEMS_TRACE
          static uint32_t rtems_rfs_rtems_trace_mask;
          
          bool
     144  rtems_rfs_rtems_trace (  uint32_t mask )
          {
           bool result = false;
           if (  mask & rtems_rfs_rtems_trace_mask )
           result = true;
           return result;
          }
          
          void
     153  rtems_rfs_trace_rtems_set_mask (  uint32_t mask )
          {
           rtems_rfs_rtems_trace_mask |= mask;
          }
          
          void
     159  rtems_rfs_trace_rtems_clear_mask (  uint32_t mask )
          {
           rtems_rfs_rtems_trace_mask &= ~mask;
          }
          
          int
     165  rtems_rfs_rtems_trace_shell_command (  int argc,   char *argv[] )
          {
           const char* table[] =
           {
           "error-msgs",  
           "eval-path"
           "eval-for-make",  
           "eval-perms",  
           "mknod",  
           "rmnod",  
           "link",  
           "unlink",  
           "chown",  
           "readlink",  
           "fchmod",  
           "stat",  
           "dir-rmnod",  
           "file-open",  
           "file-close",  
           "file-read",  
           "file-write",  
           "file-lseek",  
           "file-ftrunc"
           };
          
           bool set = true;
           int arg;
           int t;
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           switch (  argv[arg][1] )
           {
           case 'h':
           printf (  "usage: %s [-hl] [set/clear] [flags]\n",   argv[0] );
           return 0;
           case 'l':
           printf (  "%s: valid flags to set or clear are:\n",   argv[0] );
           for (  t = 0; t < (  sizeof (  table ) / sizeof (  const char* ) ); t++ )
           printf (  " %s\n",   table[t] );
           return 0;
           default:
           printf (  "error: unknown option\n" );
           return 1;
           }
           }
           else
           {
           uint32_t value = 0;
           if (  strcmp (  argv[arg],   "set" ) == 0 )
           set = true;
           if (  strcmp (  argv[arg],   "clear" ) == 0 )
           set = false;
           else if (  strcmp (  argv[arg],   "all" ) == 0 )
           value = RTEMS_RFS_RTEMS_DEBUG_ALL;
           else
           {
           for (  t = 0; t < (  sizeof (  table ) / sizeof (  const char* ) ); t++ )
           {
           if (  strcmp (  argv[arg],   table[t] ) == 0 )
           {
           value = 1 << t;
           break;
           }
           }
           }
          
           if (  set )
           rtems_rfs_rtems_trace_mask |= value;
           else
           rtems_rfs_rtems_trace_mask &= ~value;
           }
           }
          
           return 0;
          }
          
          #endif

libfs/src/rfs/rtems-rfs-rtems.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-rtems.c,  v 1.14 2010/08/25 09:37:49 sh Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File System Interface for RTEMS.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          #include <stdlib.h>
          
          #if SIZEOF_MODE_T == 8
          #define PRIomode_t PRIo64
          #elif SIZEOF_MODE_T == 4
          #define PRIomode_t PRIo32
          #else
          #error "unsupport size of mode_t"
          #endif
          
          #include <rtems/rfs/rtems-rfs-file.h>
          #include <rtems/rfs/rtems-rfs-dir.h>
          #include <rtems/rfs/rtems-rfs-link.h>
          #include "rtems-rfs-rtems.h"
          
          /**
           * The libio permissions for read/execute.
           */
          #define RTEMS_LIBIO_PERMS_RX (  RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ )
          /**
           * The libio permissions for write/execute.
           */
          #define RTEMS_LIBIO_PERMS_WX (  RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE )
          
          /**
           * Evaluate the path to a node that wishes to be accessed. The pathloc is
           * returned with the ino to the node to be accessed.
           *
           * The routine starts from the root stripping away any leading path separators
           * breaking the path up into the node names and checking an inode exists for
           * that node name. Permissions are checked to insure access to the node is
           * allowed. A path to a node must be accessable all the way even if the end
           * result is directly accessable. As a user on Linux try "ls /root/../tmp" and
           * you will see if fails.
           *
           * The whole process is complicated by crossmount paths where we head down into
           * this file system only to return to the top and out to a another mounted file
           * system. For example we are mounted on '/e' and the user enters "ls
           * /e/a/b/../../dev". We need to head down then back up.
           *
           * @param path
           * @param pathlen
           * @param flags
           * @param pathloc
           */
          int
      69  rtems_rfs_rtems_eval_path (  const char* path,  
           size_t pathlen,  
           int flags,  
           rtems_filesystem_location_info_t* pathloc )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           rtems_rfs_inode_handle inode;
           rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (  pathloc );
           uint32_t doff = 0;
           const char* node;
           size_t node_len;
           int stripped;
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH ) )
           printf (  "rtems-rfs-rtems: eval-path: in: path:%s pathlen:%zi ino:%" PRId32 "\n",  
           path,   pathlen,   ino );
          
           /*
           * Eat any separators at the start of the path.
           */
           stripped = rtems_filesystem_prefix_separators (  path,   pathlen );
           path += stripped;
           pathlen -= stripped;
          
           rtems_rfs_rtems_lock (  fs );
          
           while (  true )
           {
           /*
           * Open and load the inode.
           */
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_path: opening inode",   rc );
           }
          
           /*
           * Is this the end of the pathname we where given ?
           */
           if (  (  *path == '\0' ) || (  pathlen == 0 ) )
           break;
          
           /*
           * If a directory the execute bit must be set for us to enter.
           */
           if (  RTEMS_RFS_S_ISDIR (  rtems_rfs_inode_get_mode (  &inode ) ) &&
           !rtems_rfs_rtems_eval_perms (  &inode,   RTEMS_LIBIO_PERMS_SEARCH ) )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_path: eval perms",   EACCES );
           }
          
           /*
           * Extract the node name we will look for this time around.
           */
           node = path;
           node_len = 0;
           while (  !rtems_filesystem_is_separator (  *path ) &&
           (  *path != '\0' ) && pathlen &&
           (  (  node_len + 1 ) < rtems_rfs_fs_max_name (  fs ) ) )
           {
           path++;
           pathlen--;
           node_len++;
           }
          
           /*
           * Eat any separators at start of the path.
           */
           stripped = rtems_filesystem_prefix_separators (  path,   pathlen );
           path += stripped;
           pathlen -= stripped;
           node_len += stripped;
          
           /*
           * If the node is the current directory and there is more path to come move
           * on it else we are at the inode we want.
           */
           if (  rtems_rfs_current_dir (  node ) )
           {
           if (  *path )
           continue;
           break;
           }
          
           /*
           * If the node is a parent we must move up one directory. If the location
           * is on another file system we have a crossmount so we call that file
           * system to handle the remainder of the path.
           */
           if (  rtems_rfs_parent_dir (  node ) )
           {
           /*
           * If we are at root inode of the file system we have a crossmount path.
           */
           if (  ino == RTEMS_RFS_ROOT_INO )
           {
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH ) )
           printf(  "rtems-rfs-rtems: eval-path: crossmount: path:%s (  %zd )\n",  
           path - node_len,   pathlen + node_len );
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           *pathloc = pathloc->mt_entry->mt_point_node;
           return (  *pathloc->ops->evalpath_h )(  path - node_len,   pathlen + node_len,  
           flags,   pathloc );
           }
          
           /*
           * We need to find the parent of this node.
           */
           rc = rtems_rfs_dir_lookup_ino (  fs,   &inode,   "..",   2,   &ino,   &doff );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_path: read parent inode",   rc );
           }
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH ) )
           printf(  "rtems-rfs-rtems: eval-path: parent: ino:%" PRId32 "\n",   ino );
           }
           else
           {
           /*
           * Look up the node name in this directory. If found drop through,   close
           * the current inode and let the loop open the inode so the mode can be
           * read and handlers set.
           */
           rc = rtems_rfs_dir_lookup_ino (  fs,   &inode,  
           node,   node_len - stripped,   &ino,   &doff );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return (  (  errno = rc ) == 0 ) ? 0 : -1;
           }
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH ) )
           printf(  "rtems-rfs-rtems: eval-path: down: path:%s ino:%" PRId32 "\n",   node,   ino );
           }
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_path: closing node",   rc );
           }
           }
          
           rtems_rfs_rtems_set_pathloc_ino (  pathloc,   ino );
           rtems_rfs_rtems_set_pathloc_doff (  pathloc,   doff );
          
           rc = rtems_rfs_rtems_set_handlers (  pathloc,   &inode ) ? 0 : EIO;
          
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH ) )
           printf(  "rtems-rfs-rtems: eval-path: ino:%" PRId32 "\n",   ino );
          
           return rc;
          }
          
          /**
           * The following routine evaluates a path for a new node to be created. The
           * pathloc is returned with a pointer to the parent of the new node. The name
           * is returned with a pointer to the first character in the new node name. The
           * parent node is verified to be a directory.
           *
           * @param path
           * @param pathloc
           * @param name
           * @return int
           */
          int
     247  rtems_rfs_rtems_eval_for_make (  const char* path,  
           rtems_filesystem_location_info_t* pathloc,  
           const char** name )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           rtems_rfs_inode_handle inode;
           rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (  pathloc );
           rtems_rfs_ino node_ino;
           uint32_t doff = 0;
           const char* node;
           int node_len;
           int stripped;
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE ) )
           printf (  "rtems-rfs-rtems: eval-for-make: path:%s ino:%" PRId32 "\n",   path,   ino );
          
           *name = path + strlen (  path );
          
           while (  *name != path )
           {
           (  *name )--;
           if (  rtems_filesystem_is_separator (  **name ) )
           {
           (  *name )++;
           break;
           }
           }
          
           /*
           * Eat any separators at start of the path.
           */
           stripped = rtems_filesystem_prefix_separators (  path,   strlen(  path ) );
           path += stripped;
          
           rtems_rfs_rtems_lock (  fs );
          
           while (  true )
           {
           /*
           * Open and load the inode.
           */
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_for_make: read ino",   rc );
           }
          
           /*
           * If a directory the execute bit must be set for us to enter.
           */
           if (  RTEMS_RFS_S_ISDIR (  rtems_rfs_inode_get_mode (  &inode ) ) &&
           !rtems_rfs_rtems_eval_perms (  &inode,   RTEMS_LIBIO_PERMS_SEARCH ) )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_for_make: eval perms",   EACCES );
           }
          
           /*
           * Is this the end of the pathname we where given ?
           */
           if (  path == *name )
           break;
          
           /*
           * Extract the node name we will look for this time around.
           */
           node = path;
           node_len = 0;
           while (  !rtems_filesystem_is_separator(  *path ) &&
           (  *path != '\0' ) &&
           (  node_len < (  rtems_rfs_fs_max_name (  fs ) - 1 ) ) )
           {
           node_len++;
           path++;
           }
          
           /*
           * Eat any separators at start of the new path.
           */
           stripped = rtems_filesystem_prefix_separators (  path,   strlen (  path ) );
           path += stripped;
           node_len += stripped;
          
           /*
           * If the node is the current directory and there is more path to come move
           * on it else we are at the inode we want.
           */
           if (  rtems_rfs_current_dir (  node ) )
           {
           if (  *path )
           continue;
           break;
           }
          
           /*
           * If the node is a parent we must move up one directory. If the location
           * is on another file system we have a crossmount so we call that file
           * system to handle the remainder of the path.
           */
           if (  rtems_rfs_parent_dir (  path ) )
           {
           /*
           * If we are at the root inode of the file system we have a crossmount
           * path.
           */
           if (  ino == RTEMS_RFS_ROOT_INO )
           {
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE ) )
           printf(  "rtems-rfs-rtems: eval-for-make: crossmount: path:%s\n",  
           path - node_len );
          
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           *pathloc = pathloc->mt_entry->mt_point_node;
           return (  *pathloc->ops->evalformake_h )(  path - node_len,   pathloc,   name );
           }
          
           /*
           * If not a directory give and up return. We cannot change dir from a
           * regular file or device node.
           */
           if (  !RTEMS_RFS_S_ISDIR (  rtems_rfs_inode_get_mode (  &inode ) ) )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_for_make: not dir",   ENOTSUP );
           }
          
           /*
           * We need to find the parent of this node.
           */
           rc = rtems_rfs_dir_lookup_ino (  fs,   &inode,   "..",   2,   &ino,   &doff );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_for_make: read parent inode",   rc );
           }
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE ) )
           printf (  "rtems-rfs-rtems: eval-for-make: parent: ino:%" PRId32 "\n",   ino );
           }
           else
           {
           /*
           * Read the inode so we know it exists and what type it is.
           */
           rc = rtems_rfs_dir_lookup_ino (  fs,   &inode,  
           node,   node_len - stripped,   &ino,   &doff );
           if (  rc > 0 )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_for_make: reading inode",   rc );
           }
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE ) )
           printf(  "rtems-rfs-rtems: eval-for-make: down: path:%s ino:%" PRId32 "\n",  
           node,   ino );
           }
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_for_make: closing node",   rc );
           }
           }
          
           if (  !RTEMS_RFS_S_ISDIR (  rtems_rfs_inode_get_mode (  &inode ) ) )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_for_make: not dir",   ENOTDIR );
           }
          
           if (  !rtems_rfs_rtems_eval_perms (  &inode,   RTEMS_LIBIO_PERMS_WX ) )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_for_make: cannot write",   EACCES );
           }
          
           /*
           * Make sure the name does not already exists in the directory.
           */
           rc = rtems_rfs_dir_lookup_ino (  fs,   &inode,   *name,   strlen (  *name ),  
           &node_ino,   &doff );
           if (  rc == 0 )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_for_make: found name",   EEXIST );
           }
          
           if (  rc != ENOENT )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "eval_for_make: look up",   rc );
           }
          
           /*
           * Set the parent ino in the path location.
           */
          
           rtems_rfs_rtems_set_pathloc_ino (  pathloc,   ino );
           rtems_rfs_rtems_set_pathloc_doff (  pathloc,   doff );
          
           rc = rtems_rfs_rtems_set_handlers (  pathloc,   &inode ) ? 0 : EIO;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE ) )
           printf(  "rtems-rfs-rtems: eval-for-make: parent ino:%" PRId32 " name:%s\n",  
           ino,   *name );
          
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
          
           return rc;
          }
          
          /**
           * The following rouine creates a new link node under parent with the name
           * given in name. The link node is set to point to the node at to_loc.
           *
           * @param to_loc
           * @param parent_loc
           * @param name
           * @return int
           */
          int
     479  rtems_rfs_rtems_link (  rtems_filesystem_location_info_t* to_loc,  
           rtems_filesystem_location_info_t* parent_loc,  
           const char* name )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  to_loc );
           rtems_rfs_ino target = rtems_rfs_rtems_get_pathloc_ino (  to_loc );
           rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (  parent_loc );
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_LINK ) )
           printf (  "rtems-rfs-rtems: link: in: parent:%" PRId32 " target:%" PRId32 "\n",  
           parent,   target );
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_link (  fs,   name,   strlen (  name ),   parent,   target,   false );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "link: linking",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
          
           return 0;
          }
          
          /**
           * Routine to remove a link node from the file system.
           *
           * @param parent_loc
           * @param loc
           * @return int
           */
          
          int
     515  rtems_rfs_rtems_unlink (  rtems_filesystem_location_info_t* parent_loc,  
           rtems_filesystem_location_info_t* loc )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  parent_loc );
           rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (  parent_loc );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (  loc );
           uint32_t doff = rtems_rfs_rtems_get_pathloc_doff (  loc );
           int rc;
          
           rtems_rfs_rtems_lock (  fs );
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_UNLINK ) )
           printf(  "rtems-rfs-rtems: unlink: parent:%" PRId32 " doff:%" PRIu32 " ino:%" PRId32 "\n",  
           parent,   doff,   ino );
          
           rc = rtems_rfs_unlink (  fs,   parent,   ino,   doff,   rtems_rfs_unlink_dir_denied );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "unlink: unlink inode",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
          
           return 0;
          }
          
          /**
           * The following verifies that and returns the type of node that the loc refers
           * to.
           *
           * @param pathloc
           * @return rtems_filesystem_node_types_t
           */
          
          rtems_filesystem_node_types_t
     551  rtems_rfs_rtems_node_type (  rtems_filesystem_location_info_t* pathloc )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (  pathloc );
           rtems_filesystem_node_types_t type;
           rtems_rfs_inode_handle inode;
           uint16_t mode;
           int rc;
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "node_type: opening inode",   rc );
           }
          
           /*
           * Do not return RTEMS_FILESYSTEM_HARD_LINK because this would result in an
           * eval link which does not make sense in the case of the RFS file
           * system. All directory entries are links to an inode. A link such as a HARD
           * link is actually the normal path to a regular file,   directory,   device
           * etc's inode. Links to inodes can be considered "the real" one,   yet they
           * are all links.
           */
           mode = rtems_rfs_inode_get_mode (  &inode );
           if (  RTEMS_RFS_S_ISDIR (  mode ) )
           type = RTEMS_FILESYSTEM_DIRECTORY;
           else if (  RTEMS_RFS_S_ISLNK (  mode ) )
           type = RTEMS_FILESYSTEM_SYM_LINK;
           else if (  RTEMS_RFS_S_ISBLK (  mode ) || RTEMS_RFS_S_ISCHR (  mode ) )
           type = RTEMS_FILESYSTEM_DEVICE;
           else
           type = RTEMS_FILESYSTEM_MEMORY_FILE;
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "node_type: closing inode",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
          
           return type;
          }
          
          /**
           * This routine is the implementation of the chown(   ) system call for the
           * RFS.
           *
           * @param pathloc
           * @param owner
           * @param group
           * return int
           */
          
          static int
     610  rtems_rfs_rtems_chown (  rtems_filesystem_location_info_t *pathloc,  
           uid_t owner,  
           gid_t group )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (  pathloc );
           rtems_rfs_inode_handle inode;
          #if defined (  RTEMS_POSIX_API )
           uid_t uid;
          #endif
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_CHOWN ) )
           printf (  "rtems-rfs-rtems: chown: in: ino:%" PRId32 " uid:%d gid:%d\n",  
           ino,   owner,   group );
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "chown: opening inode",   rc );
           }
          
           /*
           * Verify I am the owner of the node or the super user.
           */
          
          #if defined (  RTEMS_POSIX_API )
           uid = geteuid(   );
          
           if (  (  uid != rtems_rfs_inode_get_uid (  &inode ) ) && (  uid != 0 ) )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "chown: not able",   EPERM );
           }
          #endif
          
           rtems_rfs_inode_set_uid_gid (  &inode,   owner,   group );
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "chown: closing inode",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
          
           return 0;
          }
          
          /**
           * This routine is the implementation of the utime(   ) system call for the
           * RFS.
           *
           * @param pathloc
           * @param atime
           * @param mtime
           * return int
           */
          
          int
     675  rtems_rfs_rtems_utime(  rtems_filesystem_location_info_t* pathloc,  
           time_t atime,  
           time_t mtime )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (  pathloc );
           rtems_rfs_inode_handle inode;
           int rc;
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "utime: read inode",   rc );
           }
          
           rtems_rfs_inode_set_atime (  &inode,   atime );
           rtems_rfs_inode_set_mtime (  &inode,   mtime );
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "utime: closing inode",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
          
           return 0;
          }
          
          /**
           * The following rouine creates a new symbolic link node under parent with the
           * name given in name. The node is set to point to the node at to_loc.
           *
           * @param parent_loc
           * @param link_name
           * @param node_name
           * return int
           */
          
          int
     719  rtems_rfs_rtems_symlink (  rtems_filesystem_location_info_t* parent_loc,  
           const char* link_name,  
           const char* node_name )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  parent_loc );
           rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (  parent_loc );
           uid_t uid;
           gid_t gid;
           int rc;
          
          #if defined(  RTEMS_POSIX_API )
           uid = geteuid (   );
           gid = getegid (   );
          #else
           uid = 0;
           gid = 0;
          #endif
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_symlink (  fs,   node_name,   strlen (  node_name ),  
           link_name,   strlen (  link_name ),  
           uid,   gid,   parent );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "symlink: linking",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
          
           return 0;
          }
          
          /**
           * The following rouine puts the symblic links destination name into buf.
           *
           * @param loc
           * @param buf
           * @param bufsize
           * @return int
           */
          
          ssize_t
     763  rtems_rfs_rtems_readlink (  rtems_filesystem_location_info_t* pathloc,  
           char* buf,  
           size_t bufsize )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (  pathloc );
           size_t length;
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_READLINK ) )
           printf (  "rtems-rfs-rtems: readlink: in: ino:%" PRId32 "\n",   ino );
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_symlink_read (  fs,   ino,   buf,   bufsize,   &length );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "readlink: reading link",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
          
           return (  int ) length;
          }
          
          /**
           * File change mode routine.
           *
           * @param pathloc
           * @param mode
           * @return int
           */
          int
     797  rtems_rfs_rtems_fchmod (  rtems_filesystem_location_info_t* pathloc,  
           mode_t mode )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (  pathloc );
           rtems_rfs_inode_handle inode;
           uint16_t imode;
          #if defined (  RTEMS_POSIX_API )
           uid_t uid;
          #endif
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_FCHMOD ) )
           printf (  "rtems-rfs-rtems: fchmod: in: ino:%" PRId32 " mode:%06" PRIomode_t "\n",  
           ino,   mode );
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "fchmod: opening inode",   rc );
           }
          
           imode = rtems_rfs_inode_get_mode (  &inode );
          
           /*
           * Verify I am the owner of the node or the super user.
           */
          #if defined (  RTEMS_POSIX_API )
           uid = geteuid(   );
          
           if (  (  uid != rtems_rfs_inode_get_uid (  &inode ) ) && (  uid != 0 ) )
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "fchmod: not owner",   EPERM );
           }
          #endif
          
           imode &= ~(  S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX );
           imode |= mode & (  S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX );
          
           rtems_rfs_inode_set_mode (  &inode,   imode );
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "fchmod: closing inode",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
          
           return 0;
          }
          
          /**
           * The following routine does a stat on a node.
           *
           * @param pathloc
           * @param buf
           * @return int
           */
          
          int
     864  rtems_rfs_rtems_stat (  rtems_filesystem_location_info_t* pathloc,  
           struct stat* buf )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (  pathloc );
           rtems_rfs_inode_handle inode;
           rtems_rfs_file_shared* shared;
           uint16_t mode;
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_STAT ) )
           printf (  "rtems-rfs-rtems: stat: in: ino:%" PRId32 "\n",   ino );
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "stat: opening inode",   rc );
           }
          
           mode = rtems_rfs_inode_get_mode (  &inode );
          
           if (  RTEMS_RFS_S_ISCHR (  mode ) || RTEMS_RFS_S_ISBLK (  mode ) )
           {
           buf->st_rdev =
           rtems_filesystem_make_dev_t (  rtems_rfs_inode_get_block (  &inode,   0 ),  
           rtems_rfs_inode_get_block (  &inode,   1 ) );
           }
          
           buf->st_dev = rtems_rfs_fs_device (  fs );
           buf->st_ino = ino;
           buf->st_mode = rtems_rfs_rtems_mode (  mode );
           buf->st_nlink = rtems_rfs_inode_get_links (  &inode );
           buf->st_uid = rtems_rfs_inode_get_uid (  &inode );
           buf->st_gid = rtems_rfs_inode_get_gid (  &inode );
          
           /*
           * Need to check is the ino is an open file. If so we take the values from
           * the open file rather than the inode.
           */
           shared = rtems_rfs_file_get_shared (  fs,   ino );
          
           if (  shared )
           {
           buf->st_atime = rtems_rfs_file_shared_get_atime (  shared );
           buf->st_mtime = rtems_rfs_file_shared_get_mtime (  shared );
           buf->st_ctime = rtems_rfs_file_shared_get_ctime (  shared );
           buf->st_blocks = rtems_rfs_file_shared_get_block_count (  shared );
          
           if (  S_ISLNK (  buf->st_mode ) )
           buf->st_size = rtems_rfs_file_shared_get_block_offset (  shared );
           else
           buf->st_size = rtems_rfs_file_shared_get_size (  fs,   shared );
           }
           else
           {
           buf->st_atime = rtems_rfs_inode_get_atime (  &inode );
           buf->st_mtime = rtems_rfs_inode_get_mtime (  &inode );
           buf->st_ctime = rtems_rfs_inode_get_ctime (  &inode );
           buf->st_blocks = rtems_rfs_inode_get_block_count (  &inode );
          
           if (  S_ISLNK (  buf->st_mode ) )
           buf->st_size = rtems_rfs_inode_get_block_offset (  &inode );
           else
           buf->st_size = rtems_rfs_inode_get_size (  fs,   &inode );
           }
          
           buf->st_blksize = rtems_rfs_fs_block_size (  fs );
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "stat: closing inode",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
           return 0;
          }
          
          /**
           * Routine to create a node in the RFS file system.
           *
           * @param name
           * @param mode
           * @param dev
           * @param pathloc
           * @return int
           */
          
          int
     957  rtems_rfs_rtems_mknod (  const char *name,  
           mode_t mode,  
           dev_t dev,  
           rtems_filesystem_location_info_t *pathloc )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (  pathloc );
           rtems_rfs_ino ino;
           rtems_rfs_inode_handle inode;
           uid_t uid;
           gid_t gid;
           int rc;
          
          #if defined(  RTEMS_POSIX_API )
           uid = geteuid (   );
           gid = getegid (   );
          #else
           uid = 0;
           gid = 0;
          #endif
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_inode_create (  fs,   parent,   name,   strlen (  name ),  
           rtems_rfs_rtems_imode (  mode ),  
           1,   uid,   gid,   &ino );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "mknod: inode create",   rc );
           }
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "mknod: inode open",   rc );
           }
          
           if (  S_ISDIR(  mode ) || S_ISREG(  mode ) )
           {
           }
           else if (  S_ISCHR (  mode ) || S_ISBLK (  mode ) )
           {
           int major;
           int minor;
           rtems_filesystem_split_dev_t (  dev,   major,   minor );
           rtems_rfs_inode_set_block (  &inode,   0,   major );
           rtems_rfs_inode_set_block (  &inode,   1,   minor );
           }
           else
           {
           rtems_rfs_inode_close (  fs,   &inode );
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "mknod: bad mode",   EINVAL );
           }
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc > 0 )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "mknod: closing inode",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
           return 0;
          }
          
          /**
           * Routine to remove a node from the RFS file system.
           *
           * @param parent_pathloc
           * @param pathloc
           * @return int
           */
          int
    1033  rtems_rfs_rtems_rmnod (  rtems_filesystem_location_info_t* parent_pathloc,  
           rtems_filesystem_location_info_t* pathloc )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (  parent_pathloc );
           rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (  pathloc );
           uint32_t doff = rtems_rfs_rtems_get_pathloc_doff (  pathloc );
           int rc;
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_RMNOD ) )
           printf (  "rtems-rfs: rmnod: parent:%" PRId32 " doff:%" PRIu32 ",   ino:%" PRId32 "\n",  
           parent,   doff,   ino );
          
           rtems_rfs_rtems_lock (  fs );
          
           rc = rtems_rfs_unlink (  fs,   parent,   ino,   doff,   rtems_rfs_unlink_dir_denied );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "rmnod: unlinking",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
           return 0;
          }
          
          /**
           * The following routine does a sync on an inode node. Currently it flushes
           * everything related to this device.
           *
           * @param iop
           * @return int
           */
          int
    1067  rtems_rfs_rtems_fdatasync (  rtems_libio_t* iop )
          {
           int rc;
          
           rc = rtems_rfs_buffer_sync (  rtems_rfs_rtems_pathloc_dev (  &iop->pathinfo ) );
           if (  rc )
           return rtems_rfs_rtems_error (  "fdatasync: sync",   rc );
          
           return 0;
          }
          
          /**
           * Rename the node.
           *
           * @param old_parent_loc The old name's parent location.
           * @param old_loc The old name's location.
           * @param new_parent_loc The new name's parent location.
           * @param new_name The new name.
           * @return int
           */
          int
    1088  rtems_rfs_rtems_rename(  rtems_filesystem_location_info_t* old_parent_loc,  
           rtems_filesystem_location_info_t* old_loc,  
           rtems_filesystem_location_info_t* new_parent_loc,  
           const char* new_name )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  old_loc );
           rtems_rfs_ino old_parent;
           rtems_rfs_ino new_parent;
           rtems_rfs_ino ino;
           uint32_t doff;
           int rc;
          
           old_parent = rtems_rfs_rtems_get_pathloc_ino (  old_parent_loc );
           new_parent = rtems_rfs_rtems_get_pathloc_ino (  new_parent_loc );
          
           ino = rtems_rfs_rtems_get_pathloc_ino (  old_loc );
           doff = rtems_rfs_rtems_get_pathloc_doff (  old_loc );
          
           if (  rtems_rfs_rtems_trace (  RTEMS_RFS_RTEMS_DEBUG_RENAME ) )
           printf (  "rtems-rfs: rename: ino:%" PRId32 " doff:%" PRIu32 ",   new parent:%" PRId32 " new name:%s\n",  
           ino,   doff,   new_parent,   new_name );
          
           rtems_rfs_rtems_lock (  fs );
          
           /*
           * Link to the inode before unlinking so the inode is not erased when
           * unlinked.
           */
           rc = rtems_rfs_link (  fs,   new_name,   strlen (  new_name ),   new_parent,   ino,   true );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "rename: linking",   rc );
           }
          
           /*
           * Unlink all inodes even directories with the dir option as false because a
           * directory may not be empty.
           */
           rc = rtems_rfs_unlink (  fs,   old_parent,   ino,   doff,  
           rtems_rfs_unlink_dir_allowed );
           if (  rc )
           {
           rtems_rfs_rtems_unlock (  fs );
           return rtems_rfs_rtems_error (  "rename: unlinking",   rc );
           }
          
           rtems_rfs_rtems_unlock (  fs );
          
           return 0;
          }
          
          /**
           * Return the file system stat data.
           *
           * @param pathloc
           * @param sb
           * @return int
           */
          int
    1148  rtems_rfs_rtems_statvfs (  rtems_filesystem_location_info_t* pathloc,  
           struct statvfs* sb )
          {
           rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (  pathloc );
           size_t blocks;
           size_t inodes;
          
           rtems_rfs_group_usage (  fs,   &blocks,   &inodes );
          
           sb->f_bsize = rtems_rfs_fs_block_size (  fs );
           sb->f_frsize = rtems_rfs_fs_media_block_size (  fs );
           sb->f_blocks = rtems_rfs_fs_media_blocks (  fs );
           sb->f_bfree = rtems_rfs_fs_blocks (  fs ) - blocks;
           sb->f_bavail = sb->f_bfree;
           sb->f_files = rtems_rfs_fs_inodes (  fs );
           sb->f_ffree = rtems_rfs_fs_inodes (  fs ) - inodes;
           sb->f_favail = sb->f_ffree;
           sb->f_fsid = RTEMS_RFS_SB_MAGIC;
           sb->f_flag = rtems_rfs_fs_flags (  fs );
           sb->f_namemax = rtems_rfs_fs_max_name (  fs );
          
           return 0;
          }
          
          /**
           * Handler table for RFS link nodes
           */
          const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers =
          {
           .open_h = rtems_filesystem_default_open,  
           .close_h = rtems_filesystem_default_close,  
           .read_h = rtems_filesystem_default_read,  
           .write_h = rtems_filesystem_default_write,  
           .ioctl_h = rtems_filesystem_default_ioctl,  
           .lseek_h = rtems_filesystem_default_lseek,  
           .fstat_h = rtems_rfs_rtems_stat,  
           .fchmod_h = rtems_filesystem_default_fchmod,  
           .ftruncate_h = rtems_filesystem_default_ftruncate,  
           .fpathconf_h = rtems_filesystem_default_fpathconf,  
           .fsync_h = rtems_filesystem_default_fsync,  
           .fdatasync_h = rtems_filesystem_default_fdatasync,  
           .fcntl_h = rtems_filesystem_default_fcntl,  
           .rmnod_h = rtems_rfs_rtems_rmnod
          };
          
          /**
           * Forward decl for the ops table.
           */
          
    1197  int rtems_rfs_rtems_initialise (  rtems_filesystem_mount_table_entry_t *mt_entry,  
           const void *data );
    1199  int rtems_rfs_rtems_shutdown (  rtems_filesystem_mount_table_entry_t *mt_entry );
          
          /**
           * RFS file system operations table.
           */
          const rtems_filesystem_operations_table rtems_rfs_ops =
          {
           .evalpath_h = rtems_rfs_rtems_eval_path,  
           .evalformake_h = rtems_rfs_rtems_eval_for_make,  
           .link_h = rtems_rfs_rtems_link,  
           .unlink_h = rtems_rfs_rtems_unlink,  
           .node_type_h = rtems_rfs_rtems_node_type,  
           .mknod_h = rtems_rfs_rtems_mknod,  
           .chown_h = rtems_rfs_rtems_chown,  
           .freenod_h = rtems_filesystem_default_freenode,  
           .mount_h = rtems_filesystem_default_mount,  
           .fsmount_me_h = rtems_rfs_rtems_initialise,  
           .unmount_h = rtems_filesystem_default_unmount,  
           .fsunmount_me_h = rtems_rfs_rtems_shutdown,  
           .utime_h = rtems_rfs_rtems_utime,  
           .eval_link_h = rtems_filesystem_default_evaluate_link,   /* never called cause we lie in the node type */
           .symlink_h = rtems_rfs_rtems_symlink,  
           .readlink_h = rtems_rfs_rtems_readlink,  
           .rename_h = rtems_rfs_rtems_rename,  
           .statvfs_h = rtems_rfs_rtems_statvfs
          };
          
          /**
           * Open the file system.
           */
          
          int
    1231  rtems_rfs_rtems_initialise (  rtems_filesystem_mount_table_entry_t* mt_entry,  
           const void* data )
          {
           rtems_rfs_rtems_private* rtems;
           rtems_rfs_file_system* fs;
           int rc;
          
           rtems = malloc (  sizeof (  rtems_rfs_rtems_private ) );
           if (  !rtems )
           return rtems_rfs_rtems_error (  "initialise: local data",   ENOMEM );
          
           memset (  rtems,   0,   sizeof (  rtems_rfs_rtems_private ) );
          
           rc = rtems_rfs_mutex_create (  &rtems->access );
           if (  rc > 0 )
           {
           free (  rtems );
           return rtems_rfs_rtems_error (  "initialise: cannot create mutex",   rc );
           }
          
           rc = rtems_rfs_mutex_lock (  &rtems->access );
           if (  rc > 0 )
           {
           rtems_rfs_mutex_destroy (  &rtems->access );
           free (  rtems );
           return rtems_rfs_rtems_error (  "initialise: cannot lock access mutex",   rc );
           }
          
           rc = rtems_rfs_fs_open (  mt_entry->dev,   rtems,   0,   &fs );
           if (  rc )
           {
           free (  rtems );
           return rtems_rfs_rtems_error (  "initialise: open",   rc );
           }
          
           mt_entry->fs_info = fs;
          
           mt_entry->mt_fs_root.node_access = (  void* ) RTEMS_RFS_ROOT_INO;
           mt_entry->mt_fs_root.handlers = &rtems_rfs_rtems_dir_handlers;
           mt_entry->mt_fs_root.ops = &rtems_rfs_ops;
          
           rtems_rfs_rtems_unlock (  fs );
          
           return 0;
          }
          
          /**
           * Shutdown the file system.
           */
          int
    1281  rtems_rfs_rtems_shutdown (  rtems_filesystem_mount_table_entry_t* mt_entry )
          {
           rtems_rfs_file_system* fs = mt_entry->fs_info;
           rtems_rfs_rtems_private* rtems;
           int rc;
          
           rtems = rtems_rfs_fs_user (  fs );
          
           rc = rtems_rfs_fs_close(  fs );
          
           rtems_rfs_mutex_destroy (  &rtems->access );
           free (  rtems );
          
           return rtems_rfs_rtems_error (  "shutdown: close",   rc );
          }

libfs/src/rfs/rtems-rfs-shell.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-shell.c,  v 1.11 2010/10/11 04:34:48 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Shell Commands Support
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          #include <string.h>
          
          #include <rtems/rfs/rtems-rfs-block.h>
          #include <rtems/rfs/rtems-rfs-buffer.h>
          #include <rtems/rfs/rtems-rfs-group.h>
          #include <rtems/rfs/rtems-rfs-inode.h>
          #include <rtems/rfs/rtems-rfs-dir.h>
          #include <rtems/rtems-rfs-format.h>
          
          #include <sys/statvfs.h>
          
          #if __rtems__
          #include "rtems-rfs-rtems.h"
          #endif
          
          /**
           * The type of the shell handlers we have.
           */
          typedef int (  *rtems_rfs_shell_handler ) (  rtems_rfs_file_system* fs,   int argc,   char *argv[] );
          
          /**
           * Table of handlers we parse to invoke the command.
           */
          typedef struct
          {
           const char* name;
           rtems_rfs_shell_handler handler;
           const char* help;
          } rtems_rfs_shell_cmd;
          
          /**
           * Lock the file system.
           */
          static void
      57  rtems_rfs_shell_lock_rfs (  rtems_rfs_file_system* fs )
          {
          #if __rtems__
           rtems_rfs_rtems_lock (  fs );
          #endif
          }
          
          /**
           * Unlock the file system.
           */
          static void
      68  rtems_rfs_shell_unlock_rfs (  rtems_rfs_file_system* fs )
          {
          #if __rtems__
           rtems_rfs_rtems_unlock (  fs );
          #endif
          }
          
          /**
           * Get the file system data from the specific path. Checks to make sure the path is
           * pointing to a valid RFS file system.
           */
          static int
      80  rtems_rfs_get_fs (  const char* path,   rtems_rfs_file_system** fs )
          {
           struct statvfs sb;
           int rc;
          
           rc = statvfs (  path,   &sb );
           if (  rc < 0 )
           {
           printf (  "error: cannot statvfs path: %s: (  %d ) %s\n",  
           path,   errno,   strerror (  errno ) );
           return -1;
           }
          
           if (  sb.f_fsid != RTEMS_RFS_SB_MAGIC )
           {
           printf (  "error: path '%s' is not on an RFS file system\n",   path );
           return -1;
           }
          
          #if __rtems__
           /*
           * Now find the path location on the file system. This will give the file
           * system data.
           */
           {
           rtems_filesystem_location_info_t pathloc;
           rc = rtems_filesystem_evaluate_path (  path,   strlen (  path ),   0,   &pathloc,   true );
           *fs = rtems_rfs_rtems_pathloc_dev (  &pathloc );
           rtems_filesystem_freenode (  &pathloc );
           }
          #endif
          
           return rc;
          }
          
          static int
     116  rtems_rfs_shell_data (  rtems_rfs_file_system* fs,   int argc,   char *argv[] )
          {
           size_t blocks;
           size_t inodes;
           int bpcent;
           int ipcent;
          
           printf (  "RFS Filesystem Data\n" );
           printf (  " flags: %08" PRIx32 "\n",   fs->flags );
          #if 0
           printf (  " device: %08lx\n",   rtems_rfs_fs_device (  fs ) );
          #endif
           printf (  " blocks: %zu\n",   rtems_rfs_fs_blocks (  fs ) );
           printf (  " block size: %zu\n",   rtems_rfs_fs_block_size (  fs ) );
           printf (  " size: %" PRIu64 "\n",   rtems_rfs_fs_size (  fs ) );
           printf (  " media block size: %" PRIu32 "\n",   rtems_rfs_fs_media_block_size (  fs ) );
           printf (  " media size: %" PRIu64 "\n",   rtems_rfs_fs_media_size (  fs ) );
           printf (  " inodes: %" PRIu32 "\n",   rtems_rfs_fs_inodes (  fs ) );
           printf (  " bad blocks: %" PRIu32 "\n",   fs->bad_blocks );
           printf (  " max. name length: %" PRIu32 "\n",   rtems_rfs_fs_max_name (  fs ) );
           printf (  " groups: %d\n",   fs->group_count );
           printf (  " group blocks: %zd\n",   fs->group_blocks );
           printf (  " group inodes: %zd\n",   fs->group_inodes );
           printf (  " inodes per block: %zd\n",   fs->inodes_per_block );
           printf (  " blocks per block: %zd\n",   fs->blocks_per_block );
           printf (  " singly blocks: %zd\n",   fs->block_map_singly_blocks );
           printf (  " doublly blocks: %zd\n",   fs->block_map_doubly_blocks );
           printf (  " max. held buffers: %" PRId32 "\n",   fs->max_held_buffers );
          
           rtems_rfs_shell_lock_rfs (  fs );
          
           rtems_rfs_group_usage (  fs,   &blocks,   &inodes );
          
           rtems_rfs_shell_unlock_rfs (  fs );
          
           bpcent = (  blocks * 1000 ) / rtems_rfs_fs_blocks (  fs );
           ipcent = (  inodes * 1000 ) / rtems_rfs_fs_inodes (  fs );
          
           printf (  " blocks used: %zd (  %d.%d%% )\n",  
           blocks,   bpcent / 10,   bpcent % 10 );
           printf (  " inodes used: %zd (  %d.%d%% )\n",  
           inodes,   ipcent / 10,   ipcent % 10 );
          
           return 0;
          }
          
          static int
     163  rtems_rfs_shell_block (  rtems_rfs_file_system* fs,   int argc,   char *argv[] )
          {
           rtems_rfs_buffer_handle buffer;
           rtems_rfs_block_no block;
           uint8_t* data;
           bool state;
           int b;
           int rc;
          
           if (  argc <= 1 )
           {
           printf (  "error: no block number provided\n" );
           return 1;
           }
          
           block = strtoul (  argv[1],   0,   0 );
          
           rtems_rfs_shell_lock_rfs (  fs );
          
           rc = rtems_rfs_group_bitmap_test (  fs,   false,   block,   &state );
           if (  rc > 0 )
           {
           rtems_rfs_shell_unlock_rfs (  fs );
           printf (  "error: testing block state: block=%" PRIu32 ": (  %d ) %s\n",  
           block,   rc,   strerror (  rc ) );
           return 1;
           }
          
           printf (  " %5" PRIu32 ": block %s\n",   block,   state ? "allocated" : "free" );
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_shell_unlock_rfs (  fs );
           printf (  "error: opening buffer handle: block=%" PRIu32 ": (  %d ) %s\n",  
           block,   rc,   strerror (  rc ) );
           return 1;
           }
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &buffer,   block,   true );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &buffer );
           rtems_rfs_shell_unlock_rfs (  fs );
           printf (  "error: requesting buffer handle: block=%" PRIu32 ": (  %d ) %s\n",  
           block,   rc,   strerror (  rc ) );
           return 1;
           }
          
           for (  b = 0,   data = rtems_rfs_buffer_data (  &buffer );
           b < rtems_rfs_fs_block_size (  fs );
           b++,   data++ )
           {
           int mod = b % 16;
           if (  mod == 0 )
           {
           if (  b )
           printf (  "\n" );
           printf (  "%04x ",   b );
           }
           if (  mod == 8 )
           printf (  " " );
           printf (  "%02x ",   *data );
           }
          
           printf (  "\n" );
          
           rc = rtems_rfs_buffer_handle_close (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_shell_unlock_rfs (  fs );
           printf (  "error: closing buffer handle: block=%" PRIu32 ": (  %d ) %s\n",  
           block,   rc,   strerror (  rc ) );
           return 1;
           }
          
           rtems_rfs_shell_unlock_rfs (  fs );
          
           return 0;
          }
          
          static int
     245  rtems_rfs_shell_inode (  rtems_rfs_file_system* fs,   int argc,   char *argv[] )
          {
           rtems_rfs_ino start;
           rtems_rfs_ino end;
           rtems_rfs_ino total;
           rtems_rfs_ino ino;
           bool show_all;
           bool error_check_only;
           bool forced;
           bool have_start;
           bool have_end;
           int arg;
           int b;
           int rc;
          
           total = fs->group_inodes * fs->group_count;
           start = RTEMS_RFS_ROOT_INO;
           end = total - 1;
           show_all = false;
           error_check_only = false;
           forced = false;
           have_start = have_end = false;
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           switch (  argv[arg][1] )
           {
           case 'a':
           show_all = true;
           break;
           case 'e':
           error_check_only = true;
           break;
           case 'f':
           forced = true;
           break;
           default:
           printf (  "warning: option ignored: %s\n",   argv[arg] );
           break;
           }
           }
           else
           {
           if (  have_end && have_start )
           printf (  "warning: option ignored: %s\n",   argv[arg] );
           else if (  !have_start )
           {
           start = end = strtoul (  argv[arg],   0,   0 );
           have_start = true;
           }
           else
           {
           end = strtoul (  argv[arg],   0,   0 );
           have_end = true;
           }
           }
           }
          
           if (  (  start >= total ) || (  end >= total ) )
           {
           printf (  "error: inode out of range (  0->%" PRId32 " ).\n",   total - 1 );
           return 1;
           }
          
           rtems_rfs_shell_lock_rfs (  fs );
          
           for (  ino = start; ino <= end; ino++ )
           {
           rtems_rfs_inode_handle inode;
           bool allocated;
          
           rc = rtems_rfs_group_bitmap_test (  fs,   true,   ino,   &allocated );
           if (  rc > 0 )
           {
           rtems_rfs_shell_unlock_rfs (  fs );
           printf (  "error: testing inode state: ino=%" PRIu32 ": (  %d ) %s\n",  
           ino,   rc,   strerror (  rc ) );
           return 1;
           }
          
           if (  show_all || allocated )
           {
           uint16_t mode;
           bool error;
          
           rc = rtems_rfs_inode_open (  fs,   ino,   &inode,   true );
           if (  rc > 0 )
           {
           rtems_rfs_shell_unlock_rfs (  fs );
           printf (  "error: opening inode handle: ino=%" PRIu32 ": (  %d ) %s\n",  
           ino,   rc,   strerror (  rc ) );
           return 1;
           }
          
           error = false;
          
           mode = rtems_rfs_inode_get_mode (  &inode );
          
           if (  error_check_only )
           {
           if (  !RTEMS_RFS_S_ISDIR (  mode ) &&
           !RTEMS_RFS_S_ISCHR (  mode ) &&
           !RTEMS_RFS_S_ISBLK (  mode ) &&
           !RTEMS_RFS_S_ISREG (  mode ) &&
           !RTEMS_RFS_S_ISLNK (  mode ) )
           error = true;
           else
           {
          #if NEED_TO_HANDLE_DIFFERENT_TYPES
           int b;
           for (  b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++ )
           {
           uint32_t block;
           block = rtems_rfs_inode_get_block (  &inode,   b );
           if (  (  block <= RTEMS_RFS_SUPERBLOCK_SIZE ) ||
           (  block >= rtems_rfs_fs_blocks (  fs ) ) )
           error = true;
           }
          #endif
           }
           }
          
           if (  !error_check_only || error )
           {
           printf (  " %5" PRIu32 ": pos=%06" PRIu32 ":%04zx %c ",  
           ino,   rtems_rfs_buffer_bnum (  &inode.buffer ),  
           inode.offset * RTEMS_RFS_INODE_SIZE,  
           allocated ? 'A' : 'F' );
          
           if (  !allocated && !forced )
           printf (  " --\n" );
           else
           {
           const char* type;
           type = "UKN";
           if (  RTEMS_RFS_S_ISDIR (  mode ) )
           type = "DIR";
           else if (  RTEMS_RFS_S_ISCHR (  mode ) )
           type = "CHR";
           else if (  RTEMS_RFS_S_ISBLK (  mode ) )
           type = "BLK";
           else if (  RTEMS_RFS_S_ISREG (  mode ) )
           type = "REG";
           else if (  RTEMS_RFS_S_ISLNK (  mode ) )
           type = "LNK";
           printf (  "links=%03i mode=%04x (  %s/%03o ) bo=%04u bc=%04" PRIu32 " b=[",  
           rtems_rfs_inode_get_links (  &inode ),  
           mode,   type,   mode & (  (  1 << 10 ) - 1 ),  
           rtems_rfs_inode_get_block_offset (  &inode ),  
           rtems_rfs_inode_get_block_count (  &inode ) );
           for (  b = 0; b < (  RTEMS_RFS_INODE_BLOCKS - 1 ); b++ )
           printf (  "%" PRIu32 " ",   rtems_rfs_inode_get_block (  &inode,   b ) );
           printf (  "%" PRIu32 "]\n",   rtems_rfs_inode_get_block (  &inode,   b ) );
           }
           }
          
           rc = rtems_rfs_inode_close (  fs,   &inode );
           if (  rc > 0 )
           {
           rtems_rfs_shell_unlock_rfs (  fs );
           printf (  "error: closing inode handle: ino=%" PRIu32 ": (  %d ) %s\n",  
           ino,   rc,   strerror (  rc ) );
           return 1;
           }
           }
           }
          
           rtems_rfs_shell_unlock_rfs (  fs );
          
           return 0;
          }
          
          static int
     420  rtems_rfs_shell_dir (  rtems_rfs_file_system* fs,   int argc,   char *argv[] )
          {
           rtems_rfs_buffer_handle buffer;
           rtems_rfs_block_no block;
           uint8_t* data;
           bool state;
           int entry;
           int b;
           int rc;
          
           if (  argc <= 1 )
           {
           printf (  "error: no block number provided\n" );
           return 1;
           }
          
           block = strtoul (  argv[1],   0,   0 );
          
           rtems_rfs_shell_lock_rfs (  fs );
          
           rc = rtems_rfs_group_bitmap_test (  fs,   false,   block,   &state );
           if (  rc > 0 )
           {
           rtems_rfs_shell_unlock_rfs (  fs );
           printf (  "error: testing block state: block=%" PRIu32 ": (  %d ) %s\n",  
           block,   rc,   strerror (  rc ) );
           return 1;
           }
          
           printf (  " %5" PRIu32 ": block %s\n",   block,   state ? "allocated" : "free" );
          
           rc = rtems_rfs_buffer_handle_open (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_shell_unlock_rfs (  fs );
           printf (  "error: opening buffer handle: block=%" PRIu32 ": (  %d ) %s\n",  
           block,   rc,   strerror (  rc ) );
           return 1;
           }
          
           rc = rtems_rfs_buffer_handle_request (  fs,   &buffer,   block,   true );
           if (  rc > 0 )
           {
           rtems_rfs_buffer_handle_close (  fs,   &buffer );
           rtems_rfs_shell_unlock_rfs (  fs );
           printf (  "error: requesting buffer handle: block=%" PRIu32 ": (  %d ) %s\n",  
           block,   rc,   strerror (  rc ) );
           return 1;
           }
          
           b = 0;
           entry = 1;
           data = rtems_rfs_buffer_data (  &buffer );
          
           while (  b < (  rtems_rfs_fs_block_size (  fs ) - RTEMS_RFS_DIR_ENTRY_SIZE - 1 ) )
           {
           rtems_rfs_ino eino;
           int elength;
           int length;
           int c;
          
           eino = rtems_rfs_dir_entry_ino (  data );
           elength = rtems_rfs_dir_entry_length (  data );
          
           if (  elength == RTEMS_RFS_DIR_ENTRY_EMPTY )
           break;
          
           if (  (  elength < RTEMS_RFS_DIR_ENTRY_SIZE ) ||
           (  elength >= rtems_rfs_fs_max_name (  fs ) ) )
           {
           printf (  " %5d: entry length appears corrupt: %d\n",   entry,   elength );
           break;
           }
          
           if (  (  eino < RTEMS_RFS_ROOT_INO ) || (  eino >= rtems_rfs_fs_inodes (  fs ) ) )
           {
           printf (  " %5d: entry ino appears corrupt: ino=%" PRId32 "\n",   entry,   eino );
           break;
           }
          
           length = elength - RTEMS_RFS_DIR_ENTRY_SIZE;
          
           printf (  " %5d: %04x inode=%-6" PRIu32 " hash=%08" PRIx32 " name[%03u]=",  
           entry,   b,  
           rtems_rfs_dir_entry_ino (  data ),  
           rtems_rfs_dir_entry_hash (  data ),  
           length );
          
           if (  length > 50 )
           length = 50;
          
           for (  c = 0; c < length; c++ )
           printf (  "%c",   data[RTEMS_RFS_DIR_ENTRY_SIZE + c] );
           if (  length < elength - RTEMS_RFS_DIR_ENTRY_SIZE )
           printf (  "..." );
           printf (  "\n" );
          
           b += elength;
           data += elength;
           entry++;
           }
          
           rc = rtems_rfs_buffer_handle_close (  fs,   &buffer );
           if (  rc > 0 )
           {
           rtems_rfs_shell_unlock_rfs (  fs );
           printf (  "error: closing buffer handle: block=%" PRIu32 ": (  %d ) %s\n",  
           block,   rc,   strerror (  rc ) );
           return 1;
           }
          
           rtems_rfs_shell_unlock_rfs (  fs );
          
           return 0;
          }
          
          static int
     537  rtems_rfs_shell_group (  rtems_rfs_file_system* fs,   int argc,   char *argv[] )
          {
           int start;
           int end;
           int g;
          
           start = 0;
           end = fs->group_count - 1;
          
           switch (  argc )
           {
           case 1:
           break;
           case 2:
           start = end = strtoul (  argv[1],   0,   0 );
           break;
           case 3:
           start = strtoul (  argv[1],   0,   0 );
           end = strtoul (  argv[2],   0,   0 );
           break;
           default:
           printf (  "error: too many arguments.\n" );
           return 1;
           }
          
           if (  (  start < 0 ) || (  end < 0 ) ||
           (  start >= fs->group_count ) || (  end >= fs->group_count ) )
           {
           printf (  "error: group out of range (  0->%d ).\n",   fs->group_count );
           return 1;
           }
          
           rtems_rfs_shell_lock_rfs (  fs );
          
           for (  g = start; g <= end; g++ )
           {
           rtems_rfs_group* group = &fs->groups[g];
           size_t blocks;
           size_t inodes;
           blocks = group->size - rtems_rfs_bitmap_map_free (  &group->block_bitmap );
           inodes = fs->group_inodes - rtems_rfs_bitmap_map_free (  &group->inode_bitmap );
           printf (  " %4d: base=%-7" PRIu32 " size=%-6zu blocks=%-5zu (  %3zu%% ) inode=%-5zu (  %3zu%% )\n",  
           g,   group->base,   group->size,  
           blocks,   (  blocks * 100 ) / group->size,  
           inodes,   (  inodes * 100 ) / fs->group_inodes );
           }
          
           rtems_rfs_shell_unlock_rfs (  fs );
          
           return 0;
          }
          
          
          void
     591  rtems_rfs_shell_usage (  const char* arg )
          {
           printf (  "%s: RFS debugger\n",   arg );
           printf (  " %s [-hl] <path> <command>\n",   arg );
           printf (  " where:\n" );
           printf (  " path: Path to the mounted RFS file system\n" );
           printf (  " command: A debugger command. See -l for a list plus help.\n" );
           printf (  " -h: This help\n" );
           printf (  " -l: The debugger command list.\n" );
          }
          
          int
     603  rtems_shell_debugrfs (  int argc,   char *argv[] )
          {
           const rtems_rfs_shell_cmd table[] =
           {
           { "block",   rtems_rfs_shell_block,  
           "Display the contents of a block,   block <bno>,   block <bno>..<bno>" },  
           { "data",   rtems_rfs_shell_data,  
           "Display file system data,   data" },  
           { "dir",   rtems_rfs_shell_dir,  
           "Display a block as a table for directory entrie,   dir <bno>" },  
           { "group",   rtems_rfs_shell_group,  
           "Display the group data of a file system,   group,   group <group>,   group <start> <end>" },  
           { "inode",   rtems_rfs_shell_inode,  
           "Display an inode,   inode <ino>,   inode> <ino>..<ino>" }
           };
          
           int arg;
           int t;
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] != '-' )
           break;
          
           switch (  argv[arg][1] )
           {
           case 'h':
           rtems_rfs_shell_usage (  argv[0] );
           return 0;
           case 'l':
           printf (  "%s: commands are:\n",   argv[0] );
           for (  t = 0; t < (  sizeof (  table ) / sizeof (  const rtems_rfs_shell_cmd ) ); t++ )
           printf (  " %s\t\t%s\n",   table[t].name,   table[t].help );
           return 0;
           default:
           printf (  "error: unknown option: %s\n",   argv[arg] );
           return 1;
           }
           }
          
           if (  (  argc - arg ) < 2 )
           printf (  "error: you need at least a path and command,   try %s -h\n",   argv[0] );
           else
           {
           rtems_rfs_file_system* fs;
           if (  rtems_rfs_get_fs (  argv[arg],   &fs ) == 0 )
           {
           for (  t = 0; t < (  sizeof (  table ) / sizeof (  const rtems_rfs_shell_cmd ) ); t++ )
           if (  strcmp (  argv[arg + 1],   table[t].name ) == 0 )
           return table[t].handler (  fs,   argc - 2,   argv + 2 );
           printf (  "error: command not found: %s\n",   argv[arg + 1] );
           }
           }
          
           return 1;
          }
          
          int
     661  rtems_shell_rfs_format (  int argc,   char* argv[] )
          {
           rtems_rfs_format_config config;
           const char* driver = NULL;
           int arg;
          
           memset (  &config,   0,   sizeof (  rtems_rfs_format_config ) );
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           switch (  argv[arg][1] )
           {
           case 'v':
           config.verbose = true;
           break;
          
           case 's':
           arg++;
           if (  arg >= argc )
           {
           printf (  "error: block size needs an argument\n" );
           return 1;
           }
           config.block_size = strtoul (  argv[arg],   0,   0 );
           break;
          
           case 'b':
           arg++;
           if (  arg >= argc )
           {
           printf (  "error: group block count needs an argument\n" );
           return 1;
           }
           config.group_blocks = strtoul (  argv[arg],   0,   0 );
           break;
          
           case 'i':
           arg++;
           if (  arg >= argc )
           {
           printf (  "error: group inode count needs an argument\n" );
           return 1;
           }
           config.group_inodes = strtoul (  argv[arg],   0,   0 );
           break;
          
           case 'I':
           config.initialise_inodes = true;
           break;
          
           case 'o':
           arg++;
           if (  arg >= argc )
           {
           printf (  "error: inode percentage overhead needs an argument\n" );
           return 1;
           }
           config.inode_overhead = strtoul (  argv[arg],   0,   0 );
           break;
          
           default:
           printf (  "error: invalid option: %s\n",   argv[arg] );
           return 1;
           }
           }
           else
           {
           if (  !driver )
           driver = argv[arg];
           else
           {
           printf (  "error: only one driver name allowed: %s\n",   argv[arg] );
           return 1;
           }
           }
           }
          
           if (  !driver ) {
           printf (  "error: no driver name provided\n" );
           return 1;
           }
          
           if (  rtems_rfs_format (  driver,   &config ) < 0 )
           {
           printf (  "error: format of %s failed: %s\n",  
           driver,   strerror (  errno ) );
           return 1;
           }
          
           return 0;
          }

libfs/src/rfs/rtems-rfs-trace.c

       1  /*
           * COPYRIGHT (  c ) 2010 Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: rtems-rfs-trace.c,  v 1.3 2010/10/11 04:34:48 ccj Exp $
           */
          /**
           * @file
           *
           * @ingroup rtems-rfs
           *
           * RTEMS File Systems Trace Support
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          #include <rtems/rfs/rtems-rfs-trace.h>
          
          #if RTEMS_RFS_TRACE
          static rtems_rfs_trace_mask rtems_rfs_trace_flags;
          
          bool
      29  rtems_rfs_trace (  rtems_rfs_trace_mask mask )
          {
           bool result = false;
           if (  mask & rtems_rfs_trace_flags )
           result = true;
           return result;
          }
          
          rtems_rfs_trace_mask
      38  rtems_rfs_trace_set_mask (  rtems_rfs_trace_mask mask )
          {
           rtems_rfs_trace_mask state = rtems_rfs_trace_flags;
           rtems_rfs_trace_flags |= mask;
           return state;
          }
          
          rtems_rfs_trace_mask
      46  rtems_rfs_trace_clear_mask (  rtems_rfs_trace_mask mask )
          {
           rtems_rfs_trace_mask state = rtems_rfs_trace_flags;
           rtems_rfs_trace_flags &= ~mask;
           return state;
          }
          
          int
      54  rtems_rfs_trace_shell_command (  int argc,   char *argv[] )
          {
           const char* table[] =
           {
           "open",  
           "close",  
           "mutex",  
           "buffer-open",  
           "buffer-close",  
           "buffer-sync",  
           "buffer-release",  
           "buffer-chains",  
           "buffer-handle-request",  
           "buffer-handle-release",  
           "buffer-setblksize",  
           "buffers-release",  
           "block-find",  
           "block-map-grow",  
           "block-map-shrink",  
           "group-open",  
           "group-close",  
           "group-bitmaps",  
           "inode-open",  
           "inode-close",  
           "inode-load",  
           "inode-unload",  
           "inode-create",  
           "inode-delete",  
           "link",  
           "unlink",  
           "dir-lookup-ino",  
           "dir-lookup-ino-check",  
           "dir-lookup-ino-found",  
           "dir-add-entry",  
           "dir-del-entry",  
           "dir-read",  
           "dir-empty",  
           "symlink",  
           "symlink-read",  
           "file-open",  
           "file-close",  
           "file-io"
           };
          
           rtems_rfs_trace_mask set_value = 0;
           rtems_rfs_trace_mask clear_value = 0;
           bool set = true;
           int arg;
           int t;
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           switch (  argv[arg][1] )
           {
           case 'h':
           printf (  "usage: %s [-hl] [set/clear] [flags]\n",   argv[0] );
           return 0;
           case 'l':
           printf (  "%s: valid flags to set or clear are:\n",   argv[0] );
           for (  t = 0; t < (  sizeof (  table ) / sizeof (  const char* ) ); t++ )
           printf (  " %s\n",   table[t] );
           return 0;
           default:
           printf (  "error: unknown option\n" );
           return 1;
           }
           }
           else
           {
           if (  strcmp (  argv[arg],   "set" ) == 0 )
           set = true;
           if (  strcmp (  argv[arg],   "clear" ) == 0 )
           set = false;
           else if (  strcmp (  argv[arg],   "all" ) == 0 )
           {
           if (  set )
           set_value = RTEMS_RFS_TRACE_ALL;
           else
           clear_value = RTEMS_RFS_TRACE_ALL;
           }
           else
           {
           for (  t = 0; t < (  sizeof (  table ) / sizeof (  const char* ) ); t++ )
           {
           if (  strcmp (  argv[arg],   table[t] ) == 0 )
           {
           if (  set )
           set_value = 1 << t;
           else
           clear_value = 1 << t;
           break;
           }
           }
           }
          
           rtems_rfs_trace_flags |= set_value;
           rtems_rfs_trace_flags &= ~clear_value;
           }
           }
          
           return 0;
          }
          
          #endif

libmd/md4.c

       1  /*
          ** ********************************************************************
          ** md4.c -- Implementation of MD4 Message Digest Algorithm **
          ** Updated: 2/16/90 by Ronald L. Rivest **
          ** (  C ) 1990 RSA Data Security,   Inc. **
          ** ********************************************************************
          */
          
          /*
          ** To use MD4:
          ** -- Include md4.h in your program
          ** -- Declare an MDstruct MD to hold the state of the digest
          ** computation.
          ** -- Initialize MD using MDbegin(  &MD )
          ** -- For each full block (  64 bytes ) X you wish to process,   call
          ** MD4Update(  &MD,  X,  512 )
          ** (  512 is the number of bits in a full block. )
          ** -- For the last block (  less than 64 bytes ) you wish to process,  
          ** MD4Update(  &MD,  X,  n )
          ** where n is the number of bits in the partial block. A partial
          ** block terminates the computation,   so every MD computation
          ** should terminate by processing a partial block,   even if it
          ** has n = 0.
          ** -- The message digest is available in MD.buffer[0] ...
          ** MD.buffer[3]. (  Least-significant byte of each word
          ** should be output first. )
          ** -- You can print out the digest using MDprint(  &MD )
          */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* Implementation notes:
          ** This implementation assumes that ints are 32-bit quantities.
          */
          
          /* Compile-time includes
          */
          #include <stdio.h>
          #include "md4.h"
          
          #include <inttypes.h>
          
          /* Compile-time declarations of MD4 "magic constants".
          */
          #define I0 0x67452301L /* Initial values for MD buffer */
          #define I1 0xefcdab89L
          #define I2 0x98badcfeL
          #define I3 0x10325476L
          #define C2 013240474631L /* round 2 constant = sqrt(  2 ) in octal */
          #define C3 015666365641L /* round 3 constant = sqrt(  3 ) in octal */
          /* C2 and C3 are from Knuth,   The Art of Programming,   Volume 2
          ** (  Seminumerical Algorithms ),   Second Edition (  1981 ),   Addison-Wesley.
          ** Table 2,   page 660.
          */
          
          #define fs1 3 /* round 1 shift amounts */
          #define fs2 7
          #define fs3 11
          #define fs4 19
          #define gs1 3 /* round 2 shift amounts */
          #define gs2 5
          #define gs3 9
          #define gs4 13
          #define hs1 3 /* round 3 shift amounts */
          #define hs2 9
          #define hs3 11
          #define hs4 15
          
          /* Compile-time macro declarations for MD4.
          ** Note: The "rot" operator uses the variable "tmp".
          ** It assumes tmp is declared as unsigned int,   so that the >>
          ** operator will shift in zeros rather than extending the sign bit.
          */
          #define f(  X,  Y,  Z ) (  (  X&Y ) | (  (  ~X )&Z ) )
          #define g(  X,  Y,  Z ) (  (  X&Y ) | (  X&Z ) | (  Y&Z ) )
          #define h(  X,  Y,  Z ) (  X^Y^Z )
          #define rot(  X,  S ) (  tmp=X,  (  tmp<<S ) | (  tmp>>(  32-S ) ) )
          #define ff(  A,  B,  C,  D,  i,  s ) A = rot(  (  A + f(  B,  C,  D ) + X[i] ),  s )
          #define gg(  A,  B,  C,  D,  i,  s ) A = rot(  (  A + g(  B,  C,  D ) + X[i] + C2 ),  s )
          #define hh(  A,  B,  C,  D,  i,  s ) A = rot(  (  A + h(  B,  C,  D ) + X[i] + C3 ),  s )
          
          /* MD4print(  MDp )
          ** Print message digest buffer MDp as 32 hexadecimal digits.
          ** Order is from low-order byte of buffer[0] to high-order byte of
          ** buffer[3].
          ** Each byte is printed with high-order hexadecimal digit first.
          ** This is a user-callable routine.
          */
          void
      92  MD4Print(  
           MD4_CTX *MDp )
          {
           int i,  j;
           for (  i=0;i<4;i++ )
           for (  j=0;j<32;j=j+8 )
           printf(  "%02" PRIx32,  (  MDp->buffer[i]>>j ) & 0xFF );
          }
          
          /* MD4Init(  MDp )
          ** Initialize message digest buffer MDp.
          ** This is a user-callable routine.
          */
          void
     106  MD4Init(  
           MD4_CTX *MDp )
          {
           int i;
           MDp->buffer[0] = I0;
           MDp->buffer[1] = I1;
           MDp->buffer[2] = I2;
           MDp->buffer[3] = I3;
           for (  i=0;i<8;i++ ) MDp->count[i] = 0;
           MDp->done = 0;
          }
          
          /* MDblock(  MDp,  X )
          ** Update message digest buffer MDp->buffer using 16-word data block X.
          ** Assumes all 16 words of X are full of data.
          ** Does not update MDp->count.
          ** This routine is not user-callable.
          */
          static void
     125  MDblock(  
           MD4_CTX *MDp,  
           unsigned char *Xb )
          {
           register uint32_t tmp,   A,   B,   C,   D;
           uint32_t X[16];
           int i;
          
           for (  i = 0; i < 16; ++i ) {
           X[i] = Xb[0] + (  (  uint32_t )Xb[1] << 8 ) +
           (  (  uint32_t )Xb[2] << 16 ) + (  (  uint32_t )Xb[3] << 24 );
           Xb += 4;
           }
          
           A = MDp->buffer[0];
           B = MDp->buffer[1];
           C = MDp->buffer[2];
           D = MDp->buffer[3];
           /* Update the message digest buffer */
           ff(  A ,   B ,   C ,   D ,   0 ,   fs1 ); /* Round 1 */
           ff(  D ,   A ,   B ,   C ,   1 ,   fs2 );
           ff(  C ,   D ,   A ,   B ,   2 ,   fs3 );
           ff(  B ,   C ,   D ,   A ,   3 ,   fs4 );
           ff(  A ,   B ,   C ,   D ,   4 ,   fs1 );
           ff(  D ,   A ,   B ,   C ,   5 ,   fs2 );
           ff(  C ,   D ,   A ,   B ,   6 ,   fs3 );
           ff(  B ,   C ,   D ,   A ,   7 ,   fs4 );
           ff(  A ,   B ,   C ,   D ,   8 ,   fs1 );
           ff(  D ,   A ,   B ,   C ,   9 ,   fs2 );
           ff(  C ,   D ,   A ,   B ,   10 ,   fs3 );
           ff(  B ,   C ,   D ,   A ,   11 ,   fs4 );
           ff(  A ,   B ,   C ,   D ,   12 ,   fs1 );
           ff(  D ,   A ,   B ,   C ,   13 ,   fs2 );
           ff(  C ,   D ,   A ,   B ,   14 ,   fs3 );
           ff(  B ,   C ,   D ,   A ,   15 ,   fs4 );
           gg(  A ,   B ,   C ,   D ,   0 ,   gs1 ); /* Round 2 */
           gg(  D ,   A ,   B ,   C ,   4 ,   gs2 );
           gg(  C ,   D ,   A ,   B ,   8 ,   gs3 );
           gg(  B ,   C ,   D ,   A ,   12 ,   gs4 );
           gg(  A ,   B ,   C ,   D ,   1 ,   gs1 );
           gg(  D ,   A ,   B ,   C ,   5 ,   gs2 );
           gg(  C ,   D ,   A ,   B ,   9 ,   gs3 );
           gg(  B ,   C ,   D ,   A ,   13 ,   gs4 );
           gg(  A ,   B ,   C ,   D ,   2 ,   gs1 );
           gg(  D ,   A ,   B ,   C ,   6 ,   gs2 );
           gg(  C ,   D ,   A ,   B ,   10 ,   gs3 );
           gg(  B ,   C ,   D ,   A ,   14 ,   gs4 );
           gg(  A ,   B ,   C ,   D ,   3 ,   gs1 );
           gg(  D ,   A ,   B ,   C ,   7 ,   gs2 );
           gg(  C ,   D ,   A ,   B ,   11 ,   gs3 );
           gg(  B ,   C ,   D ,   A ,   15 ,   gs4 );
           hh(  A ,   B ,   C ,   D ,   0 ,   hs1 ); /* Round 3 */
           hh(  D ,   A ,   B ,   C ,   8 ,   hs2 );
           hh(  C ,   D ,   A ,   B ,   4 ,   hs3 );
           hh(  B ,   C ,   D ,   A ,   12 ,   hs4 );
           hh(  A ,   B ,   C ,   D ,   2 ,   hs1 );
           hh(  D ,   A ,   B ,   C ,   10 ,   hs2 );
           hh(  C ,   D ,   A ,   B ,   6 ,   hs3 );
           hh(  B ,   C ,   D ,   A ,   14 ,   hs4 );
           hh(  A ,   B ,   C ,   D ,   1 ,   hs1 );
           hh(  D ,   A ,   B ,   C ,   9 ,   hs2 );
           hh(  C ,   D ,   A ,   B ,   5 ,   hs3 );
           hh(  B ,   C ,   D ,   A ,   13 ,   hs4 );
           hh(  A ,   B ,   C ,   D ,   3 ,   hs1 );
           hh(  D ,   A ,   B ,   C ,   11 ,   hs2 );
           hh(  C ,   D ,   A ,   B ,   7 ,   hs3 );
           hh(  B ,   C ,   D ,   A ,   15 ,   hs4 );
           MDp->buffer[0] += A;
           MDp->buffer[1] += B;
           MDp->buffer[2] += C;
           MDp->buffer[3] += D;
          }
          
          /* MD4Update(  MDp,  X,  count )
          ** Input: X -- a pointer to an array of unsigned characters.
          ** count -- the number of bits of X to use.
          ** (  if not a multiple of 8,   uses high bits of last byte. )
          ** Update MDp using the number of bits of X given by count.
          ** This is the basic input routine for an MD4 user.
          ** The routine completes the MD computation when count < 512,   so
          ** every MD computation should end with one call to MD4Update with a
          ** count less than 512. A call with count 0 will be ignored if the
          ** MD has already been terminated (  done != 0 ),   so an extra call with
          ** count 0 can be given as a "courtesy close" to force termination
          ** if desired.
          */
          void
     212  MD4Update(  
           MD4_CTX *MDp,  
           unsigned char *X,  
           unsigned int count  )
          {
           unsigned int i,   tmp,   bit,   byte,   mask;
           unsigned char XX[64];
           unsigned char *p;
          
           /* return with no error if this is a courtesy close with count
           ** zero and MDp->done is true.
           */
           if (  count == 0 && MDp->done ) return;
           /* check to see if MD is already done and report error */
           if (  MDp->done )
           { printf(  "\nError: MD4Update MD already done." ); return; }
          
           /* Add count to MDp->count */
           tmp = count;
           p = MDp->count;
           while (  tmp )
           { tmp += *p;
           *p++ = tmp;
           tmp = tmp >> 8;
           }
          
           /* Process data */
           if (  count == 512 )
           { /* Full block of data to handle */
           MDblock(  MDp,  X );
           }
           else if (  count > 512 ) /* Check for count too large */
           {
           printf(  "\nError: MD4Update called with illegal count value %d.",  
           count );
           return;
           }
           else /* partial block -- must be last block so finish up */
           {
           /* Find out how many bytes and residual bits there are */
           byte = count >> 3;
           bit = count & 7;
           /* Copy X into XX since we need to modify it */
           for (  i=0;i<=byte;i++ ) XX[i] = X[i];
           for (  i=byte+1;i<64;i++ ) XX[i] = 0;
           /* Add padding '1' bit and low-order zeros in last byte */
           mask = 1 << (  7 - bit );
           XX[byte] = (  XX[byte] | mask ) & ~(   mask - 1 );
           /* If room for bit count,   finish up with this block */
           if (  byte <= 55 )
           {
           for (  i=0;i<8;i++ ) XX[56+i] = MDp->count[i];
           MDblock(  MDp,  XX );
           }
           else /* need to do two blocks to finish up */
           {
           MDblock(  MDp,  XX );
           for (  i=0;i<56;i++ ) XX[i] = 0;
           for (  i=0;i<8;i++ ) XX[56+i] = MDp->count[i];
           MDblock(  MDp,  XX );
           }
           /* Set flag saying we're done with MD computation */
           MDp->done = 1;
           }
          }
          
          /*
          ** Finish up MD4 computation and return message digest.
          */
          void
     282  MD4Final(  
           unsigned char *buf,  
           MD4_CTX *MD )
          {
           int i,   j;
           unsigned int w;
          
           MD4Update(  MD,   NULL,   0 );
           for (  i = 0; i < 4; ++i ) {
           w = MD->buffer[i];
           for (  j = 0; j < 4; ++j ) {
           *buf++ = w;
           w >>= 8;
           }
           }
          }
          
          /*
          ** End of md4.c
          ****************************(  cut )***********************************/

libmd/md5.c

       1  
          
          /*
           ***********************************************************************
           ** md5.c -- the source code for MD5 routines **
           ** RSA Data Security,   Inc. MD5 Message-Digest Algorithm **
           ** Created: 2/17/90 RLR **
           ** Revised: 1/91 SRD,  AJ,  BSK,  JT Reference C ver.,   7/10 constant corr. **
           ***********************************************************************
           */
          
          /*
           ***********************************************************************
           ** Copyright (  C ) 1990,   RSA Data Security,   Inc. All rights reserved. **
           ** **
           ** License to copy and use this software is granted provided that **
           ** it is identified as the "RSA Data Security,   Inc. MD5 Message- **
           ** Digest Algorithm" in all material mentioning or referencing this **
           ** software or this function. **
           ** **
           ** License is also granted to make and use derivative works **
           ** provided that such works are identified as "derived from the RSA **
           ** Data Security,   Inc. MD5 Message-Digest Algorithm" in all **
           ** material mentioning or referencing the derived work. **
           ** **
           ** RSA Data Security,   Inc. makes no representations concerning **
           ** either the merchantability of this software or the suitability **
           ** of this software for any particular purpose. It is provided "as **
           ** is" without express or implied warranty of any kind. **
           ** **
           ** These notices must be retained in any copies of any part of this **
           ** documentation and/or software. **
           ***********************************************************************
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h> /* memcpy */
          
          #include "md5.h"
          
          /*
           ***********************************************************************
           ** Message-digest routines: **
           ** To form the message digest for a message M **
           ** (  1 ) Initialize a context buffer mdContext using MD5Init **
           ** (  2 ) Call MD5Update on mdContext and M **
           ** (  3 ) Call MD5Final on mdContext **
           ** The message digest is now in mdContext->digest[0...15] **
           ***********************************************************************
           */
          
          /* forward declaration */
      56  static void Transform (  UINT4 *buf,   UINT4 *in );
          
          static unsigned char PADDING[64] = {
           0x80,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
           0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
           0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
           0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
           0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
           0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
           0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,  
           0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00
          };
          
          /* F,   G,   H and I are basic MD5 functions */
          #define F(  x,   y,   z ) (  (  (  x ) & (  y ) ) | (  (  ~x ) & (  z ) ) )
          #define G(  x,   y,   z ) (  (  (  x ) & (  z ) ) | (  (  y ) & (  ~z ) ) )
          #define H(  x,   y,   z ) (  (  x ) ^ (  y ) ^ (  z ) )
          #define I(  x,   y,   z ) (  (  y ) ^ (  (  x ) | (  ~z ) ) )
          
          /* ROTATE_LEFT rotates x left n bits */
          #define ROTATE_LEFT(  x,   n ) (  (  (  x ) << (  n ) ) | (  (  x ) >> (  32-(  n ) ) ) )
          
          /* FF,   GG,   HH,   and II transformations for rounds 1,   2,   3,   and 4 */
          /* Rotation is separate from addition to prevent recomputation */
          #define FF(  a,   b,   c,   d,   x,   s,   ac ) \
           {(  a ) += F (  (  b ),   (  c ),   (  d ) ) + (  x ) + (  UINT4 )(  ac ); \
           (  a ) = ROTATE_LEFT (  (  a ),   (  s ) ); \
           (  a ) += (  b ); \
           }
          #define GG(  a,   b,   c,   d,   x,   s,   ac ) \
           {(  a ) += G (  (  b ),   (  c ),   (  d ) ) + (  x ) + (  UINT4 )(  ac ); \
           (  a ) = ROTATE_LEFT (  (  a ),   (  s ) ); \
           (  a ) += (  b ); \
           }
          #define HH(  a,   b,   c,   d,   x,   s,   ac ) \
           {(  a ) += H (  (  b ),   (  c ),   (  d ) ) + (  x ) + (  UINT4 )(  ac ); \
           (  a ) = ROTATE_LEFT (  (  a ),   (  s ) ); \
           (  a ) += (  b ); \
      94   }
          #define II(  a,   b,   c,   d,   x,   s,   ac ) \
           {(  a ) += I (  (  b ),   (  c ),   (  d ) ) + (  x ) + (  UINT4 )(  ac ); \
           (  a ) = ROTATE_LEFT (  (  a ),   (  s ) ); \
           (  a ) += (  b ); \
           }
          
          #ifdef __STDC__
          #define UL(  x ) x##U
          #else
          #define UL(  x ) x
          #endif
          
          /* The routine MD5Init initializes the message-digest context
           mdContext. All fields are set to zero.
           */
          void MD5Init (  
     111   MD5_CTX *mdContext  )
          {
           mdContext->i[0] = mdContext->i[1] = (  UINT4 )0;
          
           /* Load magic initialization constants.
           */
           mdContext->buf[0] = (  UINT4 )0x67452301;
           mdContext->buf[1] = (  UINT4 )0xefcdab89;
           mdContext->buf[2] = (  UINT4 )0x98badcfe;
           mdContext->buf[3] = (  UINT4 )0x10325476;
          }
          
          /* The routine MD5Update updates the message-digest context to
           account for the presence of each of the characters inBuf[0..inLen-1]
           in the message whose digest is being computed.
           */
          void MD5Update (  
           MD5_CTX *mdContext,  
           const unsigned char *inBuf,  
           unsigned int inLen  )
          {
           UINT4 in[16];
           int mdi;
           unsigned int i,   ii;
          
           /* compute number of bytes mod 64 */
           mdi = (  int )(  (  mdContext->i[0] >> 3 ) & 0x3F );
          
           /* update number of bits */
           if (  (  mdContext->i[0] + (  (  UINT4 )inLen << 3 ) ) < mdContext->i[0] )
           mdContext->i[1]++;
           mdContext->i[0] += (  (  UINT4 )inLen << 3 );
           mdContext->i[1] += (  (  UINT4 )inLen >> 29 );
          
           while (  inLen-- ) {
           /* add new character to buffer,   increment mdi */
           mdContext->in[mdi++] = *inBuf++;
          
     149   /* transform if necessary */
           if (  mdi == 0x40 ) {
           for (  i = 0,   ii = 0; i < 16; i++,   ii += 4 )
           in[i] = (  (  (  UINT4 )mdContext->in[ii+3] ) << 24 ) |
           (  (  (  UINT4 )mdContext->in[ii+2] ) << 16 ) |
           (  (  (  UINT4 )mdContext->in[ii+1] ) << 8 ) |
           (  (  UINT4 )mdContext->in[ii] );
           Transform (  mdContext->buf,   in );
           mdi = 0;
           }
           }
          }
          
          /* The routine MD5Final terminates the message-digest computation and
           ends with the desired message digest in mdContext->digest[0...15].
           */
          void MD5Final (  
           unsigned char hash[],  
           MD5_CTX *mdContext  )
          {
           UINT4 in[16];
           int mdi;
           unsigned int i,   ii;
           unsigned int padLen;
          
           /* save number of bits */
           in[14] = mdContext->i[0];
           in[15] = mdContext->i[1];
          
           /* compute number of bytes mod 64 */
           mdi = (  int )(  (  mdContext->i[0] >> 3 ) & 0x3F );
          
           /* pad out to 56 mod 64 */
           padLen = (  mdi < 56 ) ? (  56 - mdi ) : (  120 - mdi );
           MD5Update (  mdContext,   PADDING,   padLen );
          
           /* append length in bits and transform */
           for (  i = 0,   ii = 0; i < 14; i++,   ii += 4 )
           in[i] = (  (  (  UINT4 )mdContext->in[ii+3] ) << 24 ) |
           (  (  (  UINT4 )mdContext->in[ii+2] ) << 16 ) |
           (  (  (  UINT4 )mdContext->in[ii+1] ) << 8 ) |
           (  (  UINT4 )mdContext->in[ii] );
           Transform (  mdContext->buf,   in );
     192  
           /* store buffer in digest */
           for (  i = 0,   ii = 0; i < 4; i++,   ii += 4 ) {
           mdContext->digest[ii] = (  unsigned char )(  mdContext->buf[i] & 0xFF );
           mdContext->digest[ii+1] =
           (  unsigned char )(  (  mdContext->buf[i] >> 8 ) & 0xFF );
           mdContext->digest[ii+2] =
           (  unsigned char )(  (  mdContext->buf[i] >> 16 ) & 0xFF );
           mdContext->digest[ii+3] =
           (  unsigned char )(  (  mdContext->buf[i] >> 24 ) & 0xFF );
           }
           memcpy(  hash,   mdContext->digest,   16 );
          }
          
          /* Basic MD5 step. Transforms buf based on in.
           */
          static void Transform (  
           UINT4 *buf,  
           UINT4 *in  )
          {
           UINT4 a = buf[0],   b = buf[1],   c = buf[2],   d = buf[3];
          
           /* Round 1 */
          #define S11 7
          #define S12 12
          #define S13 17
          #define S14 22
           FF (   a,   b,   c,   d,   in[ 0],   S11,   UL(  3614090360 ) ); /* 1 */
           FF (   d,   a,   b,   c,   in[ 1],   S12,   UL(  3905402710 ) ); /* 2 */
           FF (   c,   d,   a,   b,   in[ 2],   S13,   UL(   606105819 ) ); /* 3 */
           FF (   b,   c,   d,   a,   in[ 3],   S14,   UL(  3250441966 ) ); /* 4 */
           FF (   a,   b,   c,   d,   in[ 4],   S11,   UL(  4118548399 ) ); /* 5 */
           FF (   d,   a,   b,   c,   in[ 5],   S12,   UL(  1200080426 ) ); /* 6 */
           FF (   c,   d,   a,   b,   in[ 6],   S13,   UL(  2821735955 ) ); /* 7 */
           FF (   b,   c,   d,   a,   in[ 7],   S14,   UL(  4249261313 ) ); /* 8 */
           FF (   a,   b,   c,   d,   in[ 8],   S11,   UL(  1770035416 ) ); /* 9 */
           FF (   d,   a,   b,   c,   in[ 9],   S12,   UL(  2336552879 ) ); /* 10 */
           FF (   c,   d,   a,   b,   in[10],   S13,   UL(  4294925233 ) ); /* 11 */
           FF (   b,   c,   d,   a,   in[11],   S14,   UL(  2304563134 ) ); /* 12 */
           FF (   a,   b,   c,   d,   in[12],   S11,   UL(  1804603682 ) ); /* 13 */
           FF (   d,   a,   b,   c,   in[13],   S12,   UL(  4254626195 ) ); /* 14 */
           FF (   c,   d,   a,   b,   in[14],   S13,   UL(  2792965006 ) ); /* 15 */
           FF (   b,   c,   d,   a,   in[15],   S14,   UL(  1236535329 ) ); /* 16 */
          
           /* Round 2 */
          #define S21 5
          #define S22 9
          #define S23 14
          #define S24 20
           GG (   a,   b,   c,   d,   in[ 1],   S21,   UL(  4129170786 ) ); /* 17 */
           GG (   d,   a,   b,   c,   in[ 6],   S22,   UL(  3225465664 ) ); /* 18 */
           GG (   c,   d,   a,   b,   in[11],   S23,   UL(   643717713 ) ); /* 19 */
           GG (   b,   c,   d,   a,   in[ 0],   S24,   UL(  3921069994 ) ); /* 20 */
           GG (   a,   b,   c,   d,   in[ 5],   S21,   UL(  3593408605 ) ); /* 21 */
           GG (   d,   a,   b,   c,   in[10],   S22,   UL(   38016083 ) ); /* 22 */
           GG (   c,   d,   a,   b,   in[15],   S23,   UL(  3634488961 ) ); /* 23 */
           GG (   b,   c,   d,   a,   in[ 4],   S24,   UL(  3889429448 ) ); /* 24 */
           GG (   a,   b,   c,   d,   in[ 9],   S21,   UL(   568446438 ) ); /* 25 */
           GG (   d,   a,   b,   c,   in[14],   S22,   UL(  3275163606 ) ); /* 26 */
           GG (   c,   d,   a,   b,   in[ 3],   S23,   UL(  4107603335 ) ); /* 27 */
           GG (   b,   c,   d,   a,   in[ 8],   S24,   UL(  1163531501 ) ); /* 28 */
           GG (   a,   b,   c,   d,   in[13],   S21,   UL(  2850285829 ) ); /* 29 */
           GG (   d,   a,   b,   c,   in[ 2],   S22,   UL(  4243563512 ) ); /* 30 */
           GG (   c,   d,   a,   b,   in[ 7],   S23,   UL(  1735328473 ) ); /* 31 */
           GG (   b,   c,   d,   a,   in[12],   S24,   UL(  2368359562 ) ); /* 32 */
          
           /* Round 3 */
          #define S31 4
          #define S32 11
          #define S33 16
          #define S34 23
           HH (   a,   b,   c,   d,   in[ 5],   S31,   UL(  4294588738 ) ); /* 33 */
           HH (   d,   a,   b,   c,   in[ 8],   S32,   UL(  2272392833 ) ); /* 34 */
           HH (   c,   d,   a,   b,   in[11],   S33,   UL(  1839030562 ) ); /* 35 */
           HH (   b,   c,   d,   a,   in[14],   S34,   UL(  4259657740 ) ); /* 36 */
           HH (   a,   b,   c,   d,   in[ 1],   S31,   UL(  2763975236 ) ); /* 37 */
           HH (   d,   a,   b,   c,   in[ 4],   S32,   UL(  1272893353 ) ); /* 38 */
           HH (   c,   d,   a,   b,   in[ 7],   S33,   UL(  4139469664 ) ); /* 39 */
           HH (   b,   c,   d,   a,   in[10],   S34,   UL(  3200236656 ) ); /* 40 */
           HH (   a,   b,   c,   d,   in[13],   S31,   UL(   681279174 ) ); /* 41 */
           HH (   d,   a,   b,   c,   in[ 0],   S32,   UL(  3936430074 ) ); /* 42 */
           HH (   c,   d,   a,   b,   in[ 3],   S33,   UL(  3572445317 ) ); /* 43 */
           HH (   b,   c,   d,   a,   in[ 6],   S34,   UL(   76029189 ) ); /* 44 */
           HH (   a,   b,   c,   d,   in[ 9],   S31,   UL(  3654602809 ) ); /* 45 */
           HH (   d,   a,   b,   c,   in[12],   S32,   UL(  3873151461 ) ); /* 46 */
           HH (   c,   d,   a,   b,   in[15],   S33,   UL(   530742520 ) ); /* 47 */
           HH (   b,   c,   d,   a,   in[ 2],   S34,   UL(  3299628645 ) ); /* 48 */
          
           /* Round 4 */
          #define S41 6
          #define S42 10
          #define S43 15
          #define S44 21
           II (   a,   b,   c,   d,   in[ 0],   S41,   UL(  4096336452 ) ); /* 49 */
           II (   d,   a,   b,   c,   in[ 7],   S42,   UL(  1126891415 ) ); /* 50 */
           II (   c,   d,   a,   b,   in[14],   S43,   UL(  2878612391 ) ); /* 51 */
           II (   b,   c,   d,   a,   in[ 5],   S44,   UL(  4237533241 ) ); /* 52 */
           II (   a,   b,   c,   d,   in[12],   S41,   UL(  1700485571 ) ); /* 53 */
           II (   d,   a,   b,   c,   in[ 3],   S42,   UL(  2399980690 ) ); /* 54 */
           II (   c,   d,   a,   b,   in[10],   S43,   UL(  4293915773 ) ); /* 55 */
           II (   b,   c,   d,   a,   in[ 1],   S44,   UL(  2240044497 ) ); /* 56 */
           II (   a,   b,   c,   d,   in[ 8],   S41,   UL(  1873313359 ) ); /* 57 */
           II (   d,   a,   b,   c,   in[15],   S42,   UL(  4264355552 ) ); /* 58 */
           II (   c,   d,   a,   b,   in[ 6],   S43,   UL(  2734768916 ) ); /* 59 */
           II (   b,   c,   d,   a,   in[13],   S44,   UL(  1309151649 ) ); /* 60 */
           II (   a,   b,   c,   d,   in[ 4],   S41,   UL(  4149444226 ) ); /* 61 */
           II (   d,   a,   b,   c,   in[11],   S42,   UL(  3174756917 ) ); /* 62 */
           II (   c,   d,   a,   b,   in[ 2],   S43,   UL(   718787259 ) ); /* 63 */
           II (   b,   c,   d,   a,   in[ 9],   S44,   UL(  3951481745 ) ); /* 64 */
          
           buf[0] += a;
           buf[1] += b;
           buf[2] += c;
           buf[3] += d;
          }
          
          /*
           ***********************************************************************
           ** End of md5.c **
           ******************************** (  cut ) ********************************
           */

libmisc/bspcmdline/bspcmdline_get.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: bspcmdline_get.c,  v 1.3 2010/03/27 05:01:30 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/bspcmdline.h>
          
          extern const char *bsp_boot_cmdline;
          
      20  const char *rtems_bsp_cmdline_get(  void )
          {
           return bsp_boot_cmdline;
          }

libmisc/bspcmdline/bspcmdline_getparam.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: bspcmdline_getparam.c,  v 1.4 2010/03/27 05:01:30 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/bspcmdline.h>
          
      18  static void copy_string(  
           const char *start,  
           char *value,  
           size_t length
           )
          {
           int i;
           int quotes;
           const char *p = start;
          
           quotes=0;
           for (  i=0 ; *p && i<length-1;  ) {
           if (   *p == '\"'  ) {
           quotes++;
           } else if (   (  (  quotes % 2 ) == 0 ) && *p == ' '  )
           break;
           value[i++] = *p++;
           value[i] = '\0';
           }
          
          }
          
      40  const char *rtems_bsp_cmdline_get_param(  
           const char *name,  
           char *value,  
           size_t length
           )
          {
           const char *p;
          
           if (   !name  )
           return NULL;
          
           if (   !value  )
           return NULL;
          
           if (   !length  )
           return NULL;
          
           value[0] = '\0';
          
           p = rtems_bsp_cmdline_get_param_raw(   name  );
          
           if (   !p  )
           return NULL;
          
           copy_string(   p,   value,   length  );
          
           return value;
          }

libmisc/bspcmdline/bspcmdline_getparamraw.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: bspcmdline_getparamraw.c,  v 1.4 2010/03/27 05:01:30 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          
          #include <rtems/bspcmdline.h>
          
          extern const char *bsp_boot_cmdline;
          
      22  const char *rtems_bsp_cmdline_get_param_raw(  
           const char *name
           )
          {
           const char *p;
          
           if (   !name  )
           return NULL;
          
           if (   !bsp_boot_cmdline  )
           return NULL;
          
           p = strstr(  bsp_boot_cmdline,   name );
           /* printf(   "raw: %p (  %s )\n",   p,   p  ); */
           return p;
          }

libmisc/bspcmdline/bspcmdline_getparamrhs.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: bspcmdline_getparamrhs.c,  v 1.4 2010/03/27 05:01:30 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          
          #include <rtems/bspcmdline.h>
          
      20  const char *rtems_bsp_cmdline_get_param_rhs(  
           const char *name,  
           char *value,  
           size_t length
           )
          {
           const char *p;
           const char *rhs;
           char *d;
          
           p = rtems_bsp_cmdline_get_param(   name,   value,   length  );
           if (   !p  )
           return NULL;
          
           rhs = &p[strlen(  name )];
           if (   *rhs != '='  )
           return NULL;
          
           rhs++;
           if (   *rhs == '\"'  )
           rhs++;
           for (   d=value ; *rhs ;  )
           *d++ = *rhs++;
           if (   *(  d-1 ) == '\"'  )
           d--;
           *d = '\0';
          
           return value;
          }

libmisc/capture/capture-cli.c

       1  /*
           ------------------------------------------------------------------------
           $Id: capture-cli.c,  v 1.25 2010/03/12 16:26:14 joel Exp $
           ------------------------------------------------------------------------
          
           Copyright Objective Design Systems Pty Ltd,   2002
           All rights reserved Objective Design Systems Pty Ltd,   2002
           Chris Johns (  ccj@acm.org )
          
           COPYRIGHT (  c ) 1989-1998.
           On-Line Applications Research Corporation (  OAR ).
          
           The license and distribution terms for this file may be
           found in the file LICENSE in this distribution.
          
           This software with is provided ``as is'' and with NO WARRANTY.
          
           ------------------------------------------------------------------------
          
           RTEMS Performance Monitoring and Measurement Framework.
          
           This is the Target Interface Command Line Interface. You need
           start the RTEMS monitor.
          
          */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <ctype.h>
          #include <stdlib.h>
          #include <stdio.h>
          #include <string.h>
          #include <inttypes.h>
          
          #include <rtems.h>
          #include <rtems/capture-cli.h>
          #include <rtems/monitor.h>
          
          #define RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS (  20 )
          
          /*
           * The user capture timestamper.
           */
          static rtems_capture_timestamp capture_timestamp;
          
          /*
           * Common variable to sync the load monitor task.
           */
          static volatile int cli_load_thread_active;
          
          /*
           * rtems_capture_cli_open
           *
           * DESCRIPTION:
           *
           * This function opens the capture engine. We need the size of the
           * capture buffer.
           *
           */
          
          static const char* open_usage = "usage: copen [-i] size\n";
          
          static void
      66  rtems_capture_cli_open (  int argc,  
           char** argv,  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           uint32_t size = 0;
           bool enable = false;
           rtems_status_code sc;
           int arg;
          
           if (  argc <= 1 )
           {
           fprintf (  stdout,   open_usage );
           return;
           }
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           if (  argv[arg][1] == 'i' )
           enable = true;
           else
           fprintf (  stdout,   "warning: option -%c ignored\n",   argv[arg][1] );
           }
           else
           {
           size = strtoul (  argv[arg],   0,   0 );
          
           if (  size < 100 )
           {
           fprintf (  stdout,   "error: size must be greater than or equal to 100\n" );
           return;
           }
           }
           }
          
           sc = rtems_capture_open (  size,   capture_timestamp );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: open failed: %s\n",   rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "capture engine opened.\n" );
          
           if (  !enable )
           return;
          
           sc = rtems_capture_control (  enable );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: open enable failed: %s\n",   rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "capture engine enabled.\n" );
          }
          
          /*
           * rtems_capture_cli_close
           *
           * DESCRIPTION:
           *
           * This function closes the capture engine.
           *
           */
          
          static void
     137  rtems_capture_cli_close (  int argc __attribute__(  (  unused ) ),  
           char** argv __attribute__(  (  unused ) ),  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
          
           sc = rtems_capture_close (   );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: close failed: %s\n",   rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "capture engine closed.\n" );
          }
          
          /*
           * rtems_capture_cli_enable
           *
           * DESCRIPTION:
           *
           * This function enables the capture engine.
           *
           */
          
          static void
     165  rtems_capture_cli_enable (  int argc __attribute__(  (  unused ) ),  
           char** argv __attribute__(  (  unused ) ),  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
          
           sc = rtems_capture_control (  1 );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: enable failed: %s\n",   rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "capture engine enabled.\n" );
          }
          
          /*
           * rtems_capture_cli_disable
           *
           * DESCRIPTION:
           *
           * This function disables the capture engine.
           *
           */
          
          static void
     193  rtems_capture_cli_disable (  int argc __attribute__(  (  unused ) ),  
           char** argv __attribute__(  (  unused ) ),  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
          
           sc = rtems_capture_control (  0 );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: disable failed: %s\n",   rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "capture engine disabled.\n" );
          }
          
          /*
           * rtems_capture_cli_task_list
           *
           * DESCRIPTION:
           *
           * This function lists the tasks the capture engine knows about.
           *
           */
          
          static void
     221  rtems_capture_cli_task_list (  int argc __attribute__(  (  unused ) ),  
           char** argv __attribute__(  (  unused ) ),  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (   );
           rtems_task_priority floor = rtems_capture_watch_get_floor (   );
           rtems_capture_task_t* task = rtems_capture_get_task_list (   );
           uint32_t ticks;
           uint32_t tick_offset;
           unsigned long long total_time;
           int count = rtems_capture_task_count (   );
          
           if (  capture_timestamp )
           capture_timestamp (  &ticks,   &tick_offset );
           else
           {
           ticks = _Watchdog_Ticks_since_boot;
           tick_offset = 0;
           }
          
           fprintf (  stdout,   "total %i\n",   count );
          
           while (  task )
           {
           rtems_task_priority priority;
           int32_t stack_used;
           int32_t time_used;
          
           stack_used = rtems_capture_task_stack_usage (  task );
           if (  stack_used )
           stack_used = (  stack_used * 100 ) / stack_used;
          
           if (  stack_used > 100 )
           stack_used = 100;
          
           total_time = (  ticks * rtems_capture_task_time (  task ) ) + tick_offset;
          
           time_used = (  rtems_capture_task_time (  task ) * 100 ) / total_time;
          
           if (  time_used > 100 )
           time_used = 100;
          
           priority = rtems_capture_task_real_priority (  task );
          
           fprintf (  stdout,   " " );
           rtems_monitor_dump_id (  rtems_capture_task_id (  task ) );
           fprintf (  stdout,   " " );
           rtems_monitor_dump_name (  rtems_capture_task_name (  task ) );
           fprintf (  stdout,   " " );
           rtems_monitor_dump_priority (  rtems_capture_task_start_priority (  task ) );
           fprintf (  stdout,   " " );
           rtems_monitor_dump_priority (  rtems_capture_task_real_priority (  task ) );
           fprintf (  stdout,   " " );
           rtems_monitor_dump_priority (  rtems_capture_task_curr_priority (  task ) );
           fprintf (  stdout,   " " );
           rtems_monitor_dump_state (  rtems_capture_task_state (  task ) );
           fprintf (  stdout,   " %c%c",  
           rtems_capture_task_valid (  task ) ? 'a' : 'd',  
           rtems_capture_task_flags (  task ) & RTEMS_CAPTURE_TRACED ? 't' : '-' );
          
           if (  (  floor > ceiling ) && (  ceiling > priority ) )
           fprintf (  stdout,   "--" );
           else
           {
           uint32_t flags = rtems_capture_task_control_flags (  task );
           fprintf (  stdout,   "%c%c",  
           rtems_capture_task_control (  task ) ?
           (  flags & RTEMS_CAPTURE_WATCH ? 'w' : '+' ) : '-',  
           rtems_capture_watch_global_on (   ) ? 'g' : '-' );
           }
           fprintf (  stdout,   " %3" PRId32 "%% %3" PRId32 "%% (  %" PRIu32 " )\n",  
           stack_used,   time_used,   rtems_capture_task_ticks (  task ) );
          
           task = rtems_capture_next_task (  task );
           }
          }
          
          /*
           * rtems_capture_cli_task_load_thread
           *
           * DESCRIPTION:
           *
           * This function displays the load of the tasks on an ANSI terminal.
           *
           */
          
          static void
     309  rtems_capture_cli_task_load_thread (  rtems_task_argument arg __attribute__(  (  unused ) ) )
          {
           rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (   );
           rtems_task_priority floor = rtems_capture_watch_get_floor (   );
           int last_count = 0;
          
           for (  ;; )
           {
           rtems_capture_task_t* tasks[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1];
           unsigned long long load[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1];
           rtems_capture_task_t* task;
           unsigned long long total_time;
           int count = 0;
           int i;
           int j;
          
           cli_load_thread_active = 1;
          
           /*
           * Iterate over the tasks and sort the highest load tasks
           * into our local arrays. We only handle a limited number of
           * tasks.
           */
          
           memset (  tasks,   0,   sizeof (  tasks ) );
           memset (  load,   0,   sizeof (  load ) );
          
           task = rtems_capture_get_task_list (   );
          
           total_time = 0;
          
           while (  task )
           {
           if (  rtems_capture_task_valid (  task ) )
           {
           unsigned long long l = rtems_capture_task_delta_time (  task );
          
           count++;
          
           total_time += l;
          
           for (  i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++ )
           {
           if (  tasks[i] )
           {
           if (  (  l == 0 ) || (  l < load[i] ) )
           continue;
          
           for (  j = (  RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS - 1 ); j >= i; j-- )
           {
           tasks[j + 1] = tasks[j];
           load[j + 1] = load[j];
           }
           }
          
           tasks[i] = task;
           load[i] = l;
           break;
           }
           }
           task = rtems_capture_next_task (  task );
           }
          
           fprintf (  stdout,   "\x1b[H\x1b[J Press ENTER to exit.\n\n" );
           fprintf (  stdout,  
           " PID NAME RPRI CPRI STATE %%CPU %%STK FLGS EXEC TIME\n" );
          
           if (  count > last_count )
           j = count;
           else
           j = last_count;
          
           for (  i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++ )
           {
           rtems_task_priority priority;
           int stack_used;
           int task_load;
           int k;
          
           if (  !tasks[i] )
           break;
          
           j--;
          
           stack_used = rtems_capture_task_stack_usage (  tasks[i] );
           if (  stack_used )
           stack_used = (  stack_used * 100 ) / stack_used;
          
           if (  stack_used > 100 )
           stack_used = 100;
          
           task_load = (  int ) (  (  load[i] * 100000 ) / total_time );
          
           priority = rtems_capture_task_real_priority (  tasks[i] );
          
           fprintf (  stdout,   "\x1b[K" );
           rtems_monitor_dump_id (  rtems_capture_task_id (  tasks[i] ) );
           fprintf (  stdout,   " " );
           rtems_monitor_dump_name (  rtems_capture_task_name (  tasks[i] ) );
           fprintf (  stdout,   " " );
           rtems_monitor_dump_priority (  priority );
           fprintf (  stdout,   " " );
           rtems_monitor_dump_priority (  rtems_capture_task_curr_priority (  tasks[i] ) );
           fprintf (  stdout,   " " );
           k = rtems_monitor_dump_state (  rtems_capture_task_state (  tasks[i] ) );
           fprintf (  stdout,   "%*c %3i.%03i%% ",   6 - k,   ' ',  
           task_load / 1000,   task_load % 1000 );
           fprintf (  stdout,   "%3i%% %c%c",   stack_used,  
           rtems_capture_task_valid (  tasks[i] ) ? 'a' : 'd',  
           rtems_capture_task_flags (  tasks[i] ) & RTEMS_CAPTURE_TRACED ? 't' : '-' );
          
           if (  (  floor > ceiling ) && (  ceiling > priority ) )
           fprintf (  stdout,   "--" );
           else
           fprintf (  stdout,   "%c%c",  
           rtems_capture_task_control (  tasks[i] ) ?
           (  rtems_capture_task_control_flags (  tasks[i] ) &
           RTEMS_CAPTURE_WATCH ? 'w' : '+' ) : '-',  
           rtems_capture_watch_global_on (   ) ? 'g' : '-' );
          
           fprintf (  stdout,   " %qi\n",   rtems_capture_task_time (  tasks[i] ) );
           }
          
           if (  count < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS )
           {
           j = RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS - count;
           while (  j > 0 )
           {
           fprintf (  stdout,   "\x1b[K\n" );
           j--;
           }
           }
          
           last_count = count;
          
           cli_load_thread_active = 0;
          
           rtems_task_wake_after (  RTEMS_MICROSECONDS_TO_TICKS (  5000000 ) );
           }
          }
          
          /*
           * rtems_capture_cli_task_load
           *
           * DESCRIPTION:
           *
           * This function is a monitor command.
           *
           */
          
          static void
     460  rtems_capture_cli_task_load (  int argc __attribute__(  (  unused ) ),  
           char** argv __attribute__(  (  unused ) ),  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
           rtems_task_priority priority;
           rtems_name name;
           rtems_id id;
          
           sc = rtems_task_set_priority (  RTEMS_SELF,   RTEMS_CURRENT_PRIORITY,   &priority );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: cannot obtain the current priority: %s\n",  
           rtems_status_text (  sc ) );
           return;
           }
          
           name = rtems_build_name(  'C',   'P',   'l',   't' );
          
           sc = rtems_task_create (  name,   priority,   4 * 1024,  
           RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,  
           RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,  
           &id );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: cannot create helper thread: %s\n",  
           rtems_status_text (  sc ) );
           return;
           }
          
           sc = rtems_task_start (  id,   rtems_capture_cli_task_load_thread,   0 );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: cannot start helper thread: %s\n",  
           rtems_status_text (  sc ) );
           rtems_task_delete (  id );
           return;
           }
          
           for (  ;; )
           {
           int c = getchar (   );
          
           if (  (  c == '\r' ) || (  c == '\n' ) )
           {
           int loops = 20;
          
           while (  loops && cli_load_thread_active )
           rtems_task_wake_after (  RTEMS_MICROSECONDS_TO_TICKS (  100000 ) );
          
           rtems_task_delete (  id );
          
           fprintf (  stdout,   "load monitoring stopped.\n" );
          
           return;
           }
           }
          }
          
          /*
           * rtems_capture_cli_watch_list
           *
           * DESCRIPTION:
           *
           * This function lists the controls in the capture engine.
           *
           */
          
          static void
     533  rtems_capture_cli_watch_list (  int argc __attribute__(  (  unused ) ),  
           char** argv __attribute__(  (  unused ) ),  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_capture_control_t* control = rtems_capture_get_control_list (   );
           rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (   );
           rtems_task_priority floor = rtems_capture_watch_get_floor (   );
          
           fprintf (  stdout,   "watch priority ceiling is %" PRId32 "\n",   ceiling );
           fprintf (  stdout,   "watch priority floor is %" PRId32 "\n",   floor );
           fprintf (  stdout,   "global watch is %s\n",  
           rtems_capture_watch_global_on (   ) ? "enabled" : "disabled" );
           fprintf (  stdout,   "total %" PRId32 "\n",   rtems_capture_control_count (   ) );
          
           while (  control )
           {
           uint32_t flags;
           int f;
           int fshowed;
           int lf;
          
           fprintf (  stdout,   " " );
           rtems_monitor_dump_id (  rtems_capture_control_id (  control ) );
           fprintf (  stdout,   " " );
           rtems_monitor_dump_name (  rtems_capture_control_name (  control ) );
           flags = rtems_capture_control_flags (  control );
           fprintf (  stdout,   " %c%c ",  
           rtems_capture_watch_global_on (   ) ? 'g' : '-',  
           flags & RTEMS_CAPTURE_WATCH ? 'w' : '-' );
           flags = rtems_capture_control_to_triggers (  control );
           fprintf (  stdout,   " T:%c%c%c%c%c%c%c",  
           flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-',  
           flags & RTEMS_CAPTURE_CREATE ? 'C' : '-',  
           flags & RTEMS_CAPTURE_START ? 'S' : '-',  
           flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',  
           flags & RTEMS_CAPTURE_DELETE ? 'D' : '-',  
           flags & RTEMS_CAPTURE_BEGIN ? 'B' : '-',  
           flags & RTEMS_CAPTURE_EXITTED ? 'E' : '-' );
           flags = rtems_capture_control_from_triggers (  control );
           fprintf (  stdout,   " F:%c%c%c%c%c",  
           flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-',  
           flags & RTEMS_CAPTURE_CREATE ? 'C' : '-',  
           flags & RTEMS_CAPTURE_START ? 'S' : '-',  
           flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',  
           flags & RTEMS_CAPTURE_DELETE ? 'D' : '-' );
          
           for (  f = 0,   fshowed = 0,   lf = 1; f < RTEMS_CAPTURE_TRIGGER_TASKS; f++ )
           {
           if (  rtems_capture_control_by_valid (  control,   f ) )
           {
           if (  lf && (  (  fshowed % 3 ) == 0 ) )
           {
           fprintf (  stdout,   "\n" );
           lf = 0;
           }
          
           fprintf (  stdout,   " %2i:",   f );
           rtems_monitor_dump_name (  rtems_capture_control_by_name (  control,   f ) );
           fprintf (  stdout,   "/" );
           rtems_monitor_dump_id (  rtems_capture_control_by_id (  control,   f ) );
           flags = rtems_capture_control_by_triggers (  control,   f );
           fprintf (  stdout,   ":%c%c%c%c%c",  
           flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-',  
           flags & RTEMS_CAPTURE_CREATE ? 'C' : '-',  
           flags & RTEMS_CAPTURE_START ? 'S' : '-',  
           flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',  
           flags & RTEMS_CAPTURE_DELETE ? 'D' : '-' );
           fshowed++;
           lf = 1;
           }
           }
          
           if (  lf )
           fprintf (  stdout,   "\n" );
          
           control = rtems_capture_next_control (  control );
           }
          }
          
          /*
           * rtems_capture_cli_get_name_id
           *
           * DESCRIPTION:
           *
           * This function checks arguments for a name or an id.
           *
           */
          
          static bool
     623  rtems_capture_cli_get_name_id (  char* arg,  
           bool* valid_name,  
           bool* valid_id,  
           rtems_name* name,  
           rtems_id* id )
          {
           size_t l;
           size_t i;
          
           if (  *valid_name && *valid_id )
           {
           fprintf (  stdout,   "error: too many arguments\n" );
           return 0;
           }
          
           /*
           * See if the arg is all hex digits.
           */
          
           l = strlen (  arg );
          
           for (  i = 0; i < l; i++ )
           if (  !isxdigit (  (  unsigned char )arg[i] ) )
           break;
          
           if (  i == l )
           {
           *id = strtoul (  arg,   0,   16 );
           *valid_id = true;
           }
           else
           {
           /*
           * This is a bit of hack but it should work on all platforms
           * as it is what the score does with names.
           *
           * @warning The extra assigns play with the byte order so do not
           * remove unless the score has been updated.
           */
           rtems_name rname;
          
           rname = rtems_build_name(  arg[0],   arg[1],   arg[2],   arg[3] );
           *name = rname;
           *valid_name = true;
           }
          
           return 1;
          }
          
          /*
           * rtems_capture_cli_watch_add
           *
           * DESCRIPTION:
           *
           * This function is a monitor command that add a watch to the capture
           * engine.
           *
           */
          
          static char const * watch_add_usage = "usage: cwadd [task name] [id]\n";
          
          static void
     685  rtems_capture_cli_watch_add (  int argc,  
           char** argv,  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
           int arg;
           rtems_name name = 0;
           rtems_id id = 0;
           bool valid_name = false;
           bool valid_id = false;
          
           if (  argc <= 1 )
           {
           fprintf (  stdout,   watch_add_usage );
           return;
           }
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           fprintf (  stdout,   "warning: option -%c ignored\n",   argv[arg][1] );
           }
           else
           {
           if (  !rtems_capture_cli_get_name_id (  argv[arg],   &valid_name,   &valid_id,  
           &name,   &id ) )
           return;
           }
           }
          
           if (  !valid_name && !valid_id )
           {
           fprintf (  stdout,   "error: no valid name or task id located\n" );
           return;
           }
          
           sc = rtems_capture_watch_add (  name,   id );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,  
           "error: watch add failed: %s\n",   rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "watch added.\n" );
          }
          
          /*
           * rtems_capture_cli_watch_del
           *
           * DESCRIPTION:
           *
           * This function is a monitor command that deletes a watch from the capture
           * engine.
           *
           */
          
          static char const * watch_del_usage = "usage: cwdel [task name] [id]\n";
          
          static void
     748  rtems_capture_cli_watch_del (  int argc,  
           char** argv,  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
           int arg;
           rtems_name name = 0;
           rtems_id id = 0;
           bool valid_name = false;
           bool valid_id = false;
          
           if (  argc <= 1 )
           {
           fprintf (  stdout,   watch_del_usage );
           return;
           }
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           fprintf (  stdout,   "warning: option -%c ignored\n",   argv[arg][1] );
           }
           else
           {
           if (  !rtems_capture_cli_get_name_id (  argv[arg],   &valid_name,   &valid_id,  
           &name,   &id ) )
           return;
           }
           }
          
           if (  !valid_name && !valid_id )
           {
           fprintf (  stdout,   "error: no valid name or task id located\n" );
           return;
           }
          
           sc = rtems_capture_watch_del (  name,   id );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: watch delete failed: %s\n",  
           rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "watch delete.\n" );
          }
          
          /*
           * rtems_capture_cli_watch_control
           *
           * DESCRIPTION:
           *
           * This function is a monitor command that controls a watch.
           *
           */
          
          static char const * watch_control_usage = "usage: cwctl [task name] [id] on/off\n";
          
          static void
     810  rtems_capture_cli_watch_control (  int argc,  
           char** argv,  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
           int arg;
           rtems_name name = 0;
           rtems_id id = 0;
           bool valid_name = false;
           bool valid_id = false;
           bool enable = false;
          
           if (  argc <= 2 )
           {
           fprintf (  stdout,   watch_control_usage );
           return;
           }
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           fprintf (  stdout,   "warning: option -%c ignored\n",   argv[arg][1] );
           }
           else
           {
           if (  strcmp (  argv[arg],   "on" ) == 0 )
           enable = true;
           else if (  strcmp (  argv[arg],   "off" ) == 0 )
           enable = false;
           else if (  !rtems_capture_cli_get_name_id (  argv[arg],   &valid_name,  
           &valid_id,   &name,   &id ) )
           return;
           }
           }
          
           if (  !valid_name && !valid_id )
           {
           fprintf (  stdout,   "error: no valid name or task id located\n" );
           return;
           }
          
           sc = rtems_capture_watch_ctrl (  name,   id,   enable );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: watch control failed: %s\n",  
           rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "watch %s.\n",   enable ? "enabled" : "disabled" );
          }
          
          /*
           * rtems_capture_cli_watch_global
           *
           * DESCRIPTION:
           *
           * This function is a monitor command that sets a global watch.
           *
           */
          
          static char const * watch_global_usage = "usage: cwglob on/off\n";
          
          static void
     877  rtems_capture_cli_watch_global (  int argc,  
           char** argv,  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
           int arg;
           bool enable = false;
          
           if (  argc <= 1 )
           {
           fprintf (  stdout,   watch_global_usage );
           return;
           }
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           fprintf (  stdout,   "warning: option -%c ignored\n",   argv[arg][1] );
           }
           else
           {
           if (  strcmp (  argv[arg],   "on" ) == 0 )
           enable = true;
           else if (  strcmp (  argv[arg],   "off" ) == 0 )
           enable = false;
           }
           }
          
           sc = rtems_capture_watch_global (  enable );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: global watch failed: %s\n",  
           rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "global watch %s.\n",   enable ? "enabled" : "disabled" );
          }
          
          /*
           * rtems_capture_cli_watch_ceiling
           *
           * DESCRIPTION:
           *
           * This function is a monitor command that sets watch ceiling.
           *
           */
          
          static char const * watch_ceiling_usage = "usage: cwceil priority\n";
          
          static void
     931  rtems_capture_cli_watch_ceiling (  int argc,  
           char** argv,  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
           int arg;
           rtems_task_priority priority = 0;
          
           if (  argc <= 1 )
           {
           fprintf (  stdout,   watch_ceiling_usage );
           return;
           }
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           fprintf (  stdout,   "warning: option -%c ignored\n",   argv[arg][1] );
           }
           else
           {
           priority = strtoul (  argv[arg],   0,   0 );
           }
           }
          
           sc = rtems_capture_watch_ceiling (  priority );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: watch ceiling failed: %s\n",  
           rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "watch ceiling is %" PRId32 ".\n",   priority );
          }
          
          /*
           * rtems_capture_cli_watch_floor
           *
           * DESCRIPTION:
           *
           * This function is a monitor command that sets watch floor.
           *
           */
          
          static char const * watch_floor_usage = "usage: cwfloor priority\n";
          
          static void
     982  rtems_capture_cli_watch_floor (  int argc,  
           char** argv,  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
           int arg;
           rtems_task_priority priority = 0;
          
           if (  argc <= 1 )
           {
           fprintf (  stdout,   watch_floor_usage );
           return;
           }
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           fprintf (  stdout,   "warning: option -%c ignored\n",   argv[arg][1] );
           }
           else
           {
           priority = strtoul (  argv[arg],   0,   0 );
           }
           }
          
           sc = rtems_capture_watch_floor (  priority );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: watch floor failed: %s\n",  
           rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "watch floor is %" PRId32 ".\n",   priority );
          }
          
          /*
           * rtems_capture_cli_trigger_worker
           *
           * DESCRIPTION:
           *
           * This function is a monitor command that sets or clears a trigger.
           *
           */
          
          static char const *trigger_set_usage =
           "usage: %s [-?] type [to name/id] [from] [from name/id]\n";
          
          static char const *trigger_set_types =
           " You can say 'type TASK' or 'type TO from FROM'\n" \
           " where TASK is the task the event is happening to\n" \
           " or you can say the event TO this task FROM this task.\n" \
           " No type defaults to 'switch'.\n" \
           " switch : context switch TASK or FROM or FROM->TO\n" \
           " create : create TASK,   or create TO from FROM\n" \
           " start : start TASK,   or start TO from FROM\n" \
           " restart : restart TASK,   or restart TO from FROM\n" \
           " delete : delete TASK or delete TO from FROM\n" \
           " begin : begin TASK\n" \
           " exitted : exitted TASK\n";
          
          /*
           * Structure to handle the parsing of the trigger command line.
           */
          typedef struct rtems_capture_cli_triggers_s
          {
           char const * name;
           rtems_capture_trigger_t type;
           int to_only;
          } rtems_capture_cli_triggers_t;
          
          static rtems_capture_cli_triggers_t rtems_capture_cli_triggers[] =
          {
           { "switch",   rtems_capture_switch,   0 },   /* must be first */
           { "create",   rtems_capture_create,   0 },  
           { "start",   rtems_capture_start,   0 },  
           { "restart",   rtems_capture_restart,   0 },  
           { "delete",   rtems_capture_delete,   0 },  
           { "begin",   rtems_capture_begin,   1 },  
           { "exitted",   rtems_capture_exitted,   1 }
          };
          
          typedef enum rtems_capture_cli_trig_state_e
          {
           trig_type,  
           trig_to,  
           trig_from_from,  
           trig_from
          } rtems_capture_cli_trig_state_t;
          
          #define RTEMS_CAPTURE_CLI_TRIGGERS_NUM \
           (  sizeof (  rtems_capture_cli_triggers ) / sizeof (  rtems_capture_cli_triggers_t ) )
          
    1078  static void
          rtems_capture_cli_trigger_worker (  int set,   int argc,   char** argv )
          {
           rtems_status_code sc;
           int arg;
           int trigger = 0; /* switch */
           rtems_capture_trigger_mode_t trigger_mode = rtems_capture_from_any;
           bool trigger_set = false;
           bool is_from = false;
           rtems_name name = 0;
           rtems_id id = 0;
           bool valid_name = false;
           bool valid_id = false;
           rtems_name from_name = 0;
           rtems_id from_id = 0;
           bool from_valid_name = false;
           bool from_valid_id = false;
           rtems_name to_name = 0;
           rtems_id to_id = 0;
           bool to_valid_name = false;
           bool to_valid_id = false;
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           switch (  argv[arg][1] )
           {
           case '?':
           fprintf (  stdout,   trigger_set_usage,   set ? "ctset" : "ctclear" );
           fprintf (  stdout,   trigger_set_types );
           return;
           default:
           fprintf (  stdout,   "warning: option -%c ignored\n",   argv[arg][1] );
           break;
           }
           }
           else
           {
           if (  !trigger_set )
           {
           bool found = false;
           int t;
          
           for (  t = 0; t < RTEMS_CAPTURE_CLI_TRIGGERS_NUM; t++ )
           if (  strcmp (  argv[arg],   rtems_capture_cli_triggers[t].name ) == 0 )
           {
           trigger = t;
           found = true;
           break;
           }
          
           trigger_set = true;
          
           /*
           * If a trigger was not found assume the default and
           * assume the parameter is a task name or id.
           */
           if (  found )
           continue;
           }
          
           if (  strcmp (  arg[argv],   "from" ) == 0 )
           {
           if (  is_from )
           fprintf (  stdout,   "warning: extra 'from' ignored\n" );
          
           is_from = 1;
           continue;
           }
          
           if (  !rtems_capture_cli_get_name_id (  argv[arg],   &valid_name,   &valid_id,  
           &name,   &id ) )
           return;
          
           if (  valid_name )
           {
           if (  is_from )
           {
           if (  !from_valid_name && !from_valid_id )
           {
           from_valid_name = true;
           from_name = name;
           }
           else
           fprintf (  stdout,   "warning: extra arguments ignored\n" );
           }
           else if (  !to_valid_name && !to_valid_id )
           {
           to_valid_name = true;
           to_name = name;
           }
           else
           fprintf (  stdout,   "warning: extra arguments ignored\n" );
           }
          
           if (  valid_id )
           {
           if (  is_from )
           {
           if (  !from_valid_name && !from_valid_id )
           {
           from_valid_id = true;
           from_id = id;
           }
           else
           fprintf (  stdout,   "warning: extra arguments ignored\n" );
           }
           else if (  !to_valid_name && !to_valid_id )
           {
           to_valid_id = true;
           to_id = id;
           }
           else
           fprintf (  stdout,   "warning: extra arguments ignored\n" );
           }
           }
           }
          
           if (  is_from && rtems_capture_cli_triggers[trigger].to_only )
           {
           fprintf (  stdout,   "error: a %s trigger can be a TO trigger\n",  
           rtems_capture_cli_triggers[trigger].name );
           return;
           }
          
           if (  !to_valid_name && !to_valid_id && !from_valid_name && !from_valid_id )
           {
           fprintf (  stdout,   trigger_set_usage );
           return;
           }
          
           if (  !is_from && !to_valid_name && !to_valid_id )
           {
           fprintf (  stdout,   "error: a %s trigger needs a TO name or id\n",  
           rtems_capture_cli_triggers[trigger].name );
           return;
           }
          
           if (  is_from && !from_valid_name && !from_valid_id )
           {
           fprintf (  stdout,   "error: a %s trigger needs a FROM name or id\n",  
           rtems_capture_cli_triggers[trigger].name );
           return;
           }
          
           if (  (  from_valid_name || from_valid_id ) && (  to_valid_name || to_valid_id ) )
           trigger_mode = rtems_capture_from_to;
           else if (  from_valid_name || from_valid_id )
           trigger_mode = rtems_capture_to_any;
           else if (  to_valid_name || to_valid_id )
           trigger_mode = rtems_capture_from_any;
          
           if (  set )
           sc = rtems_capture_set_trigger (  from_name,   from_id,   to_name,   to_id,  
           trigger_mode,  
           rtems_capture_cli_triggers[trigger].type );
           else
           sc = rtems_capture_clear_trigger (  from_name,   from_id,   to_name,   to_id,  
           trigger_mode,  
           rtems_capture_cli_triggers[trigger].type );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: %sing the trigger failed: %s\n",  
           set ? "sett" : "clear",   rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "trigger %s.\n",   set ? "set" : "cleared" );
          }
          
          /*
           * rtems_capture_cli_trigger_set
           *
           * DESCRIPTION:
           *
           * This function is a monitor command that sets a trigger.
           *
           */
          
    1259  static void
          rtems_capture_cli_trigger_set (  int argc,  
           char** argv,  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_capture_cli_trigger_worker (  1,   argc,   argv );
          }
          
          /*
           * rtems_capture_cli_trigger_clear
           *
           * DESCRIPTION:
           *
           * This function is a monitor command that clears a trigger.
           *
           */
          
    1277  static void
          rtems_capture_cli_trigger_clear (  int argc,  
           char** argv,  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_capture_cli_trigger_worker (  0,   argc,   argv );
          }
          
          /*
           * rtems_capture_cli_trace_records
           *
           * DESCRIPTION:
           *
           * This function is a monitor command that dumps trace records.
           *
           */
          
    1295  static void
          rtems_capture_cli_trace_records (  int argc,  
           char** argv,  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
           bool csv = false;
           static int dump_total = 22;
           int total;
           int count;
           uint32_t read;
           rtems_capture_record_t* rec;
           int arg;
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           if (  argv[arg][1] == 'c' )
           csv = true;
           else
           fprintf (  stdout,   "warning: option -%c ignored\n",   argv[arg][1] );
           }
           else
           {
           size_t i;
           size_t l;
          
           l = strlen (  argv[arg] );
          
           for (  i = 0; i < l; i++ )
           if (  !isdigit (  (  unsigned char )argv[arg][i] ) )
           {
           fprintf (  stdout,   "error: not a number\n" );
           return;
           }
          
           dump_total = strtoul (  argv[arg],   0,   0 );
           }
           }
          
           total = dump_total;
          
           while (  total )
           {
           sc = rtems_capture_read (  0,   0,   &read,   &rec );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: trace read failed: %s\n",   rtems_status_text (  sc ) );
           rtems_capture_flush (  0 );
           return;
           }
          
           /*
           * If we have no records then just exist. We still need to release
           * the reader lock.
           */
          
           if (  read == 0 )
           {
           rtems_capture_release (  read );
           break;
           }
          
           count = total < read ? total : read;
          
           while (  count-- )
           {
           if (  csv )
           fprintf (  stdout,   "%08" PRIxPTR ",  %03" PRIu32
           ",  %03" PRIu32 ",  %04" PRIx32 ",  %" PRId32 ",  %" PRId32 "\n",  
           (  uintptr_t ) rec->task,  
           (  rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT ) & 0xff,  
           (  rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT ) & 0xff,  
           (  rec->events >> RTEMS_CAPTURE_EVENT_START ),  
           rec->ticks,   rec->tick_offset );
           else
           {
           unsigned long long t;
           uint32_t event;
           int e;
          
           event = rec->events >> RTEMS_CAPTURE_EVENT_START;
          
           t = rec->ticks;
           t *= rtems_capture_tick_time (   );
           t += rec->tick_offset;
          
           for (  e = RTEMS_CAPTURE_EVENT_START; e < RTEMS_CAPTURE_EVENT_END; e++ )
           {
           if (  event & 1 )
           {
           fprintf (  stdout,   "%9li.%06li ",   (  unsigned long ) (  t / 1000000 ),  
           (  unsigned long ) (  t % 1000000 ) );
           rtems_monitor_dump_id (  rtems_capture_task_id (  rec->task ) );
           fprintf (  stdout,   " " );
           rtems_monitor_dump_name (  rtems_capture_task_name (  rec->task ) );
           fprintf (  stdout,   " %3" PRId32 " %3" PRId32 " %s\n",  
           (  rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT ) & 0xff,  
           (  rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT ) & 0xff,  
           rtems_capture_event_text (  e ) );
           }
           event >>= 1;
           }
           }
           rec++;
           }
          
           count = total < read ? total : read;
          
           if (  count < total )
           total -= count;
           else
           total = 0;
          
           rtems_capture_release (  count );
           }
          }
          
          /*
           * rtems_capture_cli_flush
           *
           * DESCRIPTION:
           *
           * This function is a monitor command that flushes and primes the capture
           * engine.
           *
           */
          
    1426  static void
          rtems_capture_cli_flush (  int argc,  
           char** argv,  
           const rtems_monitor_command_arg_t* command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           rtems_status_code sc;
           bool prime = true;
           int arg;
          
           for (  arg = 1; arg < argc; arg++ )
           {
           if (  argv[arg][0] == '-' )
           {
           if (  argv[arg][1] == 'n' )
           prime = false;
           else
           fprintf (  stdout,   "warning: option -%c ignored\n",   argv[arg][1] );
           }
           }
          
           sc = rtems_capture_flush (  prime );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           fprintf (  stdout,   "error: flush failed: %s\n",   rtems_status_text (  sc ) );
           return;
           }
          
           fprintf (  stdout,   "trace buffer flushed and %s.\n",  
           prime ? "primed" : "not primed" );
          }
          
          static rtems_monitor_command_entry_t rtems_capture_cli_cmds[] =
          {
           {
           "copen",  
           "usage: copen [-i] size\n",  
           0,  
           rtems_capture_cli_open,  
           { 0 },  
           0
           },  
           {
           "cclose",  
           "usage: cclose\n",  
           0,  
           rtems_capture_cli_close,  
           { 0 },  
           0
           },  
           {
           "cenable",  
           "usage: cenable\n",  
           0,  
           rtems_capture_cli_enable,  
           { 0 },  
           0
           },  
           {
           "cdisable",  
           "usage: cdisable\n",  
           0,  
           rtems_capture_cli_disable,  
           { 0 },  
           0
           },  
           {
           "ctlist",  
           "usage: ctlist \n",  
           0,  
           rtems_capture_cli_task_list,  
           { 0 },  
           0
           },  
           {
           "ctload",  
           "usage: ctload \n",  
           0,  
           rtems_capture_cli_task_load,  
           { 0 },  
           0
           },  
           {
           "cwlist",  
           "usage: cwlist\n",  
           0,  
           rtems_capture_cli_watch_list,  
           { 0 },  
           0
           },  
           {
           "cwadd",  
           "usage: cwadd [task name] [id]\n",  
           0,  
           rtems_capture_cli_watch_add,  
           { 0 },  
           0
           },  
           {
           "cwdel",  
           "usage: cwdel [task name] [id]\n",  
           0,  
           rtems_capture_cli_watch_del,  
           { 0 },  
           0
           },  
           {
           "cwctl",  
           "usage: cwctl [task name] [id] on/off\n",  
           0,  
           rtems_capture_cli_watch_control,  
           { 0 },  
           0
           },  
           {
           "cwglob",  
           "usage: cwglob on/off\n",  
           0,  
           rtems_capture_cli_watch_global,  
           { 0 },  
           0
           },  
           {
           "cwceil",  
           "usage: cwceil priority\n",  
           0,  
           rtems_capture_cli_watch_ceiling,  
           { 0 },  
           0
           },  
           {
           "cwfloor",  
           "usage: cwfloor priority\n",  
           0,  
           rtems_capture_cli_watch_floor,  
           { 0 },  
           0
           },  
           {
           "ctrace",  
           "usage: ctrace [-c] [-r records]\n",  
           0,  
           rtems_capture_cli_trace_records,  
           { 0 },  
           0
           },  
           {
           "ctset",  
           "usage: ctset -h\n",  
           0,  
           rtems_capture_cli_trigger_set,  
           { 0 },  
           0
           },  
           {
           "ctclear",  
           "usage: ctclear -?\n",  
           0,  
           rtems_capture_cli_trigger_clear,  
           { 0 },  
           0
           },  
           {
           "cflush",  
           "usage: cflush [-n]\n",  
           0,  
           rtems_capture_cli_flush,  
           { 0 },  
           0
           }
          };
          
          /*
           * rtems_capture_cli_init
           *
           * DESCRIPTION:
           *
           * This function initialises the command line interface to the capture
           * engine.
           *
           */
          
    1609  rtems_status_code
          rtems_capture_cli_init (  rtems_capture_timestamp timestamp )
          {
           size_t cmd;
          
           capture_timestamp = timestamp;
          
           for (  cmd = 0;
           cmd < sizeof (  rtems_capture_cli_cmds ) / sizeof (  rtems_monitor_command_entry_t );
           cmd++ )
           rtems_monitor_insert_cmd (  &rtems_capture_cli_cmds[cmd] );
          
           return RTEMS_SUCCESSFUL;
          }

libmisc/capture/capture.c

       1  /*
           ------------------------------------------------------------------------
           $Id: capture.c,  v 1.20 2009/11/29 12:12:39 ralf Exp $
           ------------------------------------------------------------------------
          
           Copyright Objective Design Systems Pty Ltd,   2002
           All rights reserved Objective Design Systems Pty Ltd,   2002
           Chris Johns (  ccj@acm.org )
          
           COPYRIGHT (  c ) 1989-2009.
           On-Line Applications Research Corporation (  OAR ).
          
           The license and distribution terms for this file may be
           found in the file LICENSE in this distribution.
          
           This software with is provided ``as is'' and with NO WARRANTY.
          
           ------------------------------------------------------------------------
          
           RTEMS Performance Monitoring and Measurement Framework.
          
           This is the Capture Engine component.
          
          */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          #include <string.h>
          
          #include "capture.h"
          #include <rtems/score/states.inl>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/wkspace.inl>
          
          /*
           * These events are always recorded and are not part of the
           * watch filters.
           *
           * This feature has been disabled as it becomes confusing when
           * setting up filters and some event leak.
           */
          #if defined (  RTEMS_CAPTURE_ENGINE_ALLOW_RELATED_EVENTS )
          #define RTEMS_CAPTURE_RECORD_EVENTS (  RTEMS_CAPTURE_CREATED_BY_EVENT | \
           RTEMS_CAPTURE_CREATED_EVENT | \
           RTEMS_CAPTURE_STARTED_BY_EVENT | \
           RTEMS_CAPTURE_STARTED_EVENT | \
           RTEMS_CAPTURE_RESTARTED_BY_EVENT | \
           RTEMS_CAPTURE_RESTARTED_EVENT | \
           RTEMS_CAPTURE_DELETED_BY_EVENT | \
           RTEMS_CAPTURE_DELETED_EVENT | \
           RTEMS_CAPTURE_BEGIN_EVENT | \
           RTEMS_CAPTURE_EXITTED_EVENT )
          #else
          #define RTEMS_CAPTURE_RECORD_EVENTS (  0 )
          #endif
          
          /*
           * Global capture flags.
           */
          #define RTEMS_CAPTURE_ON (  1 << 0 )
          #define RTEMS_CAPTURE_NO_MEMORY (  1 << 1 )
          #define RTEMS_CAPTURE_OVERFLOW (  1 << 2 )
          #define RTEMS_CAPTURE_TRIGGERED (  1 << 3 )
          #define RTEMS_CAPTURE_READER_ACTIVE (  1 << 4 )
          #define RTEMS_CAPTURE_READER_WAITING (  1 << 5 )
          #define RTEMS_CAPTURE_GLOBAL_WATCH (  1 << 6 )
          #define RTEMS_CAPTURE_ONLY_MONITOR (  1 << 7 )
          
          /*
           * RTEMS Capture Data.
           */
          static rtems_capture_record_t* capture_records;
          static uint32_t capture_size;
          static uint32_t capture_count;
          static rtems_capture_record_t* capture_in;
          static uint32_t capture_out;
          static uint32_t capture_flags;
          static rtems_capture_task_t* capture_tasks;
          static rtems_capture_control_t* capture_controls;
          static int capture_extension_index;
          static rtems_id capture_id;
          static rtems_capture_timestamp capture_timestamp;
          static rtems_task_priority capture_ceiling;
          static rtems_task_priority capture_floor;
          static uint32_t capture_tick_period;
          static rtems_id capture_reader;
          
          /*
           * RTEMS Event text.
           */
          static const char* capture_event_text[] =
          {
           "CREATED_BY",  
           "CREATED",  
           "STARTED_BY",  
           "STARTED",  
           "RESTARTED_BY",  
           "RESTARTED",  
           "DELETED_BY",  
           "DELETED",  
           "BEGIN",  
           "EXITTED",  
           "SWITCHED_OUT",  
           "SWITCHED_IN",  
           "TIMESTAMP"
          };
     110  
          /*
           * rtems_capture_get_time
           *
           * DESCRIPTION:
           *
           * This function returns the current time. If a handler is provided
           * by the user get the time from that.
           */
          static inline void rtems_capture_get_time (  uint32_t* ticks,  
           uint32_t* tick_offset )
          {
           if (  capture_timestamp )
           capture_timestamp (  ticks,   tick_offset );
           else
           {
           *ticks = _Watchdog_Ticks_since_boot;
           *tick_offset = 0;
           }
          }
          
          /*
           * rtems_capture_match_names
     133   *
           * DESCRIPTION:
           *
           * This function compares rtems_names. It protects the
           * capture engine from a change to the way names are supported
           * in RTEMS.
           *
           */
          static inline bool
          rtems_capture_match_names (  rtems_name lhs,   rtems_name rhs )
          {
           return lhs == rhs;
          }
          
          /*
           * rtems_capture_match_id
     149   *
           * DESCRIPTION:
           *
           * This function compares rtems_ids. It protects the
           * capture engine from a change to the way id are supported
           * in RTEMS.
           *
           */
          static inline bool
          rtems_capture_match_ids (  rtems_id lhs,   rtems_id rhs )
          {
           return lhs == rhs;
          }
     162  
          /*
           * rtems_capture_match_name_id
           *
           * DESCRIPTION:
           *
           * This function matches a name and/or id.
           */
          static inline bool
          rtems_capture_match_name_id (  rtems_name lhs_name,  
           rtems_id lhs_id,  
           rtems_name rhs_name,  
           rtems_id rhs_id )
          {
           /*
           * The left hand side name or id could be 0 which means a wildcard.
           */
           if (  (  lhs_name == 0 ) && (  lhs_id == rhs_id ) )
           return 1;
           else if (  (  lhs_id == 0 ) || (  lhs_id == rhs_id ) )
           {
           if (  rtems_capture_match_names (  lhs_name,   rhs_name ) )
           return 1;
           }
           return 0;
          }
          
          /*
           * rtems_capture_dup_name
     191   *
           * DESCRIPTION:
           *
           * This function duplicates an rtems_names. It protects the
           * capture engine from a change to the way names are supported
           * in RTEMS.
           *
           */
          static inline void
          rtems_capture_dup_name (  rtems_name* dst,   rtems_name src )
          {
           *dst = src;
          }
          
          /*
           * rtems_capture_by_in_to
     207   *
           * DESCRIPTION:
           *
           * This function sees if a BY control is in the BY names. The use
           * of the valid_mask in this way assumes the number of trigger
           * tasks is the number of bits in uint32_t.
           *
           */
          static inline bool
          rtems_capture_by_in_to (  uint32_t events,  
           rtems_capture_task_t* by,  
           rtems_capture_control_t* to )
          {
           uint32_t valid_mask = RTEMS_CAPTURE_CONTROL_FROM_MASK (  0 );
           uint32_t valid_remainder = 0xffffffff;
           int i;
          
           for (  i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++ )
           {
           /*
           * If there are no more valid BY entries then
           * we are finished.
           */
           if (  (  valid_remainder & to->by_valid ) == 0 )
           break;
          
           /*
           * Is the froby entry valid and does its name or id match.
           */
           if (  (  valid_mask & to->by_valid ) &&
           (  to->by[i].trigger & events ) )
           {
           /*
           * We have the BY task on the right hand side so we
           * match with id's first then labels if the id's are
           * not set.
           */
           if (  rtems_capture_match_name_id (  to->by[i].name,   to->by[i].id,  
           by->name,   by->id ) )
           return 1;
           }
          
           valid_mask >>= 1;
           valid_remainder >>= 1;
           }
          
           return 0;
          }
          
     256  /*
           * rtems_capture_refcount_up
           *
           * DESCRIPTION:
           *
           * This function raises the reference count.
           *
           */
          static inline void
          rtems_capture_refcount_up (  rtems_capture_task_t* task )
          {
           task->refcount++;
          }
          
          /*
     271   * rtems_capture_refcount_down
           *
           * DESCRIPTION:
           *
           * This function lowers the reference count and if the count
           * reaches 0 the task control block is returned to the heap.
           *
           */
          static inline void
          rtems_capture_refcount_down (  rtems_capture_task_t* task )
          {
           if (  task->refcount )
           task->refcount--;
          }
     285  
          /*
           * rtems_capture_init_stack_usage
           *
           * DESCRIPTION:
           *
           * This function setups a stack so its usage can be monitored.
           */
          static inline void
          rtems_capture_init_stack_usage (  rtems_capture_task_t* task )
          {
           if (  task->tcb )
           {
           uint32_t* s;
           uint32_t i;
          
           task->stack_size = task->tcb->Start.Initial_stack.size;
           task->stack_clean = task->stack_size;
          
           s = task->tcb->Start.Initial_stack.area;
          
           for (  i = 0; i < (  task->stack_size - 128 ); i += 4 )
           *(  s++ ) = 0xdeaddead;
           }
          }
          
     311  /*
           * rtems_capture_find_control
           *
           * DESCRIPTION:
           *
           * This function searches for a trigger given a name.
           *
           */
          static inline rtems_capture_control_t*
          rtems_capture_find_control (  rtems_name name,   rtems_id id )
          {
           rtems_capture_control_t* control;
          
           for (  control = capture_controls; control != NULL; control = control->next )
           if (  rtems_capture_match_name_id (  name,   id,   control->name,   control->id ) )
           break;
           return control;
          }
          
     330  /*
           * rtems_capture_create_control
           *
           * DESCRIPTION:
           *
           * This function creates a capture control for the capture engine.
           *
           */
          static inline rtems_capture_control_t*
          rtems_capture_create_control (  rtems_name name,   rtems_id id )
          {
           rtems_interrupt_level level;
           rtems_capture_control_t* control;
           rtems_capture_task_t* task;
          
           if (  (  name == 0 ) && (  id == 0 ) )
           return NULL;
          
           control = rtems_capture_find_control (  name,   id );
          
           if (  control == NULL )
           {
           control = _Workspace_Allocate (  sizeof (  rtems_capture_control_t ) );
          
           if (  control == NULL )
           {
           capture_flags |= RTEMS_CAPTURE_NO_MEMORY;
           return NULL;
           }
          
           control->name = name;
           control->id = id;
           control->flags = 0;
           control->to_triggers = 0;
           control->from_triggers = 0;
           control->by_valid = 0;
          
           memset (  control->by,   0,   sizeof (  control->by ) );
          
           rtems_interrupt_disable (  level );
          
           control->next = capture_controls;
           capture_controls = control;
          
           /*
           * We need to scan the task list as set the control to the
           * tasks.
           */
           for (  task = capture_tasks; task != NULL; task = task->forw )
           if (  rtems_capture_match_name_id (  name,   id,   task->name,   task->id ) )
           task->control = control;
          
           rtems_interrupt_enable (  level );
           }
          
           return control;
          }
          
     388  /*
           * rtems_capture_create_capture_task
           *
           * DESCRIPTION:
           *
           * This function create the task control.
           *
           */
          static inline rtems_capture_task_t*
          rtems_capture_create_capture_task (  rtems_tcb* new_task )
          {
           rtems_interrupt_level level;
           rtems_capture_task_t* task;
           rtems_capture_control_t* control;
           rtems_name name;
          
           task = _Workspace_Allocate (  sizeof (  rtems_capture_task_t ) );
          
           if (  task == NULL )
           {
           capture_flags |= RTEMS_CAPTURE_NO_MEMORY;
           return NULL;
           }
          
           /*
           * Check the type of name the object has.
           */
          
           rtems_object_get_classic_name(   new_task->Object.id,   &name  );
          
           rtems_capture_dup_name (  &task->name,   name );
          
           task->id = new_task->Object.id;
           task->flags = 0;
           task->in = 0;
           task->refcount = 0;
           task->out = 0;
           task->tcb = new_task;
           task->ticks = 0;
           task->tick_offset = 0;
           task->ticks_in = 0;
           task->tick_offset_in = 0;
           task->control = 0;
           task->last_ticks = 0;
           task->last_tick_offset = 0;
          
           task->tcb->extensions[capture_extension_index] = task;
          
           task->start_priority = new_task->Start.initial_priority;
           task->stack_size = new_task->Start.Initial_stack.size;
           task->stack_clean = task->stack_size;
          
           rtems_interrupt_disable (  level );
          
           task->forw = capture_tasks;
           if (  task->forw )
           task->forw->back = task;
           task->back = NULL;
           capture_tasks = task;
          
           rtems_interrupt_enable (  level );
          
           /*
           * We need to scan the default control list to initialise
           * this control.
           */
          
           for (  control = capture_controls; control != NULL; control = control->next )
           if (  rtems_capture_match_name_id (  control->name,   control->id,  
           task->name,   task->id ) )
           task->control = control;
          
           return task;
          }
          
          /*
           * rtems_capture_destroy_capture_task
     465   *
           * DESCRIPTION:
           *
           * This function destroy the task structure if the reference count
           * is 0 and the tcb has been cleared signalling the task has been
           * deleted.
           *
           */
          static inline void
          rtems_capture_destroy_capture_task (  rtems_capture_task_t* task )
          {
           if (  task )
           {
           rtems_interrupt_level level;
          
           rtems_interrupt_disable (  level );
          
           if (  task->tcb || task->refcount )
           task = 0;
          
           if (  task )
           {
           if (  task->forw )
           task->forw->back = task->back;
           if (  task->back )
           task->back->forw = task->forw;
           else
           capture_tasks = task->forw;
           }
          
           rtems_interrupt_enable (  level );
          
           if (  task )
           _Workspace_Free (  task );
           }
          }
          
     502  /*
           * rtems_capture_record
           *
           * DESCRIPTION:
           *
           * This function records a capture record into the capture buffer.
           *
           */
          static inline void
          rtems_capture_record (  rtems_capture_task_t* task,  
           uint32_t events )
          {
           /*
           * Check the watch state if we have a task control,   and
           * the task's real priority is lower or equal to the ceiling.
           */
           if (  task &&
           (  (  capture_flags &
           (  RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_ONLY_MONITOR ) ) ==
           RTEMS_CAPTURE_TRIGGERED ) )
           {
           rtems_capture_control_t* control;
          
           control = task->control;
          
           /*
           * Capure the record if we have an event that is always
           * captured,   or the task's real priority is greater than the
           * watch ceiling,   and the global watch or task watch is enabled.
           */
          
           if (  (  events & RTEMS_CAPTURE_RECORD_EVENTS ) ||
           (  (  task->tcb->real_priority >= capture_ceiling ) &&
           (  task->tcb->real_priority <= capture_floor ) &&
           (  (  capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH ) ||
           (  control && (  control->flags & RTEMS_CAPTURE_WATCH ) ) ) ) )
           {
           rtems_interrupt_level level;
          
           rtems_interrupt_disable (  level );
          
           if (  capture_count < capture_size )
           {
           capture_count++;
           capture_in->task = task;
           capture_in->events = (  events |
           (  task->tcb->real_priority ) |
           (  task->tcb->current_priority << 8 ) );
          
           if (  (  events & RTEMS_CAPTURE_RECORD_EVENTS ) == 0 )
           task->flags |= RTEMS_CAPTURE_TRACED;
          
           rtems_capture_get_time (  &capture_in->ticks,   &capture_in->tick_offset );
          
           if (  capture_in == &capture_records[capture_size - 1] )
           capture_in = capture_records;
           else
           capture_in++;
          
           rtems_capture_refcount_up (  task );
           }
           else
           capture_flags |= RTEMS_CAPTURE_OVERFLOW;
           rtems_interrupt_enable (  level );
           }
           }
          }
          
     570  /*
           * rtems_capture_trigger
           *
           * DESCRIPTION:
           *
           * See if we have triggered and if not see if this event is a
           * cause of a trigger.
           */
          bool
          rtems_capture_trigger (  rtems_capture_task_t* ft,  
           rtems_capture_task_t* tt,  
           uint32_t events )
          {
           /*
           * If we have not triggered then see if this is a trigger condition.
           */
           if (  !(  capture_flags & RTEMS_CAPTURE_TRIGGERED ) )
           {
           rtems_capture_control_t* fc = NULL;
           rtems_capture_control_t* tc = NULL;
           uint32_t from_events = 0;
           uint32_t to_events = 0;
           uint32_t from_to_events = 0;
          
           if (  ft )
           {
           fc = ft->control;
           if (  fc )
           from_events = fc->from_triggers & events;
           }
          
           if (  tt )
           {
           tc = tt->control;
           if (  tc )
           {
           to_events = tc->to_triggers & events;
           if (  ft && tc->by_valid )
           from_to_events = tc->by_triggers & events;
           }
           }
          
           /*
           * Check if we have any from or to events. These are the
           * from any or to any type triggers. All from/to triggers are
           * listed in the to's control with the from in the from list.
           *
           * The masking above means any flag set is a trigger.
           */
           if (  from_events || to_events )
           {
           capture_flags |= RTEMS_CAPTURE_TRIGGERED;
           return 1;
           }
          
           /*
           * Check the from->to events.
           */
           if (  from_to_events )
           {
           if (  rtems_capture_by_in_to (  events,   ft,   tc ) )
           {
           capture_flags |= RTEMS_CAPTURE_TRIGGERED;
           return 1;
           }
           }
          
           return 0;
           }
          
           return 1;
          }
          
     643  /*
           * rtems_capture_create_task
           *
           * DESCRIPTION:
           *
           * This function is called when a task is created.
           *
           */
          static bool
          rtems_capture_create_task (  rtems_tcb* current_task,  
           rtems_tcb* new_task )
          {
           rtems_capture_task_t* ct;
           rtems_capture_task_t* nt;
          
           ct = current_task->extensions[capture_extension_index];
          
           /*
           * The task pointers may not be known as the task may have
           * been created before the capture engine was open. Add them.
           */
          
           if (  ct == NULL )
           ct = rtems_capture_create_capture_task (  current_task );
          
           /*
           * Create the new task's capture control block.
           */
           nt = rtems_capture_create_capture_task (  new_task );
          
           if (  rtems_capture_trigger (  ct,   nt,   RTEMS_CAPTURE_CREATE ) )
           {
           rtems_capture_record (  ct,   RTEMS_CAPTURE_CREATED_BY_EVENT );
           rtems_capture_record (  nt,   RTEMS_CAPTURE_CREATED_EVENT );
           }
          
           return 1 == 1;
          }
          
     682  /*
           * rtems_capture_start_task
           *
           * DESCRIPTION:
           *
           * This function is called when a task is started.
           *
           */
          static void
          rtems_capture_start_task (  rtems_tcb* current_task,  
           rtems_tcb* started_task )
          {
           /*
           * Get the capture task control block so we can trace this
           * event.
           */
           rtems_capture_task_t* ct;
           rtems_capture_task_t* st;
          
           ct = current_task->extensions[capture_extension_index];
           st = started_task->extensions[capture_extension_index];
          
           /*
           * The task pointers may not be known as the task may have
           * been created before the capture engine was open. Add them.
           */
          
           if (  ct == NULL )
           ct = rtems_capture_create_capture_task (  current_task );
          
           if (  st == NULL )
           st = rtems_capture_create_capture_task (  started_task );
          
           if (  rtems_capture_trigger (  ct,   st,   RTEMS_CAPTURE_START ) )
           {
           rtems_capture_record (  ct,   RTEMS_CAPTURE_STARTED_BY_EVENT );
           rtems_capture_record (  st,   RTEMS_CAPTURE_STARTED_EVENT );
           }
          
           rtems_capture_init_stack_usage (  st );
          }
          
     724  /*
           * rtems_capture_restart_task
           *
           * DESCRIPTION:
           *
           * This function is called when a task is restarted.
           *
           */
          static void
          rtems_capture_restart_task (  rtems_tcb* current_task,  
           rtems_tcb* restarted_task )
          {
           /*
           * Get the capture task control block so we can trace this
           * event.
           */
           rtems_capture_task_t* ct;
           rtems_capture_task_t* rt;
          
           ct = current_task->extensions[capture_extension_index];
           rt = restarted_task->extensions[capture_extension_index];
          
           /*
           * The task pointers may not be known as the task may have
           * been created before the capture engine was open. Add them.
           */
          
           if (  ct == NULL )
           ct = rtems_capture_create_capture_task (  current_task );
          
           if (  rt == NULL )
           rt = rtems_capture_create_capture_task (  restarted_task );
          
           if (  rtems_capture_trigger (  ct,   rt,   RTEMS_CAPTURE_RESTART ) )
           {
           rtems_capture_record (  ct,   RTEMS_CAPTURE_RESTARTED_BY_EVENT );
           rtems_capture_record (  rt,   RTEMS_CAPTURE_RESTARTED_EVENT );
           }
          
           rtems_capture_task_stack_usage (  rt );
           rtems_capture_init_stack_usage (  rt );
          }
          
     767  /*
           * rtems_capture_delete_task
           *
           * DESCRIPTION:
           *
           * This function is called when a task is deleted.
           *
           */
          static void
          rtems_capture_delete_task (  rtems_tcb* current_task,  
           rtems_tcb* deleted_task )
          {
           /*
           * Get the capture task control block so we can trace this
           * event.
           */
           rtems_capture_task_t* ct;
           rtems_capture_task_t* dt;
          
           /*
           * The task pointers may not be known as the task may have
           * been created before the capture engine was open. Add them.
           */
          
           ct = current_task->extensions[capture_extension_index];
           dt = deleted_task->extensions[capture_extension_index];
          
           if (  ct == NULL )
           ct = rtems_capture_create_capture_task (  current_task );
          
           if (  dt == NULL )
           dt = rtems_capture_create_capture_task (  deleted_task );
          
           if (  rtems_capture_trigger (  ct,   dt,   RTEMS_CAPTURE_DELETE ) )
           {
           rtems_capture_record (  ct,   RTEMS_CAPTURE_DELETED_BY_EVENT );
           rtems_capture_record (  dt,   RTEMS_CAPTURE_DELETED_EVENT );
           }
          
           rtems_capture_task_stack_usage (  dt );
          
           /*
           * This task's tcb will be invalid. This signals the
           * task has been deleted.
           */
           dt->tcb = 0;
          
           rtems_capture_destroy_capture_task (  dt );
          }
          
     817  /*
           * rtems_capture_begin_task
           *
           * DESCRIPTION:
           *
           * This function is called when a task is begun.
           *
           */
          static void
          rtems_capture_begin_task (  rtems_tcb* begin_task )
          {
           /*
           * Get the capture task control block so we can trace this
           * event.
           */
           rtems_capture_task_t* bt;
          
           bt = begin_task->extensions[capture_extension_index];
          
           /*
           * The task pointers may not be known as the task may have
           * been created before the capture engine was open. Add them.
           */
          
           if (  bt == NULL )
           bt = rtems_capture_create_capture_task (  begin_task );
          
           if (  rtems_capture_trigger (  NULL,   bt,   RTEMS_CAPTURE_BEGIN ) )
           rtems_capture_record (  bt,   RTEMS_CAPTURE_BEGIN_EVENT );
          }
          
          /*
     849   * rtems_capture_exitted_task
           *
           * DESCRIPTION:
           *
           * This function is called when a task is exitted. That is
           * returned rather than was deleted.
           *
           */
          static void
          rtems_capture_exitted_task (  rtems_tcb* exitted_task )
          {
           /*
           * Get the capture task control block so we can trace this
           * event.
           */
           rtems_capture_task_t* et;
          
           et = exitted_task->extensions[capture_extension_index];
          
           /*
           * The task pointers may not be known as the task may have
           * been created before the capture engine was open. Add them.
           */
          
           if (  et == NULL )
           et = rtems_capture_create_capture_task (  exitted_task );
          
           if (  rtems_capture_trigger (  NULL,   et,   RTEMS_CAPTURE_EXITTED ) )
           rtems_capture_record (  et,   RTEMS_CAPTURE_EXITTED_EVENT );
          
           rtems_capture_task_stack_usage (  et );
          }
          
     882  /*
           * rtems_capture_switch_task
           *
           * DESCRIPTION:
           *
           * This function is called when a context is switched.
           *
           */
          static void
          rtems_capture_switch_task (  rtems_tcb* current_task,  
           rtems_tcb* heir_task )
          {
           /*
           * Only perform context switch trace processing if tracing is
           * enabled.
           */
           if (  capture_flags & RTEMS_CAPTURE_ON )
           {
           uint32_t ticks;
           uint32_t tick_offset;
          
           /*
           * Get the cpature task control block so we can update the
           * reference and perform any watch or trigger functions.
           * The task pointers may not be known as the task may have
           * been created before the capture engine was open. Add them.
           */
           rtems_capture_task_t* ct;
           rtems_capture_task_t* ht;
          
           if (  _States_Is_transient (  current_task->current_state ) )
           {
           rtems_id ct_id = current_task->Object.id;
          
           for (  ct = capture_tasks; ct; ct = ct->forw )
           if (  ct->id == ct_id )
           break;
           }
           else
           {
           ct = current_task->extensions[capture_extension_index];
          
           if (  ct == NULL )
           ct = rtems_capture_create_capture_task (  current_task );
           }
          
           ht = heir_task->extensions[capture_extension_index];
          
           if (  ht == NULL )
           ht = rtems_capture_create_capture_task (  heir_task );
          
           /*
           * Update the execution time. Assume the tick will not overflow
           * for now. This may need to change.
           */
           rtems_capture_get_time (  &ticks,   &tick_offset );
          
           /*
           * We could end up with null pointers for both the current task
           * and the heir task.
           */
          
           if (  ht )
           {
           ht->in++;
           ht->ticks_in = ticks;
           ht->tick_offset_in = tick_offset;
           }
          
           if (  ct )
           {
           ct->out++;
           ct->ticks += ticks - ct->ticks_in;
          
           if (  capture_timestamp )
           {
           tick_offset += capture_tick_period - ct->tick_offset_in;
          
           if (  tick_offset < capture_tick_period )
           ct->tick_offset = tick_offset;
           else
           {
           ct->ticks++;
           ct->tick_offset = tick_offset - capture_tick_period;
           }
           }
           else
           {
           ct->tick_offset += 100;
           }
           }
          
           if (  rtems_capture_trigger (  ct,   ht,   RTEMS_CAPTURE_SWITCH ) )
           {
           rtems_capture_record (  ct,   RTEMS_CAPTURE_SWITCHED_OUT_EVENT );
           rtems_capture_record (  ht,   RTEMS_CAPTURE_SWITCHED_IN_EVENT );
           }
           }
          }
          
          /*
     983   * rtems_capture_open
           *
           * DESCRIPTION:
           *
           * This function initialises the realtime capture engine allocating the trace
           * buffer. It is assumed we have a working heap at stage of initialisation.
           *
           */
          rtems_status_code
          rtems_capture_open (  uint32_t size,   rtems_capture_timestamp timestamp __attribute__(  (  unused ) ) )
          {
           rtems_extensions_table capture_extensions;
           rtems_name name;
           rtems_status_code sc;
          
           /*
           * See if the capture engine is already open.
           */
          
           if (  capture_records )
           return RTEMS_RESOURCE_IN_USE;
          
           capture_records = malloc (  size * sizeof (  rtems_capture_record_t ) );
          
           if (  capture_records == NULL )
           return RTEMS_NO_MEMORY;
          
           capture_size = size;
           capture_count = 0;
           capture_in = capture_records;
           capture_out = 0;
           capture_flags = 0;
           capture_tasks = NULL;
           capture_ceiling = 0;
           capture_floor = 255;
          
           /*
           * Create the extension table. This is copied so we
           * can create it as a local.
           */
           capture_extensions.thread_create = rtems_capture_create_task;
           capture_extensions.thread_start = rtems_capture_start_task;
           capture_extensions.thread_restart = rtems_capture_restart_task;
           capture_extensions.thread_delete = rtems_capture_delete_task;
           capture_extensions.thread_switch = rtems_capture_switch_task;
           capture_extensions.thread_begin = rtems_capture_begin_task;
           capture_extensions.thread_exitted = rtems_capture_exitted_task;
           capture_extensions.fatal = NULL;
          
           /*
           * Get the tick period from the BSP Configuration Table.
           */
           capture_tick_period = Configuration.microseconds_per_tick;
          
           /*
           * Register the user extension handlers for the CAPture Engine.
           */
           name = rtems_build_name (  'C',   'A',   'P',   'E' );
           sc = rtems_extension_create (  name,   &capture_extensions,   &capture_id );
          
           if (  sc != RTEMS_SUCCESSFUL )
           {
           capture_id = 0;
           free (  capture_records );
           capture_records = NULL;
           }
           else
           {
           capture_extension_index = rtems_object_id_get_index (  capture_id );;
           }
          
           /*
           * Iterate over the list of existing tasks.
           */
          
           return sc;
          }
          
    1061  /*
           * rtems_capture_close
           *
           * DESCRIPTION:
           *
           * This function shutdowns the capture engine and release any claimed
           * resources.
           */
          rtems_status_code
          rtems_capture_close (  void )
          {
           rtems_interrupt_level level;
           rtems_capture_task_t* task;
           rtems_capture_control_t* control;
           rtems_capture_record_t* records;
           rtems_status_code sc;
          
           rtems_interrupt_disable (  level );
          
           if (  !capture_records )
           {
           rtems_interrupt_enable (  level );
           return RTEMS_SUCCESSFUL;
           }
          
           capture_flags &= ~(  RTEMS_CAPTURE_ON | RTEMS_CAPTURE_ONLY_MONITOR );
          
           records = capture_records;
           capture_records = NULL;
          
           rtems_interrupt_enable (  level );
          
           /*
           * Delete the extension first. This means we are now able to
           * release the resources we have without them being used.
           */
          
           sc = rtems_extension_delete (  capture_id );
          
           if (  sc != RTEMS_SUCCESSFUL )
           return sc;
          
           task = capture_tasks;
          
           while (  task )
           {
           rtems_capture_task_t* delete = task;
           task = task->forw;
           _Workspace_Free (  delete );
           }
          
           capture_tasks = NULL;
          
           control = capture_controls;
          
           while (  control )
           {
           rtems_capture_control_t* delete = control;
           control = control->next;
           _Workspace_Free (  delete );
           }
          
           capture_controls = NULL;
          
           if (  capture_records )
           {
           free (  capture_records );
           capture_records = NULL;
           }
          
           return RTEMS_SUCCESSFUL;
          }
    1133  
          /*
           * rtems_capture_control
           *
           * DESCRIPTION:
           *
           * This function allows control of tracing at a global level.
           */
          rtems_status_code
          rtems_capture_control (  bool enable )
          {
           rtems_interrupt_level level;
          
           rtems_interrupt_disable (  level );
          
           if (  !capture_records )
           {
           rtems_interrupt_enable (  level );
           return RTEMS_UNSATISFIED;
           }
          
           if (  enable )
           capture_flags |= RTEMS_CAPTURE_ON;
           else
           capture_flags &= ~RTEMS_CAPTURE_ON;
          
           rtems_interrupt_enable (  level );
          
           return RTEMS_SUCCESSFUL;
          }
          
          /*
    1165   * rtems_capture_monitor
           *
           * DESCRIPTION:
           *
           * This function enable the monitor mode. When in the monitor mode
           * the tasks are monitored but no data is saved. This can be used
           * to profile the load on a system.
           */
          rtems_status_code
          rtems_capture_monitor (  bool enable )
          {
           rtems_interrupt_level level;
          
           rtems_interrupt_disable (  level );
          
           if (  !capture_records )
           {
           rtems_interrupt_enable (  level );
           return RTEMS_UNSATISFIED;
           }
          
           if (  enable )
           capture_flags |= RTEMS_CAPTURE_ONLY_MONITOR;
           else
           capture_flags &= ~RTEMS_CAPTURE_ONLY_MONITOR;
          
           rtems_interrupt_enable (  level );
          
           return RTEMS_SUCCESSFUL;
          }
          
    1196  /*
           * rtems_capture_flush
           *
           * DESCRIPTION:
           *
           * This function flushes the capture buffer. The prime parameter allows the
           * capture engine to also be primed again.
           */
          rtems_status_code
          rtems_capture_flush (  bool prime )
          {
           rtems_interrupt_level level;
           rtems_capture_task_t* task;
          
           rtems_interrupt_disable (  level );
          
           for (  task = capture_tasks; task != NULL; task = task->forw )
           {
           task->flags &= ~RTEMS_CAPTURE_TRACED;
           task->refcount = 0;
           }
          
           if (  prime )
           capture_flags &= ~(  RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW );
           else
           capture_flags &= ~RTEMS_CAPTURE_OVERFLOW;
          
           capture_count = 0;
           capture_in = capture_records;
           capture_out = 0;
          
           rtems_interrupt_enable (  level );
          
           task = capture_tasks;
          
           while (  task )
           {
           rtems_capture_task_t* check = task;
           task = task->forw;
           rtems_capture_destroy_capture_task (  check );
           }
          
           return RTEMS_SUCCESSFUL;
          }
          
          /*
           * rtems_capture_watch_add
    1243   *
           * DESCRIPTION:
           *
           * This function defines a watch for a specific task given a name. A watch
           * causes it to be traced either in or out of context. The watch can be
           * optionally enabled or disabled with the set routine. It is disabled by
           * default.
           */
          rtems_status_code
          rtems_capture_watch_add (  rtems_name name,   rtems_id id )
          {
           rtems_capture_control_t* control;
          
           if (  (  name == 0 ) && (  id == 0 ) )
           return RTEMS_UNSATISFIED;
          
           control = rtems_capture_find_control (  name,   id );
          
           if (  control && !id )
           return RTEMS_TOO_MANY;
          
           if (  !control )
           control = rtems_capture_create_control (  name,   id );
          
           if (  !control )
           return RTEMS_NO_MEMORY;
          
           return RTEMS_SUCCESSFUL;
          }
          
          /*
    1274   * rtems_capture_watch_del
           *
           * DESCRIPTION:
           *
           * This function removes a watch for a specific task given a name. The task
           * description will still exist if referenced by a trace record in the trace
           * buffer or a global watch is defined.
           */
          rtems_status_code
          rtems_capture_watch_del (  rtems_name name,   rtems_id id )
          {
           rtems_interrupt_level level;
           rtems_capture_control_t* control;
           rtems_capture_control_t** prev_control;
           rtems_capture_task_t* task;
           bool found = false;
          
           /*
           * Should this test be for wildcards ?
           */
          
           for (  prev_control = &capture_controls,   control = capture_controls;
           control != NULL;  )
           {
           if (  rtems_capture_match_name_id (  control->name,   control->id,   name,   id ) )
           {
           rtems_interrupt_disable (  level );
          
           for (  task = capture_tasks; task != NULL; task = task->forw )
           if (  task->control == control )
           task->control = 0;
          
           *prev_control = control->next;
          
           rtems_interrupt_enable (  level );
          
           _Workspace_Free (  control );
          
           control = *prev_control;
          
           found = true;
           }
           else
           {
           prev_control = &control->next;
           control = control->next;
           }
           }
          
           if (  found )
           return RTEMS_SUCCESSFUL;
          
           return RTEMS_INVALID_NAME;
          }
          
    1329  /*
           * rtems_capture_watch_set
           *
           * DESCRIPTION:
           *
           * This function allows control of a watch. The watch can be enabled or
           * disabled.
           */
          rtems_status_code
          rtems_capture_watch_ctrl (  rtems_name name,   rtems_id id,   bool enable )
          {
           rtems_interrupt_level level;
           rtems_capture_control_t* control;
           bool found = false;
          
           /*
           * Find the control and then set the watch. It must exist before it can
           * be controlled.
           */
           for (  control = capture_controls; control != NULL; control = control->next )
           {
           if (  rtems_capture_match_name_id (  control->name,   control->id,   name,   id ) )
           {
           rtems_interrupt_disable (  level );
          
           if (  enable )
           control->flags |= RTEMS_CAPTURE_WATCH;
           else
           control->flags &= ~RTEMS_CAPTURE_WATCH;
          
           rtems_interrupt_enable (  level );
          
           found = true;
           }
           }
          
           if (  found )
           return RTEMS_SUCCESSFUL;
          
           return RTEMS_INVALID_NAME;
          }
          
          /*
    1372   * rtems_capture_watch_global
           *
           * DESCRIPTION:
           *
           * This function allows control of a global watch. The watch can be enabled or
           * disabled. A global watch configures all tasks below the ceiling and above
           * the floor to be traced.
           */
          rtems_status_code
          rtems_capture_watch_global (  bool enable )
          {
           rtems_interrupt_level level;
          
           rtems_interrupt_disable (  level );
          
           /*
           * We need to keep specific and global watches separate so
           * a global enable/disable does not lose a specific watch.
           */
           if (  enable )
           capture_flags |= RTEMS_CAPTURE_GLOBAL_WATCH;
           else
           capture_flags &= ~RTEMS_CAPTURE_GLOBAL_WATCH;
          
           rtems_interrupt_enable (  level );
          
           return RTEMS_SUCCESSFUL;
          }
    1400  
          /*
           * rtems_capture_watch_global_on
           *
           * DESCRIPTION:
           *
           * This function returns the global watch state.
           */
          bool
          rtems_capture_watch_global_on (  void )
          {
           return capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0;
          }
          
          /*
           * rtems_capture_watch_ceiling
    1416   *
           * DESCRIPTION:
           *
           * This function sets a watch ceiling. Tasks at or greating that the
           * ceiling priority are not watched. This is a simple way to monitor
           * an application and exclude system tasks running at a higher
           * priority level.
           */
          rtems_status_code
          rtems_capture_watch_ceiling (  rtems_task_priority ceiling )
          {
           capture_ceiling = ceiling;
           return RTEMS_SUCCESSFUL;
          }
    1430  
          /*
           * rtems_capture_watch_get_ceiling
           *
           * DESCRIPTION:
           *
           * This function gets the watch ceiling.
           */
          rtems_task_priority
          rtems_capture_watch_get_ceiling (  void )
          {
           return capture_ceiling;
          }
          
          /*
           * rtems_capture_watch_floor
    1446   *
           * DESCRIPTION:
           *
           * This function sets a watch floor. Tasks at or less that the
           * floor priority are not watched. This is a simple way to monitor
           * an application and exclude system tasks running at a lower
           * priority level.
           */
          rtems_status_code
          rtems_capture_watch_floor (  rtems_task_priority floor )
          {
           capture_floor = floor;
           return RTEMS_SUCCESSFUL;
          }
    1460  
          /*
           * rtems_capture_watch_get_floor
           *
           * DESCRIPTION:
           *
           * This function gets the watch floor.
           */
          rtems_task_priority
          rtems_capture_watch_get_floor (  void )
          {
           return capture_floor;
          }
          
    1474  /*
           * rtems_capture_map_trigger
           *
           * DESCRIPTION:
           *
           * Map the trigger to a bit mask.
           *
           */
          uint32_t
          rtems_capture_map_trigger (  rtems_capture_trigger_t trigger )
          {
           /*
           * Transform the mode and trigger to a bit map.
           */
           switch (  trigger )
           {
           case rtems_capture_switch:
           return RTEMS_CAPTURE_SWITCH;
           case rtems_capture_create:
           return RTEMS_CAPTURE_CREATE;
           case rtems_capture_start:
           return RTEMS_CAPTURE_START;
           case rtems_capture_restart:
           return RTEMS_CAPTURE_RESTART;
           case rtems_capture_delete:
           return RTEMS_CAPTURE_DELETE;
           case rtems_capture_begin:
           return RTEMS_CAPTURE_BEGIN;
           case rtems_capture_exitted:
           return RTEMS_CAPTURE_EXITTED;
           default:
           break;
           }
           return 0;
          }
          
          /*
           * rtems_capture_set_trigger
           *
           * DESCRIPTION:
           *
           * This function sets a trigger.
           *
    1517   * This set trigger routine will create a capture control for the
           * target task. The task list is searched and any existing tasks
           * are linked to the new control.
           *
           * We can have a number of tasks that have the same name so we
           * search using names. This means a number of tasks can be
           * linked to single control.
           */
          rtems_status_code
          rtems_capture_set_trigger (  rtems_name from_name,  
           rtems_id from_id,  
           rtems_name to_name,  
           rtems_id to_id,  
           rtems_capture_trigger_mode_t mode,  
           rtems_capture_trigger_t trigger )
          {
           rtems_capture_control_t* control;
           uint32_t flags;
          
           flags = rtems_capture_map_trigger (  trigger );
          
           /*
           * The mode sets the opposite type of trigger. For example
           * FROM ANY means trigger when the event happens TO this
           * task. TO ANY means FROM this task.
           */
          
           if (  mode == rtems_capture_to_any )
           {
           control = rtems_capture_create_control (  from_name,   from_id );
           if (  control == NULL )
           return RTEMS_NO_MEMORY;
           control->from_triggers |= flags & RTEMS_CAPTURE_FROM_TRIGS;
           }
           else
           {
           control = rtems_capture_create_control (  to_name,   to_id );
           if (  control == NULL )
           return RTEMS_NO_MEMORY;
           if (  mode == rtems_capture_from_any )
           control->to_triggers |= flags;
           else
           {
           bool done = false;
           int i;
          
           control->by_triggers |= flags;
          
           for (  i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++ )
           {
           if (  rtems_capture_control_by_valid (  control,   i ) &&
           (  (  control->by[i].name == from_name ) ||
           (  from_id && (  control->by[i].id == from_id ) ) ) )
           {
           control->by[i].trigger |= flags;
           done = true;
           break;
           }
           }
          
           if (  !done )
           {
           for (  i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++ )
           {
           if (  !rtems_capture_control_by_valid (  control,   i ) )
           {
           control->by_valid |= RTEMS_CAPTURE_CONTROL_FROM_MASK (  i );
           control->by[i].name = from_name;
           control->by[i].id = from_id;
           control->by[i].trigger = flags;
           done = true;
           break;
           }
           }
           }
          
           if (  !done )
           return RTEMS_TOO_MANY;
           }
           }
           return RTEMS_SUCCESSFUL;
          }
    1599  
          /*
           * rtems_capture_clear_trigger
           *
           * DESCRIPTION:
           *
           * This function clear a trigger.
           */
          rtems_status_code
          rtems_capture_clear_trigger (  rtems_name from_name,  
           rtems_id from_id,  
           rtems_name to_name,  
           rtems_id to_id,  
           rtems_capture_trigger_mode_t mode,  
           rtems_capture_trigger_t trigger )
          {
           rtems_capture_control_t* control;
           uint32_t flags;
          
           flags = rtems_capture_map_trigger (  trigger );
          
           if (  mode == rtems_capture_to_any )
           {
           control = rtems_capture_find_control (  from_name,   from_id );
           if (  control == NULL )
           {
           if (  from_id )
           return RTEMS_INVALID_ID;
           return RTEMS_INVALID_NAME;
           }
           control->from_triggers &= ~flags;
           }
           else
           {
           control = rtems_capture_find_control (  to_name,   to_id );
           if (  control == NULL )
           {
           if (  to_id )
           return RTEMS_INVALID_ID;
           return RTEMS_INVALID_NAME;
           }
           if (  mode == rtems_capture_from_any )
           control->to_triggers &= ~flags;
           else
           {
           bool done = false;
           int i;
          
           control->by_triggers &= ~flags;
          
           for (  i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++ )
           {
           if (  rtems_capture_control_by_valid (  control,   i ) &&
           (  (  control->by[i].name == from_name ) ||
           (  control->by[i].id == from_id ) ) )
           {
           control->by[i].trigger &= ~trigger;
           if (  control->by[i].trigger == 0 )
           control->by_valid &= ~RTEMS_CAPTURE_CONTROL_FROM_MASK (  i );
           done = true;
           break;
           }
           }
          
           if (  !done )
           {
           if (  from_id )
           return RTEMS_INVALID_ID;
           return RTEMS_INVALID_NAME;
           }
           }
           }
           return RTEMS_SUCCESSFUL;
          }
          
          /*
           * rtems_capture_read
           *
           * DESCRIPTION:
           *
           * This function reads a number of records from the capture buffer.
           * The user can optionally block and wait until the buffer as a
           * specific number of records available or a specific time has
           * elasped.
           *
           * The function returns the number of record that is has that are
           * in a continous block of memory. If the number of available records
           * wrap then only those records are provided. This removes the need for
           * caller to be concerned about buffer wrappings. If the number of
           * requested records cannot be met due to the wrapping of the records
           * less than the specified number will be returned.
           *
           * The user must release the records. This is achieved with a call to
           * rtems_capture_release. Calls this function without a release will
           * result in at least the same number of records being released.
           *
           * The 'threshold' parameter is the number of records that must be
           * captured before returning. If a timeout period is specified (  non-0 )
    1697   * any captured records will be returned. These parameters stop
           * thrashing occuring for a small number of records,   yet allows
           * a user configured latiency to be applied for single events.
           *
           * The 'timeout' parameter is in micro-seconds. A value of 0 will disable
           * the timeout.
           *
           */
          rtems_status_code
          rtems_capture_read (  uint32_t threshold,  
           uint32_t timeout,  
           uint32_t* read,  
           rtems_capture_record_t** recs )
          {
           rtems_interrupt_level level;
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           uint32_t count;
          
           *read = 0;
           *recs = NULL;
          
           rtems_interrupt_disable (  level );
          
           /*
           * Only one reader is allowed.
           */
          
           if (  capture_flags & RTEMS_CAPTURE_READER_ACTIVE )
           {
           rtems_interrupt_enable (  level );
           return RTEMS_RESOURCE_IN_USE;
           }
          
           capture_flags |= RTEMS_CAPTURE_READER_ACTIVE;
           *read = count = capture_count;
          
           rtems_interrupt_enable (  level );
          
           *recs = &capture_records[capture_out];
          
           for (  ;; )
           {
           /*
           * See if the count wraps the end of the record buffer.
           */
           if (  count && (  (  capture_out + count ) >= capture_size ) )
           *read = capture_size - capture_out;
          
           /*
           * Do we have a threshold and the current count has not wrapped
           * around the end of the capture record buffer ?
           */
           if (  (  *read == count ) && threshold )
           {
           /*
           * Do we have enough records ?
           */
           if (  *read < threshold )
           {
           rtems_event_set event_out;
          
           rtems_task_ident (  RTEMS_SELF,   RTEMS_LOCAL,   &capture_reader );
          
           rtems_interrupt_disable (  level );
          
           capture_flags |= RTEMS_CAPTURE_READER_WAITING;
          
           rtems_interrupt_enable (  level );
          
           sc = rtems_event_receive (  RTEMS_EVENT_0,  
           RTEMS_WAIT | RTEMS_EVENT_ANY,  
           RTEMS_MICROSECONDS_TO_TICKS (  timeout ),  
           &event_out );
          
           /*
           * Let the user handle all other sorts of errors. This may
           * not be the best solution,   but oh well,   it will do for
           * now.
           */
           if (  (  sc != RTEMS_SUCCESSFUL ) && (  sc != RTEMS_TIMEOUT ) )
           break;
          
           rtems_interrupt_disable (  level );
          
           *read = count = capture_count;
          
           rtems_interrupt_enable (  level );
          
           continue;
           }
           }
          
           /*
           * Always out if we reach here. To loop use continue.
           */
           break;
           }
          
           return sc;
          }
          
    1798  /*
           * rtems_capture_release
           *
           * DESCRIPTION:
           *
           * This function releases the requested number of record slots back
           * to the capture engine. The count must match the number read.
           */
          rtems_status_code
          rtems_capture_release (  uint32_t count )
          {
           rtems_capture_record_t* rec;
           uint32_t counted;
          
           rtems_interrupt_level level;
          
           rtems_interrupt_disable (  level );
          
           if (  count > capture_count )
           count = capture_count;
          
           rtems_interrupt_enable (  level );
          
           counted = count;
          
           rec = &capture_records[capture_out];
          
           while (  counted-- )
           {
           rtems_capture_refcount_down (  rec->task );
           rtems_capture_destroy_capture_task (  rec->task );
           rec++;
           }
          
           rtems_interrupt_disable (  level );
          
           capture_count -= count;
          
           capture_out = (  capture_out + count ) % capture_size;
          
           capture_flags &= ~RTEMS_CAPTURE_READER_ACTIVE;
          
           rtems_interrupt_enable (  level );
          
           return RTEMS_SUCCESSFUL;
          }
    1844  
          /*
           * rtems_capture_tick_time
           *
           * DESCRIPTION:
           *
           * This function returns the tick period in nano-seconds.
           */
          uint32_t
          rtems_capture_tick_time (  void )
          {
           return capture_tick_period;
          }
          
          /*
    1859   * rtems_capture_event_text
           *
           * DESCRIPTION:
           *
           * This function returns a string for an event based on the bit in the
           * event. The functions takes the bit offset as a number not the bit
           * set in a bit map.
           */
          const char*
          rtems_capture_event_text (  int event )
          {
           if (  (  event < RTEMS_CAPTURE_EVENT_START ) || (  event > RTEMS_CAPTURE_EVENT_END ) )
           return "invalid event id";
           return capture_event_text[event - RTEMS_CAPTURE_EVENT_START];
          }
          
    1875  /*
           * rtems_capture_get_task_list
           *
           * DESCRIPTION:
           *
           * This function returns the head of the list of tasks that the
           * capture engine has detected.
           */
          rtems_capture_task_t*
          rtems_capture_get_task_list (  void )
          {
           return capture_tasks;
          }
          
    1889  /*
           * rtems_capture_task_stack_usage
           *
           * DESCRIPTION:
           *
           * This function updates the stack usage. The task control block
           * is updated.
           */
          uint32_t
          rtems_capture_task_stack_usage (  rtems_capture_task_t* task )
          {
           if (  task->tcb )
           {
           uint32_t* st;
           uint32_t* s;
          
           /*
           * @todo: Assumes all stacks move the same way.
           */
           st = task->tcb->Start.Initial_stack.area + task->stack_size;
           s = task->tcb->Start.Initial_stack.area;
          
           while (  s < st )
           {
           if (  *s != 0xdeaddead )
           break;
           s++;
           }
          
           task->stack_clean =
           s - (  uint32_t* ) task->tcb->Start.Initial_stack.area;
           }
          
           return task->stack_clean;
          }
          
    1925  /*
           * rtems_capture_get_control_list
           *
           * DESCRIPTION:
           *
           * This function returns the head of the list of control in the
           * capture engine.
           */
          rtems_capture_control_t*
          rtems_capture_get_control_list (  void )
          {
           return capture_controls;
          }

libmisc/cpuuse/cpuusagedata.c

       1  /*
           * CPU Usage Reporter - Shared Data
           *
           * COPYRIGHT (  c ) 1989-2009
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpuusagedata.c,  v 1.3 2009/12/02 18:22:18 humph Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/cpuuse.h>
          #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           #include <rtems/score/timespec.h>
          #endif
          
          #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           struct timespec CPU_usage_Uptime_at_last_reset;
          #else
           uint32_t CPU_usage_Ticks_at_last_reset;
          #endif

libmisc/cpuuse/cpuusagereport.c

       1  /*
           * CPU Usage Reporter
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpuusagereport.c,  v 1.15 2010/07/26 22:03:17 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          
          #include <string.h>
          #include <stdlib.h>
          #include <stdio.h>
          #include <ctype.h>
          #include <inttypes.h>
          
          #include <rtems/cpuuse.h>
          #include <rtems/bspIo.h>
          
          #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           #include <rtems/score/timestamp.h>
          #endif
          
          #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           extern Timestamp_Control CPU_usage_Uptime_at_last_reset;
          #else
           extern uint32_t CPU_usage_Ticks_at_last_reset;
          #endif
          
          /*PAGE
           *
           * rtems_cpu_usage_report
           */
          
      44  void rtems_cpu_usage_report_with_plugin(  
           void *context,  
           rtems_printk_plugin_t print
           )
          {
           uint32_t i;
           uint32_t api_index;
           Thread_Control *the_thread;
           Objects_Information *information;
           char name[13];
           uint32_t ival,   fval;
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           Timestamp_Control uptime,   total,   ran;
           #else
           uint32_t total_units = 0;
           #endif
          
           if (   !print  )
           return;
          
           /*
           * When not using nanosecond CPU usage resolution,   we have to count
           * the number of "ticks" we gave credit for to give the user a rough
           * guideline as to what each number means proportionally.
           */
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           _TOD_Get_uptime(   &uptime  );
           _Timestamp_Subtract(   &CPU_usage_Uptime_at_last_reset,   &uptime,   &total  );
           #else
           for (   api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++  ) {
           /*
           * Since the removal of ITRON,   this cannot occur.
           */
           #if defined(  RTEMS_DEBUG )
           if (   !_Objects_Information_table[ api_index ]  )
           continue;
           #endif
          
           information = _Objects_Information_table[ api_index ][ 1 ];
           if (   information  ) {
           for (   i=1 ; i <= information->maximum ; i++  ) {
           the_thread = (  Thread_Control * )information->local_table[ i ];
          
           if (   the_thread  )
           total_units += the_thread->cpu_time_used;
           }
           }
           }
           #endif
          
           (  *print )(  
           context,  
           "-------------------------------------------------------------------------------\n"
           " CPU USAGE BY THREAD\n"
           "------------+----------------------------------------+---------------+---------\n"
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           " ID | NAME | SECONDS | PERCENT\n"
           #else
           " ID | NAME | TICKS | PERCENT\n"
           #endif
           "------------+----------------------------------------+---------------+---------\n"
            );
          
           for (   api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++  ) {
           /*
           * Since the removal of ITRON,   this cannot occur.
           */
           #if defined(  RTEMS_DEBUG )
           if (   !_Objects_Information_table[ api_index ]  )
           continue;
           #endif
          
           information = _Objects_Information_table[ api_index ][ 1 ];
           if (   information  ) {
           for (   i=1 ; i <= information->maximum ; i++  ) {
           the_thread = (  Thread_Control * )information->local_table[ i ];
          
           if (   !the_thread  )
           continue;
          
           rtems_object_get_name(   the_thread->Object.id,   sizeof(  name ),   name  );
          
           (  *print )(  
           context,  
           " 0x%08" PRIx32 " | %-38s |",  
           the_thread->Object.id,  
           name
            );
          
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           /*
           * If this is the currently executing thread,   account for time
           * since the last context switch.
           */
           ran = the_thread->cpu_time_used;
           if (   _Thread_Executing->Object.id == the_thread->Object.id  ) {
           Timestamp_Control used;
           _Timestamp_Subtract(  
           &_Thread_Time_of_last_context_switch,   &uptime,   &used
            );
           _Timestamp_Add_to(   &ran,   &used  );
           };
           _Timestamp_Divide(   &ran,   &total,   &ival,   &fval  );
          
           /*
           * Print the information
           */
          
           (  *print )(   context,  
           "%7" PRIu32 ".%06" PRIu32 " |%4" PRIu32 ".%03" PRIu32 "\n",  
           _Timestamp_Get_seconds(   &ran  ),  
           _Timestamp_Get_nanoseconds(   &ran  ) /
           TOD_NANOSECONDS_PER_MICROSECOND,  
           ival,   fval
            );
           #else
           if (  total_units ) {
           uint64_t ival_64;
          
           ival_64 = the_thread->cpu_time_used;
           ival_64 *= 100000;
           ival = ival_64 / total_units;
           } else {
           ival = 0;
           }
          
           fval = ival % 1000;
           ival /= 1000;
           (  *print )(   context,  
           "%14" PRIu32 " |%4" PRIu32 ".%03" PRIu32 "\n",  
           the_thread->cpu_time_used,  
           ival,  
           fval
            );
           #endif
           }
           }
           }
          
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           (  *print )(  
           context,  
           "------------+----------------------------------------+---------------+---------\n"
           " TIME SINCE LAST CPU USAGE RESET IN SECONDS: %7" PRIu32 ".%06" PRIu32 "\n"
           "-------------------------------------------------------------------------------\n",  
           _Timestamp_Get_seconds(   &total  ),  
           _Timestamp_Get_nanoseconds(   &total  ) / TOD_NANOSECONDS_PER_MICROSECOND
            );
           #else
           (  *print )(  
           context,  
           "------------+----------------------------------------+---------------+---------\n"
           " TICKS SINCE LAST SYSTEM RESET: %14" PRIu32 "\n"
           " TOTAL UNITS: %14" PRIu32 "\n"
           "-------------------------------------------------------------------------------\n",  
           _Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset,  
           total_units
            );
           #endif
          }
          
     205  void rtems_cpu_usage_report(   void  )
          {
           rtems_cpu_usage_report_with_plugin(   NULL,   printk_plugin  );
          }

libmisc/cpuuse/cpuusagereset.c

       1  /*
           * CPU Usage Reporter
           *
           * COPYRIGHT (  c ) 1989-2009
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpuusagereset.c,  v 1.8 2009/12/02 18:22:18 humph Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/score/timestamp.h>
          
          #include <stdlib.h>
          #include <ctype.h>
          #include <inttypes.h>
          
          #include <rtems/cpuuse.h>
          
      27  static void CPU_usage_Per_thread_handler(  
           Thread_Control *the_thread
           )
          {
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           _Timestamp_Set_to_zero(   &the_thread->cpu_time_used  );
           #else
           the_thread->cpu_time_used = 0;
           #endif
          }
          
          /*
           * External data that is shared by cpu usage code but not declared in .h files.
           */
          #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           extern Timestamp_Control CPU_usage_Uptime_at_last_reset;
          #else
           extern uint32_t CPU_usage_Ticks_at_last_reset;
          #endif
          
          /*
           * rtems_cpu_usage_reset
           */
      50  void rtems_cpu_usage_reset(   void  )
          {
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           _TOD_Get_uptime(   &CPU_usage_Uptime_at_last_reset  );
           _Thread_Time_of_last_context_switch = CPU_usage_Uptime_at_last_reset;
           #else
           CPU_usage_Ticks_at_last_reset = _Watchdog_Ticks_since_boot;
           #endif
          
           rtems_iterate_over_all_threads(  CPU_usage_Per_thread_handler );
          }

libmisc/devnull/devnull.c

       1  /* /dev/null
           *
           * Derived from rtems' stub driver.
           *
           * Author: Ralf Corsepius (  corsepiu@faw.uni-ulm.de )
           *
           * COPYRIGHT (  c ) 1989-2000.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: devnull.c,  v 1.8 2009/01/02 13:01:21 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/devnull.h>
          #include <rtems/libio.h>
          
          /* null_initialize
           *
           * This routine is the null device driver init routine.
           *
           * Input parameters:
           * major - device major number
           * minor - device minor number
           * pargp - pointer to parameter block
           *
           * Output parameters:
           * rval - NULL_SUCCESSFUL
           */
          
          uint32_t NULL_major;
          static char initialized;
          
      41  rtems_device_driver null_initialize(  
           rtems_device_major_number major,  
           rtems_device_minor_number minor __attribute__(  (  unused ) ),  
           void *pargp __attribute__(  (  unused ) )
           )
          {
           rtems_device_driver status;
          
           if (   !initialized  ) {
           initialized = 1;
          
           status = rtems_io_register_name(  
           "/dev/null",  
           major,  
           (  rtems_device_minor_number ) 0
            );
          
           if (  status != RTEMS_SUCCESSFUL )
           rtems_fatal_error_occurred(  status );
          
           NULL_major = major;
           }
          
           return RTEMS_SUCCESSFUL;
          }
          
          /* null_open
           *
           * This routine is the null device driver open routine.
           *
           * Input parameters:
           * major - device major number
           * minor - device minor number
           * pargb - pointer to open parameter block
           *
           * Output parameters:
           * rval - NULL_SUCCESSFUL
           */
          
      80  rtems_device_driver null_open(  
           rtems_device_major_number major __attribute__(  (  unused ) ),  
           rtems_device_minor_number minor __attribute__(  (  unused ) ),  
           void *pargp __attribute__(  (  unused ) )
           )
          {
           return NULL_SUCCESSFUL;
          }
          
          
          /* null_close
           *
           * This routine is the null device driver close routine.
           *
           * Input parameters:
           * major - device major number
           * minor - device minor number
           * pargb - pointer to close parameter block
           *
           * Output parameters:
           * rval - NULL_SUCCESSFUL
           */
          
     103  rtems_device_driver null_close(  
           rtems_device_major_number major __attribute__(  (  unused ) ),  
           rtems_device_minor_number minor __attribute__(  (  unused ) ),  
           void *pargp __attribute__(  (  unused ) )
           )
          {
           return NULL_SUCCESSFUL;
          }
          
          
          /* null_read
           *
           * This routine is the null device driver read routine.
           *
           * Input parameters:
           * major - device major number
           * minor - device minor number
           * pargp - pointer to read parameter block
           *
           * Output parameters:
           * rval - NULL_SUCCESSFUL
           */
          
     126  rtems_device_driver null_read(  
           rtems_device_major_number major __attribute__(  (  unused ) ),  
           rtems_device_minor_number minor __attribute__(  (  unused ) ),  
           void *pargp __attribute__(  (  unused ) )
           )
          {
           return NULL_SUCCESSFUL;
          }
          
          
          /* null_write
           *
           * This routine is the null device driver write routine.
           *
           * Input parameters:
           * major - device major number
           * minor - device minor number
           * pargp - pointer to write parameter block
           *
           * Output parameters:
           * rval - NULL_SUCCESSFUL
           */
          
     149  rtems_device_driver null_write(  
           rtems_device_major_number major __attribute__(  (  unused ) ),  
           rtems_device_minor_number minor __attribute__(  (  unused ) ),  
           void *pargp
           )
          {
           rtems_libio_rw_args_t *rw_args = (  rtems_libio_rw_args_t * ) pargp;
          
           if (   rw_args  )
           rw_args->bytes_moved = rw_args->count;
          
           return NULL_SUCCESSFUL;
          }
          
          
          /* null_control
           *
           * This routine is the null device driver control routine.
           *
           * Input parameters:
           * major - device major number
           * minor - device minor number
           * pargp - pointer to cntrl parameter block
           *
           * Output parameters:
           * rval - NULL_SUCCESSFUL
           */
          
     177  rtems_device_driver null_control(  
           rtems_device_major_number major __attribute__(  (  unused ) ),  
           rtems_device_minor_number minor __attribute__(  (  unused ) ),  
           void *pargp __attribute__(  (  unused ) )
           )
          {
           return NULL_SUCCESSFUL;
          }

libmisc/dummy/dummy-networking.c

       1  /*
           * Dummy configuration file
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: dummy-networking.c,  v 1.1 2009/08/05 00:00:54 ccj Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          
          /* Loopback Network Configuration */
          #if defined(  RTEMS_NETWORKING )
           #include <rtems/rtems_bsdnet.h>
           #include <sys/socket.h>
           #include <netinet/in.h>
          
      26   extern int rtems_bsdnet_loopattach(  struct rtems_bsdnet_ifconfig *,   int );
          
           static struct rtems_bsdnet_ifconfig loopback_config = {
           "lo0",   /* name */
           rtems_bsdnet_loopattach,   /* attach function */
           NULL,   /* link to next interface */
           "127.0.0.1",   /* IP address */
           "255.0.0.0",   /* IP net mask */
           0,   /* hardware_address */
           0,   0,   0,   0,  
           0,   0,   0,  
           0
           };
          
           struct rtems_bsdnet_config rtems_bsdnet_config = {
           &loopback_config,   /* Network interface */
           NULL,   /* Use fixed network configuration */
           0,   /* Default network task priority */
           0,   /* Default mbuf capacity */
           0,   /* Default mbuf cluster capacity */
           "testSystem",   /* Host name */
           "nowhere.com",   /* Domain name */
           "127.0.0.1",   /* Gateway */
           "127.0.0.1",   /* Log host */
           {"127.0.0.1" },   /* Name server(  s ) */
           {"127.0.0.1" },   /* NTP server(  s ) */
           1,   /* sb_efficiency */
           0,   /* udp_tx_buf_size */
           0,   /* udp_rx_buf_size */
           0,   /* tcp_tx_buf_size */
           0 /* tcp_rx_buf_size */
           };
          #endif

libmisc/dummy/dummy.c

       1  /*
           * Dummy configuration file
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: dummy.c,  v 1.15 2009/08/05 00:00:54 ccj Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          
      20  int main(   int,   char **,   char ** );
          
          /* configuration information */
          
          /* This is enough to get a basic main(   ) up. */
          #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
          #define CONFIGURE_MAXIMUM_TASKS 10
          #define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
          #define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 20
          #define CONFIGURE_INIT_TASK_ENTRY_POINT (  void * )main
          
          /* Include basic device drivers needed to call delays */
          #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
          #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
          
          #define CONFIGURE_INIT
          
          #include <rtems/confdefs.h>
          

libmisc/dumpbuf/dumpbuf.c

       1  /*
           * COPYRIGHT (  c ) 1997-2007.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may in
           * the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: dumpbuf.c,  v 1.8 2010/06/28 14:33:34 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <string.h>
          #include <ctype.h>
          #include <rtems/dumpbuf.h>
          #include <rtems/bspIo.h>
          
          /*
           * Put the body below rtems_print_buffer so it won't get inlined.
           */
          
      26  static inline void Dump_Line(  
           const unsigned char *buffer,  
           int length
           );
          
      31  void rtems_print_buffer(  
           const unsigned char *buffer,  
           int length
           )
          {
          
           int i,   mod,   max;
          
           if (   !length  ) return;
          
           mod = length % 16;
          
           max = length - mod;
          
           for (   i=0 ; i<max ; i+=16  )
           Dump_Line(   &buffer[ i ],   16  );
          
           if (   mod  )
           Dump_Line(   &buffer[ max ],   mod  );
          }
          
      52  static inline void Dump_Line(  
           const unsigned char *buffer,  
           int length
           )
          {
          
           int i;
           char line_buffer[120];
          
           line_buffer[0] = '\0';
          
           for(   i=0 ; i<length ; i++  )
           sprintf(   line_buffer,   "%s%02x ",   line_buffer,   buffer[ i ]  );
          
           for(   ; i<16 ; i++  )
           strcat(   line_buffer,   " "  );
          
           strcat(   line_buffer,   "|"  );
           for(   i=0 ; i<length ; i++  )
           sprintf(   line_buffer,   "%s%c",   line_buffer,  
           isprint(   buffer[ i ]  ) ? buffer[ i ] : '.'  );
          
           for(   ; i<16 ; i++  )
           strcat(   line_buffer,   " "  );
          
           strcat(   line_buffer,   "|\n"  );
          
           printk(   line_buffer  );
          }

libmisc/fb/mw_uid.c

       1  /*
           *
           * Copyright (  c ) 2000 - Rosimildo da Silva
           *
           * MODULE DESCRIPTION:
           * This module implements the input devices interface used by MicroWindows
           * in an embedded system environment.
           * It uses the RTEMS message queue as the repository for the messages posted
           * by the devices registered.
           *
           * $Id: mw_uid.c,  v 1.1 2009/08/21 18:39:59 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <fcntl.h>
          #include <sys/ioctl.h>
          #include <errno.h>
          #include <rtems.h>
          
          #include <rtems/mw_uid.h>
          #include <rtems/seterr.h>
          
          static rtems_id queue_id = 0;
          static int open_count = 0;
          
          /*
          #define MW_DEBUG_ON 1
          */
          
          /* open a message queue with the kernel */
      35  int uid_open_queue(   const char *q_name,   int flags __attribute__(  (  unused ) ),   size_t max_msgs  )
          {
           static rtems_name queue_name;
          
           /*
           * For the first device calling this function we would create the queue.
           * It is assumed that this call is done at initialization,   and no concerns
           * regarding multi-threading is taken in consideration here.
           */
           if(   !open_count  )
           {
           rtems_status_code status;
           queue_name = rtems_build_name(   q_name[0],  
           q_name[1],  
           q_name[2],  
           q_name[3]  );
           status = rtems_message_queue_create(   queue_name,  
           max_msgs,  
           sizeof(   struct MW_UID_MESSAGE  ),  
           RTEMS_FIFO | RTEMS_LOCAL,  
           &queue_id  );
           if(   status != RTEMS_SUCCESSFUL  )
           {
          #ifdef MW_DEBUG_ON
           printk(   "UID_Queue: error creating queue: %d\n",   status  );
          #endif
           return -1;
           }
          #ifdef MW_DEBUG_ON
           printk(   "UID_Queue: id=%X\n",   queue_id  );
          #endif
           }
           open_count++;
           return 0;
          }
          
          
          /* close message queue */
      73  int uid_close_queue(   void  )
          {
           if(   open_count == 1  )
           {
           rtems_message_queue_delete(   queue_id  );
           queue_id = 0;
           }
           open_count--;
           return 0;
          }
          
          /* reads for a message from the device */
      85  int uid_read_message(   struct MW_UID_MESSAGE *m,   unsigned long timeout  )
          {
           rtems_status_code status;
           size_t size = 0;
           unsigned long micro_secs = timeout*1000;
           int wait = (   timeout != 0  );
          
           status = rtems_message_queue_receive(   queue_id,  
           (  void* )m,  
           &size,  
           wait ? RTEMS_WAIT : RTEMS_NO_WAIT,  
           RTEMS_MICROSECONDS_TO_TICKS(  micro_secs ) );
          
           if(   status == RTEMS_SUCCESSFUL  )
           {
           return size;
           }
           else if(   (   status == RTEMS_UNSATISFIED  ) || (   status == RTEMS_TIMEOUT  )  )
           {
           /* this macro returns -1 */
           rtems_set_errno_and_return_minus_one(   ETIMEDOUT  );
           }
           /* Here we have one error condition */
          #ifdef MW_DEBUG_ON
           printk(   "UID_Queue: error reading queue: %d\n",   status  );
          #endif
           return -1;
          }
          
          
          /*
           * add a message to the queue of events. This method cna be used to
           * simulate hardware events,   and it can be very handy during development
           * a new interface.
           */
     120  int uid_send_message(   struct MW_UID_MESSAGE *m  )
          {
           rtems_status_code status;
           status = rtems_message_queue_send(   queue_id,   (   void *  )m,  
           sizeof(   struct MW_UID_MESSAGE  )  );
           return status == RTEMS_SUCCESSFUL ? 0 : -1;
          }
          
          /*
           * register the device to insert events to the message
           * queue named as the value passed in q_name
           */
     132  int uid_register_device(   int fd,   const char *q_name  )
          {
           return ioctl(   fd,   MW_UID_REGISTER_DEVICE,   q_name  );
          }
          
          /* tell this device to stop adding events to the queue */
     138  int uid_unregister_device(   int fd  )
          {
           return ioctl(   fd,   MW_UID_UNREGISTER_DEVICE,   NULL  );
          }
          
          /* set the keyboard */
     144  int uid_set_kbd_mode(   int fd,   int mode,   int *old_mode  )
          {
           if (  ioctl(   fd,   MV_KDGKBMODE,   old_mode ) < 0 )
           {
           return -1;
           }
           if (  ioctl(  fd,   MV_KDSKBMODE,   mode  ) < 0  )
           {
           return -1;
           }
           return 0;
          }

libmisc/fsmount/fsmount.c

       1  /**
           * @file
           *
           * File system mount functions.
           */
          
          /*===============================================================*\
          | Project: RTEMS fsmount |
          +-----------------------------------------------------------------+
          | File: fsmount.c |
          +-----------------------------------------------------------------+
          | Copyright (  c ) 2003 IMD |
          | Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
          | <Thomas.Doerfler@imd-systems.de> |
          | all rights reserved |
          +-----------------------------------------------------------------+
          | this file contains the fsmount functions. These functions |
          | are used to mount a list of filesystems (  and create their mount |
          | points before ) |
          | |
          | The license and distribution terms for this file may be |
          | found in the file LICENSE in this distribution or at |
          | http://www.rtems.com/license/LICENSE. |
          | |
          +-----------------------------------------------------------------+
          | date history ID |
          | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
          | 02.07.03 creation doe |
          \*===============================================================*/
          
          #ifndef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/fsmount.h>
          #include <rtems/libio.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <errno.h>
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
      46  int rtems_fsmount
          (  
          /*-------------------------------------------------------------------------*\
           | Purpose: |
           | This function will create the mount points listed and mount the file |
           | systems listed in the calling parameters |
           +---------------------------------------------------------------------------+
           | Input Parameters: |
           \*-------------------------------------------------------------------------*/
           const rtems_fstab_entry *fstab_ptr,  
           size_t fstab_count,  
           size_t *fail_idx
            )
          /*-------------------------------------------------------------------------*\
           | Return Value: |
           | 0,   if success,   -1 and errno if failed |
           \*=========================================================================*/
          {
           int rc = 0;
           int tmp_rc;
           size_t fstab_idx = 0;
           bool terminate = false;
          
           /*
           * scan through all fstab entries;
           */
           while (  !terminate &&
           (  fstab_idx < fstab_count ) ) {
           tmp_rc = 0;
           /*
           * create mount point
           */
           if (  tmp_rc == 0 ) {
           tmp_rc = rtems_mkdir(  fstab_ptr->target,   S_IRWXU | S_IRWXG | S_IRWXO );
           if (  tmp_rc != 0 ) {
           if (  0 != (  fstab_ptr->report_reasons & FSMOUNT_MNTPNT_CRTERR ) ) {
           fprintf(  stdout,  "fsmount: creation of mount point \"%s\" failed: %s\n",  
           fstab_ptr->target,  
           strerror(  errno ) );
           }
           if (  0 != (  fstab_ptr->abort_reasons & FSMOUNT_MNTPNT_CRTERR ) ) {
           terminate = true;
           rc = tmp_rc;
           }
           }
           }
           /*
           * mount device to given mount point
           */
           if (  tmp_rc == 0 ) {
           tmp_rc = mount(  fstab_ptr->source,  
           fstab_ptr->target,  
           fstab_ptr->type,  
           fstab_ptr->options,  
           NULL );
           if (  tmp_rc != 0 ) {
           if (  0 != (  fstab_ptr->report_reasons & FSMOUNT_MNT_FAILED ) ) {
           fprintf(  stdout,  "fsmount: mounting of \"%s\" to"
           " \"%s\" failed: %s\n",  
           fstab_ptr->source,  
           fstab_ptr->target,  
           strerror(  errno ) );
           }
           if (  0 != (  fstab_ptr->abort_reasons & FSMOUNT_MNT_FAILED ) ) {
           terminate = true;
           rc = tmp_rc;
           }
           }
           else {
           if (  0 != (  fstab_ptr->report_reasons & FSMOUNT_MNT_OK ) ) {
           fprintf(  stdout,  "fsmount: mounting of \"%s\" to"
           " \"%s\" succeeded\n",  
           fstab_ptr->source,  
           fstab_ptr->target );
           }
           if (  0 != (  fstab_ptr->abort_reasons & FSMOUNT_MNT_OK ) ) {
           terminate = true;
           }
           }
           }
           /*
           * proceed to next entry
           */
           if (  !terminate ) {
           fstab_ptr++;
           fstab_idx++;
           }
           }
           if (  fail_idx != NULL ) {
           *fail_idx = fstab_idx;
           }
           return rc;
          }

libmisc/monitor/mon-command.c

       1  /**
           * @file
           *
           * @brief Command support routines for RTEMS monitor.
           */
          
          /*
           * $Id: mon-command.c,  v 1.27 2010/03/27 03:58:06 ralf Exp $
           *
           * 2001-01-30 KJO (  vac4050@cae597.rsc.raytheon.com ):
           * Fixed rtems_monitor_command_lookup(   ) to accept partial
           * commands to uniqeness. Added support for setting
           * the monitor prompt via an environment variable:
           * RTEMS_MONITOR_PROMPT
           *
           * CCJ: 26-3-2000,   adding command history and command line
           * editing. This code is donated from My Right Boot and not
           * covered by GPL,   only the RTEMS license.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          #include <stdio.h>
          
          #include <rtems.h>
          #include <rtems/monitor.h>
          
          static void
      32  rtems_monitor_show_help (  
           const rtems_monitor_command_entry_t *help_cmd,  
           int max_cmd_len
           )
          {
          #define MAX_HELP_LINE_LENGTH (  75 - max_cmd_len - 2 )
          
           if (  help_cmd && help_cmd->command )
           {
           const char *help = help_cmd->usage;
           int help_len = strlen (  help );
           int spaces = max_cmd_len - strlen (  help_cmd->command );
           int show_this_line = 0;
           int line_one = 1;
           int c;
          
           fprintf(  stdout,  "%s",   help_cmd->command );
          
           if (  help_len == 0 )
           {
           fprintf(  stdout,  " - No help associated.\n" );
           return;
           }
          
           while (  help_len )
           {
           fprintf(  stdout,  "%*c",   spaces,   ' ' );
          
           if (  line_one )
           fprintf(  stdout,  " - " );
          
           spaces = max_cmd_len + 2;
           line_one = 0;
          
           /*
           * See if greater then the line length if so,   work back
           * from the end for a space,   tab or lf or cr.
           */
          
           if (  help_len > MAX_HELP_LINE_LENGTH )
           {
           for (  show_this_line = MAX_HELP_LINE_LENGTH - 1;
           show_this_line;
           show_this_line-- )
           if (  (  help[show_this_line] == ' ' ) ||
           (  help[show_this_line] == '\n' ) ||
           (  help[show_this_line] == '\r' ) )
           break;
          
           /*
           * If show_this_line is 0,   it is a very long word !!
           */
          
           if (  show_this_line == 0 )
           show_this_line = MAX_HELP_LINE_LENGTH - 1;
           }
           else
           show_this_line = help_len;
          
           for (  c = 0; c < show_this_line; c++ )
           if (  (  help[c] == '\r' ) || (  help[c] == '\n' ) )
           show_this_line = c;
           else
           putchar (  help[c] );
          
           fprintf(  stdout,  "\n" );
          
           help += show_this_line;
           help_len -= show_this_line;
          
           /*
           * Move past the line feeds or what ever else is being skipped.
           */
          
           while (  help_len )
           {
           if (  (  *help != '\r' ) && (  *help != '\n' ) )
           break;
          
           if (  *help != ' ' )
           {
           help++;
           help_len--;
           break;
           }
           help++;
           help_len--;
           }
           }
           }
          }
          
          void
     125  rtems_monitor_command_usage(  
           const rtems_monitor_command_entry_t *table,  
           const char *command_name
           )
          {
           const rtems_monitor_command_entry_t *command = table;
           int max_cmd_len = 0;
          
           /* if first entry in table is a usage,   then print it out */
          
           if (  command_name && (  *command_name != '\0' ) )
           {
           command = rtems_monitor_command_lookup (  command_name );
          
           if (  command )
           rtems_monitor_show_help (  command,   strlen (  command_name ) );
           else
           fprintf(  stdout,  "Unrecognised command; try just 'help'\n" );
           return;
           }
          
           /*
           * Find the largest command size.
           */
          
           while (  command )
           {
           int len = command->command ? strlen (  command->command ) : 0 ;
          
           if (  len > max_cmd_len )
           max_cmd_len = len;
          
           command = command->next;
           }
          
           max_cmd_len++;
          
           command = table;
          
           /*
           * Now some nice formatting for the help.
           */
          
           while (  command )
           {
           rtems_monitor_show_help (  command,   max_cmd_len );
           command = command->next;
           }
          }
          
          
     176  void rtems_monitor_help_cmd(  
           int argc,  
           char **argv,  
           const rtems_monitor_command_arg_t *command_arg,  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           int arg;
           const rtems_monitor_command_entry_t *command =
           command_arg->monitor_command_entry;
          
           if (  argc == 1 )
           rtems_monitor_command_usage(  command,   0 );
           else
           {
           for (  arg = 1; argv[arg]; arg++ )
           rtems_monitor_command_usage(  command,   argv[arg] );
           }
          }
          
          typedef struct {
           const char *name;
           size_t length;
           const rtems_monitor_command_entry_t *match;
          } rtems_monitor_command_lookup_entry;
          
     202  static bool rtems_monitor_command_lookup_routine(  
           const rtems_monitor_command_entry_t *e,  
           void *arg
           )
          {
           rtems_monitor_command_lookup_entry *le =
           (  rtems_monitor_command_lookup_entry * ) arg;
          
           /* Check name */
           if (  strncmp(  e->command,   le->name,   le->length ) == 0 ) {
           /* Check for ambiguity */
           if (  le->match == NULL ) {
           le->match = e;
           } else {
           return false;
           }
           }
          
           return true;
          }
          
          /**
           * @brief Looks for a command with the name @a name in the list of registered
           * commands.
           *
           * The parameter @a name must not be NULL.
           *
           * Returns the corresponding command entry or NULL if no command is found.
           */
     231  const rtems_monitor_command_entry_t *rtems_monitor_command_lookup(  
           const char *name
           )
          {
           rtems_monitor_command_lookup_entry e = {
           .name = name,  
           .length = strlen(   name ),  
           .match = NULL
           };
          
           rtems_monitor_command_iterate(  rtems_monitor_command_lookup_routine,   &e );
          
           return e.match;
          }

libmisc/monitor/mon-config.c

       1  /*
           * RTEMS Config display support
           *
           * TODO
           *
           * $Id: mon-config.c,  v 1.17 2009/01/02 13:01:21 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          #include <rtems/monitor.h>
          
          #include <inttypes.h>
          #include <stdio.h>
          #include <stdlib.h> /* strtoul(   ) */
          
          #define DATACOL 15
          #define CONTCOL DATACOL /* continued col */
          
          /*
           * Fill in entire monitor config table
           * for sending to a remote monitor or printing on the local system
           */
          
          void
      30  rtems_monitor_config_canonical(  
           rtems_monitor_config_t *canonical_config,  
           void *config_void
           )
          {
           rtems_configuration_table *c = (  rtems_configuration_table * ) config_void;
           rtems_api_configuration_table *r = &Configuration_RTEMS_API;
          
           canonical_config->work_space_start = c->work_space_start;
           canonical_config->work_space_size = c->work_space_size;
           canonical_config->maximum_tasks = r->maximum_tasks;
           canonical_config->maximum_timers = r->maximum_timers;
           canonical_config->maximum_semaphores = r->maximum_semaphores;
           canonical_config->maximum_message_queues = r->maximum_message_queues;
           canonical_config->maximum_partitions = r->maximum_partitions;
           canonical_config->maximum_regions = r->maximum_regions;
           canonical_config->maximum_ports = r->maximum_ports;
           canonical_config->maximum_periods = r->maximum_periods;
           canonical_config->maximum_extensions = c->maximum_extensions;
           canonical_config->microseconds_per_tick = c->microseconds_per_tick;
           canonical_config->ticks_per_timeslice = c->ticks_per_timeslice;
           canonical_config->number_of_initialization_tasks = r->number_of_initialization_tasks;
          }
          
          /*
           * This is easy,   since there is only 1 (  altho we could get them from
           * other nodes... )
           */
          
          void *
      60  rtems_monitor_config_next(  
           void *object_info __attribute__(  (  unused ) ),  
           rtems_monitor_config_t *canonical_config __attribute__(  (  unused ) ),  
           rtems_id *next_id
           )
          {
           rtems_configuration_table *c = &Configuration;
           int n = rtems_object_id_get_index(  *next_id );
          
           if (  n >= 1 )
           goto failed;
          
           _Thread_Disable_dispatch(   );
          
           *next_id += 1;
           return (  void * ) c;
          
          failed:
           *next_id = RTEMS_OBJECT_ID_FINAL;
           return 0;
          }
          
          
          void
      84  rtems_monitor_config_dump_header(  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           fprintf(  stdout,  "\
          INITIAL (  startup ) Configuration Info\n" );
          /*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
          0 1 2 3 4 5 6 7 */
           rtems_monitor_separator(   );
          }
          
          
          int
      97  rtems_monitor_config_dump(  
           rtems_monitor_config_t *monitor_config,  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           int length = 0;
          
           length = 0;
           length += fprintf(  stdout,  "WORKSPACE" );
           length += rtems_monitor_pad(  DATACOL,   length );
           length += fprintf(  stdout,  "start: %p; size: 0x%" PRIx32 "\n",  
           monitor_config->work_space_start,  
           monitor_config->work_space_size );
          
           length = 0;
           length += fprintf(  stdout,  "TIME" );
           length += rtems_monitor_pad(  DATACOL,   length );
           length += fprintf(  stdout,  "usec/tick: %" PRId32 "; tick/timeslice: %" PRId32 "; tick/sec: %" PRId32 "\n",  
           monitor_config->microseconds_per_tick,  
           monitor_config->ticks_per_timeslice,  
           1000000 / monitor_config->microseconds_per_tick );
          
           length = 0;
           length += fprintf(  stdout,  "MAXIMUMS" );
           length += rtems_monitor_pad(  DATACOL,   length );
           length += fprintf(  stdout,  "tasks: %" PRId32 "; timers: %" PRId32 "; sems: %" PRId32 "; que's: %" PRId32 "; ext's: %" PRId32 "\n",  
           monitor_config->maximum_tasks,  
           monitor_config->maximum_timers,  
           monitor_config->maximum_semaphores,  
           monitor_config->maximum_message_queues,  
           monitor_config->maximum_extensions );
           length = 0;
           length += rtems_monitor_pad(  CONTCOL,   length );
           length += fprintf(  stdout,  "partitions: %" PRId32 "; regions: %" PRId32 "; ports: %" PRId32 "; periods: %" PRId32 "\n",  
           monitor_config->maximum_partitions,  
           monitor_config->maximum_regions,  
           monitor_config->maximum_ports,  
           monitor_config->maximum_periods );
           return length;
          }

libmisc/monitor/mon-driver.c

       1  /*
           * RTEMS monitor IO (  device drivers ) support
           *
           * There are 2 "driver" things the monitor knows about.
           *
           * 1. Regular RTEMS drivers.
           * This is a table indexed by major device number and
           * containing driver entry points only.
           *
           * 2. Driver name table.
           * A separate table of names for drivers.
           * The table converts driver names to a major number
           * as index into the driver table and a minor number
           * for an argument to driver.
           *
           * Drivers are displayed with 'driver' command.
           * Names are displayed with 'name' command.
           *
           * $Id: mon-driver.c,  v 1.18 2009/10/02 15:54:47 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          
          #include <rtems/monitor.h>
          
          #include <stdio.h>
          #include <stdlib.h> /* strtoul(   ) */
          #include <inttypes.h>
          
          #define DATACOL 15
          #define CONTCOL DATACOL /* continued col */
          
          
          void
      40  rtems_monitor_driver_canonical(  
           rtems_monitor_driver_t *canonical_driver,  
           void *driver_void
           )
          {
           rtems_driver_address_table *d = (  rtems_driver_address_table * ) driver_void;
          
           rtems_monitor_symbol_canonical_by_value(  &canonical_driver->initialization,  
           (  void * ) d->initialization_entry );
          
           rtems_monitor_symbol_canonical_by_value(  &canonical_driver->open,  
           (  void * ) d->open_entry );
           rtems_monitor_symbol_canonical_by_value(  &canonical_driver->close,  
           (  void * ) d->close_entry );
           rtems_monitor_symbol_canonical_by_value(  &canonical_driver->read,  
           (  void * ) d->read_entry );
           rtems_monitor_symbol_canonical_by_value(  &canonical_driver->write,  
           (  void * ) d->write_entry );
           rtems_monitor_symbol_canonical_by_value(  &canonical_driver->control,  
           (  void * ) d->control_entry );
          }
          
          
          void *
      64  rtems_monitor_driver_next(  
           void *object_info __attribute__(  (  unused ) ),  
           rtems_monitor_driver_t *canonical_driver,  
           rtems_id *next_id
           )
          {
           rtems_configuration_table *c = &Configuration;
           uint32_t n = rtems_object_id_get_index(  *next_id );
          
           if (  n >= c->number_of_device_drivers )
           goto failed;
          
           _Thread_Disable_dispatch(   );
          
           /*
           * dummy up a fake id and name for this item
           */
          
           canonical_driver->id = n;
           canonical_driver->name = rtems_build_name(  '-',   '-',   '-',   '-' );
          
           *next_id += 1;
           return (  void * ) (  c->Device_driver_table + n );
          
          failed:
           *next_id = RTEMS_OBJECT_ID_FINAL;
           return 0;
          }
          
          
          void
      95  rtems_monitor_driver_dump_header(  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           fprintf(  stdout,  "\
           Major Entry points\n" );
          /*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
          0 1 2 3 4 5 6 7 */
           rtems_monitor_separator(   );
          }
          
          void
     107  rtems_monitor_driver_dump(  
           rtems_monitor_driver_t *monitor_driver,  
           bool verbose
           )
          {
           uint32_t length = 0;
          
          #if defined(  RTEMS_USE_16_BIT_OBJECT )
           length += fprintf(  stdout,  " %" PRId16 "",   monitor_driver->id );
          #else
           length += fprintf(  stdout,  " %" PRId32 "",   monitor_driver->id );
          #endif
           length += rtems_monitor_pad(  13,   length );
           length += fprintf(  stdout,  "init: " );
           length += rtems_monitor_symbol_dump(  &monitor_driver->initialization,   verbose );
           length += fprintf(  stdout,  "; control: " );
           length += rtems_monitor_symbol_dump(  &monitor_driver->control,   verbose );
           length += fprintf(  stdout,  "\n" );
           length = 0;
          
           length += rtems_monitor_pad(  13,   length );
          
           length += fprintf(  stdout,  "open: " );
           length += rtems_monitor_symbol_dump(  &monitor_driver->open,   verbose );
           length += fprintf(  stdout,  "; close: " );
           length += rtems_monitor_symbol_dump(  &monitor_driver->close,   verbose );
           length += fprintf(  stdout,  "\n" );
           length = 0;
          
           length += rtems_monitor_pad(  13,   length );
          
           length += fprintf(  stdout,  "read: " );
           length += rtems_monitor_symbol_dump(  &monitor_driver->read,   verbose );
           length += fprintf(  stdout,  "; write: " );
           length += rtems_monitor_symbol_dump(  &monitor_driver->write,   verbose );
           length += fprintf(  stdout,  "\n" );
           length = 0;
          }

libmisc/monitor/mon-editor.c

       1  /**
           * @file
           *
           * @brief Command line editor for RTEMS monitor.
           */
          
          /*
           * $Id: mon-editor.c,  v 1.5 2010/06/21 16:25:09 joel Exp $
           *
           * 2001-01-30 KJO (  vac4050@cae597.rsc.raytheon.com ):
           * Fixed rtems_monitor_command_lookup(   ) to accept partial
           * commands to uniqeness. Added support for setting
           * the monitor prompt via an environment variable:
           * RTEMS_MONITOR_PROMPT
           *
           * CCJ: 26-3-2000,   adding command history and command line
           * editing. This code is donated from My Right Boot and not
           * covered by GPL,   only the RTEMS license.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          
          #include <rtems/monitor.h>
          
          #include <stdio.h>
          #include <string.h>
          #include <stdlib.h>
          #include <inttypes.h>
          #include <termios.h>
          #include <unistd.h>
          
          #ifndef MONITOR_PROMPT
          #define MONITOR_PROMPT "rtems" /* will have '> ' appended */
          #endif
          
          /*
           * Some key labels to define special keys.
           */
          
          #define KEYS_EXTENDED (  0x8000 )
          #define KEYS_NORMAL_MASK (  0x00ff )
          #define KEYS_INS (  0 )
          #define KEYS_DEL (  1 )
          #define KEYS_UARROW (  2 )
          #define KEYS_DARROW (  3 )
          #define KEYS_LARROW (  4 )
          #define KEYS_RARROW (  5 )
          #define KEYS_HOME (  6 )
          #define KEYS_END (  7 )
          #define KEYS_F1 (  8 )
          #define KEYS_F2 (  9 )
          #define KEYS_F3 (  10 )
          #define KEYS_F4 (  11 )
          #define KEYS_F5 (  12 )
          #define KEYS_F6 (  13 )
          #define KEYS_F7 (  14 )
          #define KEYS_F8 (  15 )
          #define KEYS_F9 (  16 )
          #define KEYS_F10 (  17 )
          
          #define RTEMS_COMMAND_BUFFER_SIZE (  75 )
          
          static char monitor_prompt[32];
          static char buffer[RTEMS_COMMAND_BUFFER_SIZE];
          static int pos;
          static int logged_in;
          
          /*
           * History data.
           */
          
          #define RTEMS_COMMAND_HISTORIES (  20 )
          
          static char history_buffer[RTEMS_COMMAND_HISTORIES][RTEMS_COMMAND_BUFFER_SIZE];
          static int history_pos[RTEMS_COMMAND_HISTORIES];
          static int history;
          static int history_next;
          
          /*
           * Translation tables. Not sure if this is the best way to
           * handle this,   how-ever I wish to avoid the overhead of
           * including a more complete and standard environment such
           * as ncurses.
           */
          
          struct translation_table
          {
           char expecting;
           const struct translation_table *branch;
           unsigned int key;
          };
          
          static const struct translation_table trans_two[] =
          {
           { '~',   0,   KEYS_INS },  
           { 0,   0,   0 }
          };
          
          static const struct translation_table trans_three[] =
          {
           { '~',   0,   KEYS_DEL },  
           { 0,   0,   0 }
          };
          
          static const struct translation_table trans_tab_csi[] =
          {
           { '2',   trans_two,   0 },  
           { '3',   trans_three,   0 },  
           { 'A',   0,   KEYS_UARROW },  
           { 'B',   0,   KEYS_DARROW },  
           { 'D',   0,   KEYS_LARROW },  
           { 'C',   0,   KEYS_RARROW },  
           { 'F',   0,   KEYS_END },  
           { 'H',   0,   KEYS_HOME },  
           { 0,   0,   0 }
          };
          
          static const struct translation_table trans_tab_O[] =
          {
           { '1',   0,   KEYS_F1 },  
           { '2',   0,   KEYS_F2 },  
           { '3',   0,   KEYS_F3 },  
           { '4',   0,   KEYS_F4 },  
           { '5',   0,   KEYS_F5 },  
           { '6',   0,   KEYS_F6 },  
           { '7',   0,   KEYS_F7 },  
           { '8',   0,   KEYS_F8 },  
           { '9',   0,   KEYS_F9 },  
           { ':',   0,   KEYS_F10 },  
           { 'P',   0,   KEYS_F1 },  
           { 'Q',   0,   KEYS_F2 },  
           { 'R',   0,   KEYS_F3 },  
           { 'S',   0,   KEYS_F4 },  
           { 'T',   0,   KEYS_F5 },  
           { 'U',   0,   KEYS_F6 },  
           { 'V',   0,   KEYS_F7 },  
           { 'W',   0,   KEYS_F8 },  
           { 'X',   0,   KEYS_F9 },  
           { 'Y',   0,   KEYS_F10 },  
           { 0,   0,   0 }
          };
          
          static const struct translation_table trans_tab[] =
          {
           { '[',   trans_tab_csi,   0 },   /* CSI command sequences */
           { 'O',   trans_tab_O,   0 },   /* O are the fuction keys */
           { 0,   0,   0 }
          };
          
          /*
           * Perform a basic translation for some ANSI/VT100 key codes.
           * This code could do with a timeout on the ESC as it is
           * now lost from the input stream. It is not* used by the
           * line editor below so considiered not worth the effort.
           */
          
          static unsigned int
     162  rtems_monitor_getchar (  void )
          {
           const struct translation_table *translation = 0;
           for (  ;; )
           {
           char c = getchar (   );
           if (  c == 27 )
           translation = trans_tab;
           else
           {
           /*
           * If no translation happing just pass through
           * and return the key.
           */
           if (  translation )
           {
           /*
           * Scan the current table for the key,   and if found
           * see if this key is a fork. If so follow it and
           * wait else return the extended key.
           */
           int index = 0;
           int branched = 0;
           while (  (  translation[index].expecting != '\0' ) ||
           (  translation[index].key != '\0' ) )
           {
           if (  translation[index].expecting == c )
           {
           /*
           * A branch is take if more keys are to come.
           */
           if (  translation[index].branch == 0 )
           return KEYS_EXTENDED | translation[index].key;
           else
           {
           translation = translation[index].branch;
           branched = 1;
           break;
           }
           }
           index++;
           }
           /*
           * Who knows what these keys are,   just drop them.
           */
           if (  !branched )
           translation = 0;
           }
           else
           return c;
           }
           }
          }
          
          /*
           * The line editor with history.
           */
          
          static int
     221  rtems_monitor_line_editor (  
           char *command
           )
          {
           int repeating = 0;
          
           memset (  buffer,   0,   RTEMS_COMMAND_BUFFER_SIZE );
           history = history_next;
           pos = 0;
          
           if (  !logged_in )
           fprintf(  stdout,  "\nMonitor ready,   press enter to login.\n\n" );
           else
           fprintf(  stdout,  "%s $ ",   monitor_prompt );
          
           while (  1 )
           {
           unsigned int extended_key;
           char c;
          
           fflush (  stdout );
          
           extended_key = rtems_monitor_getchar (   );
           c = extended_key & KEYS_NORMAL_MASK;
          
           /*
           * Make the extended_key usable as a boolean.
           */
           extended_key &= ~KEYS_NORMAL_MASK;
          
           if (  !extended_key && !logged_in )
           {
           if (  c == '\n' )
           {
           logged_in = 1;
           /*
           * The prompt has changed from `>' to `$' to help know
           * which version of the monitor code people are using.
           */
           fprintf(  stdout,  "%s $ ",   monitor_prompt );
           }
           }
           else
           {
           if (  extended_key )
           {
           switch (  c )
           {
           case KEYS_END:
           fprintf(  stdout,  buffer + pos );
           pos = (  int ) strlen (  buffer );
           break;
          
           case KEYS_HOME:
           fprintf(  stdout,  "\r%s $ ",   monitor_prompt );
           pos = 0;
           break;
          
           case KEYS_LARROW:
           if (  pos > 0 )
           {
           pos--;
           putchar (  '\b' );
           }
           break;
          
           case KEYS_RARROW:
           if (  (  pos < RTEMS_COMMAND_BUFFER_SIZE ) && (  buffer[pos] != '\0' ) )
           {
           putchar (  buffer[pos] );
           pos++;
           }
           break;
          
           case KEYS_UARROW:
           /*
           * If we are moving up the histories then we need to save the working
           * buffer.
           */
           if (  history )
           {
           int end;
           int bs;
           if (  history == history_next )
           {
           memcpy (  history_buffer[history_next],   buffer,  
           RTEMS_COMMAND_BUFFER_SIZE );
           history_pos[history_next] = pos;
           }
           history--;
           memcpy (  buffer,   history_buffer[history],  
           RTEMS_COMMAND_BUFFER_SIZE );
           pos = history_pos[history];
           fprintf(  stdout,  "\r%*c",   RTEMS_COMMAND_BUFFER_SIZE,   ' ' );
           fprintf(  stdout,  "\r%s $ %s",   monitor_prompt,   buffer );
           end = (  int ) strlen (  buffer );
           for (  bs = 0; bs < (  end - pos ); bs++ )
           putchar (  '\b' );
           }
           break;
          
           case KEYS_DARROW:
           if (  history < history_next )
           {
           int end;
           int bs;
           history++;
           memcpy (  buffer,   history_buffer[history],  
           RTEMS_COMMAND_BUFFER_SIZE );
           pos = history_pos[history];
           fprintf(  stdout,  "\r%*c",   RTEMS_COMMAND_BUFFER_SIZE,   ' ' );
           fprintf(  stdout,  "\r%s $ %s",   monitor_prompt,   buffer );
           end = (  int ) strlen (  buffer );
           for (  bs = 0; bs < (  end - pos ); bs++ )
           putchar (  '\b' );
           }
           break;
          
           case KEYS_DEL:
           if (  buffer[pos] != '\0' )
           {
           int end;
           int bs;
           strcpy (  &buffer[pos],   &buffer[pos + 1] );
           fprintf(  stdout,  "\r%s $ %s",   monitor_prompt,   buffer );
           end = (  int ) strlen (  buffer );
           for (  bs = 0; bs < (  end - pos ); bs++ )
           putchar (  '\b' );
           }
           break;
           }
           }
           else
           {
           switch (  c )
           {
           case '\b':
           case '\x7e':
           case '\x7f':
           if (  pos > 0 )
           {
           int bs;
           pos--;
           strcpy (  buffer + pos,   buffer + pos + 1 );
           fprintf(  stdout,  "\b%s \b",   buffer + pos );
           for (  bs = 0; bs < (  (  int ) strlen (  buffer ) - pos ); bs++ )
           putchar (  '\b' );
           }
           break;
          
           case '\n':
           /*
           * Process the command.
           */
           fprintf(  stdout,  "\n" );
           repeating = 1;
           /*
           * Only process the history if we have a command and
           *a history.
           */
           if (  strlen (  buffer ) )
           {
           if (  history_next && (  history == history_next ) )
           {
           /*
           * Do not place the last command into the history
           *if the same.
           */
           if (  strcmp (  history_buffer[history_next - 1],   buffer ) )
           repeating = 0;
           }
           else
           repeating = 0;
           }
           if (  !repeating )
           {
           memcpy (  history_buffer[history_next],   buffer,  
           RTEMS_COMMAND_BUFFER_SIZE );
           history_pos[history_next] = pos;
           if (  history_next < (  RTEMS_COMMAND_HISTORIES - 1 ) )
           history_next++;
           else
           {
           memmove (  history_buffer[0],   history_buffer[1],  
           RTEMS_COMMAND_BUFFER_SIZE * (  RTEMS_COMMAND_HISTORIES - 1 ) );
           memmove (  &history_pos[0],   &history_pos[1],  
           sizeof (  history_pos[0] ) * (  RTEMS_COMMAND_HISTORIES - 1 ) );
           }
           }
           else
           {
          #ifdef ENABLE_ENTER_REPEATS
           if (  history_next )
           memcpy (  buffer,   history_buffer[history_next - 1],  
           RTEMS_COMMAND_BUFFER_SIZE );
          #endif
           }
           memmove (  command,   buffer,   RTEMS_COMMAND_BUFFER_SIZE );
           return repeating;
           break;
          
           default:
           if (  (  pos < (  RTEMS_COMMAND_BUFFER_SIZE - 1 ) ) &&
           (  c >= ' ' ) && (  c <= 'z' ) )
           {
           int end;
           end = strlen (  buffer );
           if (  (  pos < end ) && (  end < RTEMS_COMMAND_BUFFER_SIZE ) )
           {
           int ch,   bs;
           for (  ch = end; ch > pos; ch-- )
           buffer[ch] = buffer[ch - 1];
           fprintf(  stdout,  buffer + pos );
           for (  bs = 0; bs < (  end - pos + 1 ); bs++ )
           putchar (  '\b' );
           }
           buffer[pos++] = c;
           if (  pos > end )
           buffer[pos] = '\0';
           putchar (  c );
           }
           break;
           }
           }
           }
           }
          }
          
          /*
           * make_argv(  cp ): token-count
           * Break up the command line in 'cp' into global argv[] and argc (  return
           * value ).
           */
          
          int
     456  rtems_monitor_make_argv(  
           char *cp,  
           int *argc_p,  
           char **argv )
          {
           int argc = 0;
          
           while (  (  cp = strtok(  cp,   " \t\n\r" ) ) )
           {
           argv[argc++] = cp;
           cp = (  char * ) NULL;
           }
           argv[argc] = (  char * ) NULL; /* end of argv */
          
           return *argc_p = argc;
          }
          
          
          /*
           * Read and break up a monitor command
           *
           * We have to loop on the gets call,   since it will return NULL under UNIX
           * RTEMS when we get a signal (  eg: SIGALRM ).
           */
          
          int
     482  rtems_monitor_command_read(  char *command,  
           int *argc,  
           char **argv )
          {
           char *env_prompt;
          
           env_prompt = getenv(  "RTEMS_MONITOR_PROMPT" );
          
           /*
           * put node number in the prompt if we are multiprocessing
           */
          #if defined(  RTEMS_MULTIPROCESSING )
           if (  !rtems_configuration_get_user_multiprocessing_table (   ) )
           sprintf (  monitor_prompt,   "%s",  
           (  env_prompt == NULL ) ? MONITOR_PROMPT: env_prompt );
           else /* .... */
          #endif
           if (  rtems_monitor_default_node != rtems_monitor_node )
           sprintf (  monitor_prompt,   "%" PRId32 "-%s-%" PRId32 "",   rtems_monitor_node,  
           (  env_prompt == NULL ) ? MONITOR_PROMPT : env_prompt,  
           rtems_monitor_default_node );
           else
           sprintf (  monitor_prompt,   "%" PRId32 "-%s",   rtems_monitor_node,  
           (  env_prompt == NULL ) ? MONITOR_PROMPT : env_prompt );
          
           rtems_monitor_line_editor (  command );
          
           return rtems_monitor_make_argv (  command,   argc,   argv );
          }
          
          /*
           * Main monitor command loop
           */
          
          void
     517  rtems_monitor_task(  
           rtems_task_argument monitor_flags
           )
          {
           rtems_tcb *debugee = 0;
           rtems_context *rp;
          #if (  CPU_HARDWARE_FP == TRUE ) || (  CPU_SOFTWARE_FP == TRUE )
           rtems_context_fp *fp;
          #endif
           char command_buffer[513];
           int argc;
           char *argv[64];
           bool verbose = false;
           struct termios term;
          
           /*
           * Make the stdin stream characte not line based.
           */
          
           if (  tcgetattr (  STDIN_FILENO,   &term ) < 0 )
           {
           fprintf(  stdout,  "rtems-monitor: cannot get terminal attributes.\n" );
           }
           else
           {
           /*
           * No echo,   no canonical processing.
           */
          
           term.c_lflag &= ~(  ECHO | ICANON | IEXTEN );
          
           /*
           * No sigint on BREAK,   CR-to-NL off,   input parity off,  
           * don't strip 8th bit on input,   output flow control off
           */
          
           term.c_lflag &= ~(  INPCK | ISTRIP | IXON );
           term.c_cc[VMIN] = 1;
           term.c_cc[VTIME] = 0;
          
           if (  tcsetattr (  STDIN_FILENO,   TCSANOW,   &term ) < 0 )
           {
           fprintf(  stdout,  "cannot set terminal attributes\n" );
           }
           }
          
           if (  !(  monitor_flags & RTEMS_MONITOR_NOSYMLOAD ) ) {
           rtems_monitor_symbols_loadup(   );
           }
          
           if (  monitor_flags & RTEMS_MONITOR_SUSPEND )
           (  void ) rtems_monitor_suspend(  RTEMS_NO_TIMEOUT );
          
           for (  ;; )
           {
           const rtems_monitor_command_entry_t *command;
          
           debugee = _Thread_Executing;
           rp = &debugee->Registers;
          #if (  CPU_HARDWARE_FP == TRUE ) || (  CPU_SOFTWARE_FP == TRUE )
           fp = debugee->fp_context; /* possibly 0 */
          #endif
          
           if (  0 == rtems_monitor_command_read(  command_buffer,   &argc,   argv ) )
           continue;
           if (  argc < 1
           || (  command = rtems_monitor_command_lookup(  argv [0] ) ) == 0 ) {
           /* no command */
           fprintf(  stdout,  "Unrecognised command; try 'help'\n" );
           continue;
           }
          
           command->command_function(  argc,   argv,   &command->command_arg,   verbose );
          
           fflush(  stdout );
           }
          }
          
          
          void
     597  rtems_monitor_kill(  void )
          {
           if (  rtems_monitor_task_id )
           rtems_task_delete(  rtems_monitor_task_id );
           rtems_monitor_task_id = 0;
          
           rtems_monitor_server_kill(   );
          }
          
          void
     607  rtems_monitor_init(  
           uint32_t monitor_flags
           )
          {
           rtems_status_code status;
          
           rtems_monitor_kill(   );
          
           status = rtems_task_create(  RTEMS_MONITOR_NAME,  
           1,  
           RTEMS_MINIMUM_STACK_SIZE * 2,  
           RTEMS_INTERRUPT_LEVEL(  0 ),  
           RTEMS_DEFAULT_ATTRIBUTES,  
           &rtems_monitor_task_id );
           if (  status != RTEMS_SUCCESSFUL )
           {
           rtems_error(  status,   "could not create monitor task" );
           return;
           }
          
           rtems_monitor_node = rtems_object_id_get_node(  rtems_monitor_task_id );
           rtems_monitor_default_node = rtems_monitor_node;
          
           rtems_monitor_server_init(  monitor_flags );
          
           if (  !(  monitor_flags & RTEMS_MONITOR_NOTASK ) ) {
           /*
           * Start the monitor task itself
           */
           status = rtems_task_start(  
           rtems_monitor_task_id,   rtems_monitor_task,   monitor_flags );
           if (  status != RTEMS_SUCCESSFUL ) {
           rtems_error(  status,   "could not start monitor" );
           return;
           }
           }
          }

libmisc/monitor/mon-extension.c

       1  /*
           * RTEMS Monitor extension support
           *
           * $Id: mon-extension.c,  v 1.14 2009/01/02 13:01:21 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/monitor.h>
          
          #include <stdio.h>
          
          void
      17  rtems_monitor_extension_canonical(  
           rtems_monitor_extension_t *canonical_extension,  
           void *extension_void
           )
          {
           Extension_Control *rtems_extension = (  Extension_Control * ) extension_void;
           rtems_extensions_table *e = &rtems_extension->Extension.Callouts;
          
           rtems_monitor_symbol_canonical_by_value(  &canonical_extension->e_create,  
           (  void * ) e->thread_create );
          
           rtems_monitor_symbol_canonical_by_value(  &canonical_extension->e_start,  
           (  void * ) e->thread_start );
           rtems_monitor_symbol_canonical_by_value(  &canonical_extension->e_restart,  
           (  void * ) e->thread_restart );
           rtems_monitor_symbol_canonical_by_value(  &canonical_extension->e_delete,  
           (  void * ) e->thread_delete );
           rtems_monitor_symbol_canonical_by_value(  &canonical_extension->e_tswitch,  
           (  void * ) e->thread_switch );
           rtems_monitor_symbol_canonical_by_value(  &canonical_extension->e_begin,  
           (  void * ) e->thread_begin );
           rtems_monitor_symbol_canonical_by_value(  &canonical_extension->e_exitted,  
           (  void * ) e->thread_exitted );
           rtems_monitor_symbol_canonical_by_value(  &canonical_extension->e_fatal,  
           (  void * ) e->fatal );
          }
          
          void
      45  rtems_monitor_extension_dump_header(  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           fprintf(  stdout,  "\
           ID NAME\n" );
          /*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
          0 1 2 3 4 5 6 7 */
          
           rtems_monitor_separator(   );
          }
          
          
          /*
           * Dump out the canonical form
           */
          
          void
      63  rtems_monitor_extension_dump(  
           rtems_monitor_extension_t *monitor_extension,  
           bool verbose
           )
          {
           uint32_t length = 0;
          
           length += rtems_monitor_dump_id(  monitor_extension->id );
           length += rtems_monitor_pad(  11,   length );
           length += rtems_monitor_dump_name(  monitor_extension->id );
          
           length += rtems_monitor_pad(  18,   length );
           length += fprintf(  stdout,  "create: " );
           length += rtems_monitor_symbol_dump(  &monitor_extension->e_create,   verbose );
           length += fprintf(  stdout,  "; start: " );
           length += rtems_monitor_symbol_dump(  &monitor_extension->e_start,   verbose );
           length += fprintf(  stdout,  "; restart: " );
           length += rtems_monitor_symbol_dump(  &monitor_extension->e_restart,   verbose );
           length += fprintf(  stdout,  "\n" );
           length = 0;
          
           length += rtems_monitor_pad(  18,   length );
           length += fprintf(  stdout,  "delete: " );
           length += rtems_monitor_symbol_dump(  &monitor_extension->e_delete,   verbose );
           length += fprintf(  stdout,  "; switch: " );
           length += rtems_monitor_symbol_dump(  &monitor_extension->e_tswitch,   verbose );
           length += fprintf(  stdout,  "; begin: " );
           length += rtems_monitor_symbol_dump(  &monitor_extension->e_begin,   verbose );
           length += fprintf(  stdout,  "\n" );
           length = 0;
          
           length += rtems_monitor_pad(  18,   length );
           length += fprintf(  stdout,  "exitted: " );
           length += rtems_monitor_symbol_dump(  &monitor_extension->e_exitted,   verbose );
           length += fprintf(  stdout,  "; fatal: " );
           length += rtems_monitor_symbol_dump(  &monitor_extension->e_fatal,   verbose );
           length += fprintf(  stdout,  "\n" );
           length = 0;
           fprintf(  stdout,  "\n" );
          }

libmisc/monitor/mon-itask.c

       1  /*
           * RTEMS Monitor init task support
           *
           * $Id: mon-itask.c,  v 1.20 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          #include <rtems/monitor.h>
          
          #include <inttypes.h>
          #include <stdio.h>
          
          /*
           * As above,   but just for init tasks
           */
          void
      22  rtems_monitor_init_task_canonical(  
           rtems_monitor_init_task_t *canonical_itask,  
           void *itask_void
           )
          {
           rtems_initialization_tasks_table *rtems_itask = itask_void;
          
           rtems_monitor_symbol_canonical_by_value(  &canonical_itask->entry,  
           (  void * ) rtems_itask->entry_point );
          
           canonical_itask->argument = rtems_itask->argument;
           canonical_itask->stack_size = rtems_itask->stack_size;
           canonical_itask->priority = rtems_itask->initial_priority;
           canonical_itask->modes = rtems_itask->mode_set;
           canonical_itask->attributes = rtems_itask->attribute_set;
          }
          
          void *
      40  rtems_monitor_init_task_next(  
           void *object_info __attribute__(  (  unused ) ),  
           rtems_monitor_init_task_t *canonical_init_task,  
           rtems_id *next_id
           )
          {
           rtems_initialization_tasks_table *itask;
           uint32_t n = rtems_object_id_get_index(  *next_id );
          
           if (  n >= Configuration_RTEMS_API.number_of_initialization_tasks )
           goto failed;
          
           _Thread_Disable_dispatch(   );
          
           itask = Configuration_RTEMS_API.User_initialization_tasks_table + n;
          
           /*
           * dummy up a fake id and name for this item
           */
          
           canonical_init_task->id = n;
           canonical_init_task->name = itask->name;
          
           *next_id += 1;
           return (  void * ) itask;
          
          failed:
           *next_id = RTEMS_OBJECT_ID_FINAL;
           return 0;
          }
          
          
          void
      73  rtems_monitor_init_task_dump_header(  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           fprintf(  stdout,  "\
           # NAME ENTRY ARGUMENT PRIO MODES ATTRIBUTES STACK SIZE\n" );
          /*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
          0 1 2 3 4 5 6 7 */
           rtems_monitor_separator(   );
          }
          
          /*
           */
          
          void
      88  rtems_monitor_init_task_dump(  
           rtems_monitor_init_task_t *monitor_itask,  
           bool verbose
           )
          {
           int length = 0;
          
           length += rtems_monitor_dump_decimal(  monitor_itask->id );
          
           length += rtems_monitor_pad(  7,   length );
           length += rtems_monitor_dump_name(  monitor_itask->id );
          
           length += rtems_monitor_pad(  14,   length );
           length += rtems_monitor_symbol_dump(  &monitor_itask->entry,   verbose );
          
           length += rtems_monitor_pad(  25,   length );
           length += fprintf(  stdout,  "%" PRId32 " [0x%" PRIx32 "]",  
           monitor_itask->argument,   monitor_itask->argument );
          
           length += rtems_monitor_pad(  39,   length );
           length += rtems_monitor_dump_priority(  monitor_itask->priority );
          
           length += rtems_monitor_pad(  46,   length );
           length += rtems_monitor_dump_modes(  monitor_itask->modes );
          
           length += rtems_monitor_pad(  54,   length );
           length += rtems_monitor_dump_attributes(  monitor_itask->attributes );
          
           length += rtems_monitor_pad(  66,   length );
           length += fprintf(  stdout,  "%" PRId32 " [0x%" PRIx32 "]",  
           monitor_itask->stack_size,   monitor_itask->stack_size );
          
           fprintf(  stdout,  "\n" );
          }

libmisc/monitor/mon-manager.c

       1  /*
           * RTEMS Monitor "manager" support.
           * Used to traverse object (  chain ) lists and print them out.
           *
           * $Id: mon-manager.c,  v 1.13 2008/01/23 22:57:43 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/monitor.h>
          
          #include <stdio.h>
          
          /*
           * "next" routine for all objects that are RTEMS manager objects
           */
          
          void *
      22  rtems_monitor_manager_next(  
           void *table_void,  
           void *canonical,  
           rtems_id *next_id
           )
          {
           Objects_Information *table = table_void;
           rtems_monitor_generic_t *copy;
           Objects_Control *object = 0;
           Objects_Locations location;
          
           /*
           * When we are called,   it must be local
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   ! _Objects_Is_local_id(  *next_id )  )
           goto done;
          #endif
          
           object = _Objects_Get_next(  table,   *next_id,   &location,   next_id );
          
           if (  object )
           {
           copy = (  rtems_monitor_generic_t * ) canonical;
           copy->id = object->id;
           copy->name = object->name.name_u32;
           }
          
          #if defined(  RTEMS_MULTIPROCESSING )
          done:
          #endif
           return object;
          }

libmisc/monitor/mon-monitor.c

       1  /*
           * RTEMS monitor main body
           *
           * TODO:
           * add stuff to RTEMS api
           * rtems_get_name(  id )
           * rtems_get_type(  id )
           * rtems_build_id(  node,   type,   num )
           * Add a command to dump out info about an arbitrary id when
           * types are added to id's
           * rtems> id idnum
           * idnum: node n,   object: whatever,   id: whatever
           * allow id's to be specified as n:t:id,   where 'n:t' is optional
           * should have a separate monitor FILE stream (  ala the debugger )
           * remote request/response stuff should be cleaned up
           * maybe we can use real rpc??
           * 'info' command to print out:
           * interrupt stack location,   direction and size
           * floating point config stuff
           * interrupt config stuff
           *
           * $Id: mon-monitor.c,  v 1.40 2010/04/07 14:58:45 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          
          #include <stdio.h>
          #include <string.h>
          #include <stdlib.h>
          
          #include <rtems/monitor.h>
          
          /* set by trap handler */
          extern rtems_tcb *debugger_interrupted_task;
          extern rtems_context *debugger_interrupted_task_context;
          extern uint32_t debugger_trap;
          
          /*
           * Various id's for the monitor
           * They need to be public variables for access by other agencies
           * such as debugger and remote servers'
           */
          
          rtems_id rtems_monitor_task_id;
          
          uint32_t rtems_monitor_node; /* our node number */
          uint32_t rtems_monitor_default_node; /* current default for commands */
          
          /*
           * The rtems symbol table
           */
          
          rtems_symbol_table_t *rtems_monitor_symbols;
          
          /*
           * The top-level commands
           */
          
          static const rtems_monitor_command_entry_t rtems_monitor_commands[] = {
           { "config",  
           "Show the system configuration.",  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_CONFIG },  
           &rtems_monitor_commands[1],  
           },  
           { "itask",  
           "List init tasks for the system",  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_INIT_TASK },  
           &rtems_monitor_commands[2],  
           },  
           { "mpci",  
           "Show the MPCI system configuration,   if configured.",  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_MPCI },  
           &rtems_monitor_commands[3],  
           },  
           { "pause",  
           "Monitor goes to \"sleep\" for specified ticks (  default is 1 ). "
           "Monitor will resume at end of period or if explicitly awakened\n"
           " pause [ticks]",  
           0,  
           rtems_monitor_pause_cmd,  
           { 0 },  
           &rtems_monitor_commands[4],  
           },  
           { "continue",  
           "Put the monitor to sleep waiting for an explicit wakeup from the "
           "program running.\n",  
           0,  
           rtems_monitor_continue_cmd,  
           { 0 },  
           &rtems_monitor_commands[5],  
           },  
           { "go",  
           "Alias for 'continue'",  
           0,  
           rtems_monitor_continue_cmd,  
           { 0 },  
           &rtems_monitor_commands[6],  
           },  
           { "node",  
           "Specify default node number for commands that take id's.\n"
           " node [ node number ]",  
           0,  
           rtems_monitor_node_cmd,  
           { 0 },  
           &rtems_monitor_commands[7],  
           },  
           { "symbol",  
           "Display value associated with specified symbol. "
           "Defaults to displaying all known symbols.\n"
           " symbol [ symbolname [symbolname ... ] ]",  
           0,  
           rtems_monitor_symbol_cmd,  
           { .symbol_table = &rtems_monitor_symbols },  
           &rtems_monitor_commands[8],  
           },  
           { "extension",  
           "Display information about specified extensions. "
           "Default is to display information about all extensions on this node.\n"
           " extension [id [id ...] ]",  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_EXTENSION },  
           &rtems_monitor_commands[9],  
           },  
           { "task",  
           "Display information about the specified tasks. "
           "Default is to display information about all tasks on this node.\n"
           " task [id [id ...] ]",  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_TASK },  
           &rtems_monitor_commands[10],  
           },  
           { "queue",  
           "Display information about the specified message queues. "
           "Default is to display information about all queues on this node.\n"
           " queue [id [id ... ] ]",  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_QUEUE },  
           &rtems_monitor_commands[11],  
           },  
           { "sema",  
           "sema [id [id ... ] ]\n"
           " display information about the specified semaphores\n"
           " Default is to display information about all semaphores on this node\n"
           ,  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_SEMAPHORE },  
           &rtems_monitor_commands[12],  
           },  
           { "region",  
           "region [id [id ... ] ]\n"
           " display information about the specified regions\n"
           " Default is to display information about all regions on this node\n"
           ,  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_REGION },  
           &rtems_monitor_commands[13],  
           },  
           { "part",  
           "part [id [id ... ] ]\n"
           " display information about the specified partitions\n"
           " Default is to display information about all partitions on this node\n"
           ,  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_PARTITION },  
           &rtems_monitor_commands[14],  
           },  
           { "object",  
           "Display information about specified RTEMS objects. "
           "Object id's must include 'type' information. "
           "(  which may normally be defaulted )\n"
           " object [id [id ...] ]",  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_INVALID },  
           &rtems_monitor_commands[15],  
           },  
           { "driver",  
           "Display the RTEMS device driver table.\n"
           " driver [ major [ major ... ] ]",  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_DRIVER },  
           &rtems_monitor_commands[16],  
           },  
           { "dname",  
           "Displays information about named drivers.\n",  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_DNAME },  
           &rtems_monitor_commands[17],  
           },  
           { "exit",  
           "Invoke 'rtems_fatal_error_occurred' with 'status' "
           "(  default is RTEMS_SUCCESSFUL )\n"
           " exit [status]",  
           0,  
           rtems_monitor_fatal_cmd,  
           { .status_code = RTEMS_SUCCESSFUL },  
           &rtems_monitor_commands[18],  
           },  
           { "fatal",  
           "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
           " fatal [status]",  
           0,  
           rtems_monitor_fatal_cmd,  
           { .status_code = RTEMS_TASK_EXITTED },   /* exit value */
           &rtems_monitor_commands[19],  
           },  
           { "quit",  
           "Alias for 'exit'\n",  
           0,  
           rtems_monitor_fatal_cmd,  
           { .status_code = RTEMS_SUCCESSFUL },   /* exit value */
           &rtems_monitor_commands[20],  
           },  
           { "reset",  
           "(  SW )Resets the System.",  
           0,  
           rtems_monitor_reset_cmd,  
           { 0 },  
           &rtems_monitor_commands[21],  
           },  
          #ifdef RTEMS_POSIX_API
           { "pthread",  
           "Display information about the specified pthreads. "
           "Default is to display information about all pthreads on this node.\n"
           " pthread [id [id ...] ]",  
           0,  
           rtems_monitor_object_cmd,  
           { RTEMS_MONITOR_OBJECT_PTHREAD },  
           &rtems_monitor_commands[22],  
           },  
           #define RTEMS_MONITOR_DEBUGGER_NEXT 23
          #else
           #define RTEMS_MONITOR_DEBUGGER_NEXT 22
          #endif
          #ifdef CPU_INVOKE_DEBUGGER
           { "debugger",  
           "Enter the debugger,   if possible. "
           "A continue from the debugger will return to the monitor.\n",  
           0,  
           rtems_monitor_debugger_cmd,  
           { 0 },  
           &rtems_monitor_commands[RTEMS_MONITOR_DEBUGGER_NEXT],  
           },  
          #endif
           { "help",  
           "Provide information about commands. "
           "Default is show basic command summary.\n"
           "help [ command [ command ] ]",  
           0,  
           rtems_monitor_help_cmd,  
           { .monitor_command_entry = rtems_monitor_commands },  
           NULL
           }
          };
          
          /*
           * All registered commands.
           */
          
          static const rtems_monitor_command_entry_t *rtems_monitor_registered_commands =
           &rtems_monitor_commands [0];
          
          
          rtems_status_code
     283  rtems_monitor_suspend(  rtems_interval timeout )
          {
           rtems_event_set event_set;
           rtems_status_code status;
          
           status = rtems_event_receive(  MONITOR_WAKEUP_EVENT,  
           RTEMS_DEFAULT_OPTIONS,  
           timeout,  
           &event_set );
           return status;
          }
          
     295  void __attribute__(  (  weak ) )
          rtems_monitor_reset_cmd(  
           int argc,  
           char **argv,  
           const rtems_monitor_command_arg_t* command_arg,  
           bool verbose
           )
          {
          
          }
          
          void
     307  rtems_monitor_wakeup(  void )
          {
           rtems_status_code status;
          
           status = rtems_event_send(  rtems_monitor_task_id,   MONITOR_WAKEUP_EVENT );
          }
          
     314  void rtems_monitor_debugger_cmd(  
           int argc __attribute__(  (  unused ) ),  
           char **argv __attribute__(  (  unused ) ),  
           const rtems_monitor_command_arg_t *command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) )
           )
          {
          #ifdef CPU_INVOKE_DEBUGGER
           CPU_INVOKE_DEBUGGER;
          #endif
          }
          
     326  void rtems_monitor_pause_cmd(  
           int argc,  
           char **argv,  
           const rtems_monitor_command_arg_t *command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           if (  argc == 1 )
           rtems_monitor_suspend(  1 );
           else
           rtems_monitor_suspend(  strtoul(  argv[1],   0,   0 ) );
          }
          
     339  void rtems_monitor_fatal_cmd(  
           int argc,  
           char **argv,  
           const rtems_monitor_command_arg_t *command_arg,  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           if (  argc == 1 )
           rtems_fatal_error_occurred(  command_arg->status_code );
           else
           rtems_fatal_error_occurred(  strtoul(  argv[1],   0,   0 ) );
          }
          
     352  void rtems_monitor_continue_cmd(  
           int argc __attribute__(  (  unused ) ),  
           char **argv __attribute__(  (  unused ) ),  
           const rtems_monitor_command_arg_t *command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           rtems_monitor_suspend(  RTEMS_NO_TIMEOUT );
          }
          
     362  void rtems_monitor_node_cmd(  
           int argc,  
           char **argv,  
           const rtems_monitor_command_arg_t *command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           uint32_t new_node = rtems_monitor_default_node;
          
           switch (  argc )
           {
           case 1: /* no node,   just set back to ours */
           new_node = rtems_monitor_node;
           break;
          
           case 2:
           new_node = strtoul(  argv[1],   0,   0 );
           break;
          
           default:
           fprintf(  stdout,  "invalid syntax,   try 'help node'\n" );
           break;
           }
          
           #if defined(  RTEMS_MULTIPROCESSING )
           if (  (  new_node >= 1 ) &&
           _Configuration_MP_table &&
           (  new_node <= _Configuration_MP_table->maximum_nodes ) )
           rtems_monitor_default_node = new_node;
           #endif
          }
          
          
          /*
           * Function: rtems_monitor_symbols_loadup
           *
           * Description:
           * Create and load the monitor's symbol table.
           * We are reading the output format of 'gnm' which looks like this:
           *
           * 400a7068 ? _Rate_monotonic_Information
           * 400a708c ? _Thread_Dispatch_disable_level
           * 400a7090 ? _Configuration_Table
           *
           * We ignore the type field.
           *
           * Side Effects:
           * Creates and fills in 'rtems_monitor_symbols' table
           *
           * TODO
           * there should be a BSP #define or something like that
           * to do this; Assuming stdio is crazy.
           * Someday this should know BFD
           * Maybe we could get objcopy to just copy the symbol areas
           * and copy that down.
           *
           */
          
          void
     421  rtems_monitor_symbols_loadup(  void )
          {
           FILE *fp;
           char buffer[128];
          
           if (  rtems_monitor_symbols )
           rtems_symbol_table_destroy(  rtems_monitor_symbols );
          
           rtems_monitor_symbols = rtems_symbol_table_create(   );
           if (  rtems_monitor_symbols == 0 )
           return;
          
           fp = fopen(  "symbols",   "r" );
          
           if (  fp == 0 )
           return;
          
           while (  fgets(  buffer,   sizeof(  buffer ) - 1,   fp ) )
           {
           char *symbol;
           char *value;
           char *ignored_type;
          
           value = strtok(  buffer,   " \t\n" );
           ignored_type = strtok(  0,   " \t\n" );
           symbol = strtok(  0,   " \t\n" );
          
           if (  symbol && ignored_type && value )
           {
           rtems_symbol_t *sp;
           sp = rtems_symbol_create(  rtems_monitor_symbols,  
           symbol,  
           (  uint32_t ) strtoul(  value,   0,   16 ) );
           if (  sp == 0 )
           {
           fprintf(  stdout,  "could not define symbol '%s'\n",   symbol );
           goto done;
           }
           }
           else
           {
           fprintf(  stdout,  "parsing error on '%s'\n",   buffer );
           goto done;
           }
           }
          
          done:
           fclose(  fp );
           return;
          }
          
          /*
           * User registered commands.
           */
          
          int
     477  rtems_monitor_insert_cmd (  
           rtems_monitor_command_entry_t *command
           )
          {
           const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;
          
           /* Reject empty commands */
           if (  command->command == NULL ) {
           return 0;
           }
          
           /* Reject command if already present */
           while (  e->next != NULL ) {
           if (  e->command != NULL && strcmp(  command->command,   e->command ) == 0 ) {
           return 0;
           }
           e = e->next;
           }
          
           /* Prepend new command */
           command->next = rtems_monitor_registered_commands;
           rtems_monitor_registered_commands = command;
          
           return 1;
          }
          
          /**
           * @brief Iterates through all registerd commands.
           *
           * For each command the interation routine @a routine is called with the
           * command entry and the user provided argument @a arg. It is guaranteed that
           * the command name and function are not NULL.
           */
     510  void rtems_monitor_command_iterate(  
           rtems_monitor_per_command_routine routine,  
           void *arg
           )
          {
           const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;
          
           while (  e != NULL ) {
           if (  e->command != NULL && e->command_function != NULL ) {
           if (  !routine(  e,   arg ) ) {
           break;
           }
           }
           e = e->next;
           }
          }

libmisc/monitor/mon-mpci.c

       1  /*
           * RTEMS MPCI Config display support
           *
           * TODO
           *
           * $Id: mon-mpci.c,  v 1.15 2008/12/15 19:21:01 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          #include <rtems/monitor.h>
          
          #include <stdio.h>
          #include <stdlib.h> /* strtoul(   ) */
          #include <inttypes.h>
          
          #define DATACOL 15
          
          /*
           * Fill in entire monitor config table
           * for sending to a remote monitor or printing on the local system
           */
          
          void
      29  rtems_monitor_mpci_canonical(  
           rtems_monitor_mpci_t *canonical_mpci,  
           void *config_void
           )
          {
           rtems_configuration_table *c = &Configuration;
           rtems_multiprocessing_table *m;
           rtems_mpci_table *mt;
          
           m = c->User_multiprocessing_table;
           if (  m == 0 )
           return;
           mt = m->User_mpci_table;
          
           canonical_mpci->node = m->node;
           canonical_mpci->maximum_nodes = m->maximum_nodes;
           canonical_mpci->maximum_global_objects = m->maximum_global_objects;
           canonical_mpci->maximum_proxies = m->maximum_proxies;
          
           canonical_mpci->default_timeout = mt->default_timeout;
           canonical_mpci->maximum_packet_size = mt->maximum_packet_size;
          
           rtems_monitor_symbol_canonical_by_value(  &canonical_mpci->initialization,  
           (  void * ) mt->initialization );
          
           rtems_monitor_symbol_canonical_by_value(  &canonical_mpci->get_packet,  
           (  void * ) mt->get_packet );
           rtems_monitor_symbol_canonical_by_value(  &canonical_mpci->return_packet,  
           (  void * ) mt->return_packet );
           rtems_monitor_symbol_canonical_by_value(  &canonical_mpci->send_packet,  
           (  void * ) mt->send_packet );
           rtems_monitor_symbol_canonical_by_value(  &canonical_mpci->receive_packet,  
           (  void * ) mt->receive_packet );
          }
          
          /*
           * This is easy,   since there is only 1 (  altho we could get them from
           * other nodes... )
           */
          
          void *
      70  rtems_monitor_mpci_next(  
           void *object_info,  
           rtems_monitor_mpci_t *canonical_mpci,  
           rtems_id *next_id
           )
          {
           rtems_configuration_table *c = &Configuration;
           int n = rtems_object_id_get_index(  *next_id );
          
           if (  n >= 1 )
           goto failed;
          
           if (   ! c->User_multiprocessing_table )
           goto failed;
          
           _Thread_Disable_dispatch(   );
          
           *next_id += 1;
           return (  void * ) c;
          
          failed:
           *next_id = RTEMS_OBJECT_ID_FINAL;
           return 0;
          }
          
          
          void
      97  rtems_monitor_mpci_dump_header(  
           bool verbose
           )
          {
           fprintf(  stdout,  "\
           max max max default max\n\
           node nodes globals proxies timeout pktsize\n" );
          /*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
          0 1 2 3 4 5 6 7 */
          
           rtems_monitor_separator(   );
          }
          
          
          void
     112  rtems_monitor_mpci_dump(  
           rtems_monitor_mpci_t *monitor_mpci,  
           bool verbose
           )
          {
           uint32_t length = 0;
          
           length += rtems_monitor_pad(  2,   length );
           length += fprintf(  stdout,  " %" PRId32 ,   monitor_mpci->node );
           length += rtems_monitor_pad(  11,   length );
           length += fprintf(  stdout,  "%" PRId32,   monitor_mpci->maximum_nodes );
          
           length += rtems_monitor_pad(  18,   length );
           length += rtems_monitor_dump_decimal(  monitor_mpci->maximum_global_objects );
          
           length += rtems_monitor_pad(  28,   length );
           length += rtems_monitor_dump_decimal(  monitor_mpci->maximum_proxies );
          
           length += rtems_monitor_pad(  37,   length );
           length += rtems_monitor_dump_decimal(  monitor_mpci->default_timeout );
          
           length += rtems_monitor_pad(  46,   length );
           length += rtems_monitor_dump_decimal(  (  uint32_t ) monitor_mpci->maximum_packet_size );
          
           fprintf(  stdout,  "\n" );
           length = 0;
           length += rtems_monitor_pad(  DATACOL,   length );
          
           length += fprintf(  stdout,  "init: " );
           length += rtems_monitor_symbol_dump(  &monitor_mpci->initialization,   verbose );
          
           fprintf(  stdout,  "\n" );
           length = 0;
           length += rtems_monitor_pad(  DATACOL,   length );
          
           length += fprintf(  stdout,  "get: " );
           length += rtems_monitor_symbol_dump(  &monitor_mpci->get_packet,   verbose );
           length += fprintf(  stdout,  "; return: " );
           length += rtems_monitor_symbol_dump(  &monitor_mpci->return_packet,   verbose );
          
           fprintf(  stdout,  "\n" );
           length = 0;
           length += rtems_monitor_pad(  DATACOL,   length );
          
           length += fprintf(  stdout,  "send: " );
           length += rtems_monitor_symbol_dump(  &monitor_mpci->send_packet,   verbose );
           length += fprintf(  stdout,  "; receive: " );
           length += rtems_monitor_symbol_dump(  &monitor_mpci->receive_packet,   verbose );
          
           fprintf(  stdout,  "\n" );
           length = 0;
          }

libmisc/monitor/mon-network.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mon-network.c,  v 1.9 2010/03/12 16:26:14 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <stdio.h>
          #include <ctype.h>
          #include <errno.h>
          
          #include <rtems/rtems_bsdnet.h>
          #include <sys/socket.h>
          #include <net/if.h>
          #include <arpa/inet.h>
          #include <netinet/in.h>
          #include <sys/sockio.h>
          #include <net/route.h>
          
          
      30  void mon_ifconfig(  int argc,   char *argv[],  
           uint32_t command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           struct sockaddr_in ipaddr;
           struct sockaddr_in dstaddr;
           struct sockaddr_in netmask;
           struct sockaddr_in broadcast;
           char *iface;
           int f_ip = 0;
           int f_ptp = 0;
           int f_netmask = 0;
           int f_up = 0;
           int f_down = 0;
           int f_bcast = 0;
           int cur_idx;
           int rc;
           int flags;
          
           memset(  &ipaddr,   0,   sizeof(  ipaddr ) );
           memset(  &dstaddr,   0,   sizeof(  dstaddr ) );
           memset(  &netmask,   0,   sizeof(  netmask ) );
           memset(  &broadcast,   0,   sizeof(  broadcast ) );
          
           ipaddr.sin_len = sizeof(  ipaddr );
           ipaddr.sin_family = AF_INET;
          
           dstaddr.sin_len = sizeof(  dstaddr );
           dstaddr.sin_family = AF_INET;
          
           netmask.sin_len = sizeof(  netmask );
           netmask.sin_family = AF_INET;
          
           broadcast.sin_len = sizeof(  broadcast );
           broadcast.sin_family = AF_INET;
          
           cur_idx = 0;
           if (  argc <= 1 ) {
           /* display all interfaces */
           iface = NULL;
           cur_idx += 1;
           } else {
           iface = argv[1];
           if (  isdigit(  (  unsigned char )*argv[2] ) ) {
           if (  inet_pton(  AF_INET,   argv[2],   &ipaddr.sin_addr ) < 0 ) {
           printf(  "bad ip address: %s\n",   argv[2] );
           return;
           }
           f_ip = 1;
           cur_idx += 3;
           } else {
           cur_idx += 2;
           }
           }
          
           if (  (  f_down !=0 ) && (  f_ip != 0 ) ) {
           f_up = 1;
           }
          
           while(  argc > cur_idx ) {
           if (  strcmp(  argv[cur_idx],   "up" ) == 0 ) {
           f_up = 1;
           if (  f_down != 0 ) {
           printf(  "Can't make interface up and down\n" );
           }
           } else if(  strcmp(  argv[cur_idx],   "down" ) == 0 ) {
           f_down = 1;
           if (  f_up != 0 ) {
           printf(  "Can't make interface up and down\n" );
           }
           } else if(  strcmp(  argv[cur_idx],   "netmask" ) == 0 ) {
           if (  (  cur_idx + 1 ) >= argc ) {
           printf(  "No netmask address\n" );
           return;
           }
           if (  inet_pton(  AF_INET,   argv[cur_idx+1],   &netmask.sin_addr ) < 0 ) {
           printf(  "bad netmask: %s\n",   argv[cur_idx] );
           return;
           }
           f_netmask = 1;
           cur_idx += 1;
           } else if(  strcmp(  argv[cur_idx],   "broadcast" ) == 0 ) {
           if (  (  cur_idx + 1 ) >= argc ) {
           printf(  "No broadcast address\n" );
           return;
           }
           if (  inet_pton(  AF_INET,   argv[cur_idx+1],   &broadcast.sin_addr ) < 0 ) {
           printf(  "bad broadcast: %s\n",   argv[cur_idx] );
           return;
           }
           f_bcast = 1;
           cur_idx += 1;
           } else if(  strcmp(  argv[cur_idx],   "pointopoint" ) == 0 ) {
           if (  (  cur_idx + 1 ) >= argc ) {
           printf(  "No pointopoint address\n" );
           return;
           }
           if (  inet_pton(  AF_INET,   argv[cur_idx+1],   &dstaddr.sin_addr ) < 0 ) {
           printf(  "bad pointopoint: %s\n",   argv[cur_idx] );
           return;
           }
          
           f_ptp = 1;
           cur_idx += 1;
           } else {
           printf(  "Bad parameter: %s\n",   argv[cur_idx] );
           return;
           }
          
           cur_idx += 1;
           }
          
           printf(  "ifconfig " );
           if (  iface != NULL ) {
           printf(  "%s ",   iface );
           if (  f_ip != 0 ) {
           char str[256];
           inet_ntop(  AF_INET,   &ipaddr.sin_addr,   str,   256 );
           printf(  "%s ",   str );
           }
          
           if (  f_netmask != 0 ) {
           char str[256];
           inet_ntop(  AF_INET,   &netmask.sin_addr,   str,   256 );
           printf(  "netmask %s ",   str );
           }
          
           if (  f_bcast != 0 ) {
           char str[256];
           inet_ntop(  AF_INET,   &broadcast.sin_addr,   str,   256 );
           printf(  "broadcast %s ",   str );
           }
          
           if (  f_ptp != 0 ) {
           char str[256];
           inet_ntop(  AF_INET,   &dstaddr.sin_addr,   str,   256 );
           printf(  "pointopoint %s ",   str );
           }
          
           if (  f_up != 0 ) {
           printf(  "up\n" );
           } else if (  f_down != 0 ) {
           printf(  "down\n" );
           } else {
           printf(  "\n" );
           }
           }
          
           if (  (  iface == NULL ) || (  (  f_ip == 0 ) && (  f_down == 0 ) && (  f_up == 0 ) ) ) {
           rtems_bsdnet_show_if_stats(   );
           return;
           }
          
           flags = 0;
           if (  f_netmask ) {
           rc = rtems_bsdnet_ifconfig(  iface,   SIOCSIFNETMASK,   &netmask );
           if (  rc < 0 ) {
           printf(  "Could not set netmask: %s\n",   strerror(  errno ) );
           return;
           }
           }
          
           if (  f_bcast ) {
           rc = rtems_bsdnet_ifconfig(  iface,   SIOCSIFBRDADDR,   &broadcast );
           if (  rc < 0 ) {
           printf(  "Could not set broadcast: %s\n",   strerror(  errno ) );
           return;
           }
           }
          
           if (  f_ptp ) {
           rc = rtems_bsdnet_ifconfig(  iface,   SIOCSIFDSTADDR,   &dstaddr );
           if (  rc < 0 ) {
           printf(  "Could not set destination address: %s\n",   strerror(  errno ) );
           return;
           }
           flags |= IFF_POINTOPOINT;
           }
          
           /* This must come _after_ setting the netmask,   broadcast addresses */
           if (  f_ip ) {
           rc = rtems_bsdnet_ifconfig(  iface,   SIOCSIFADDR,   &ipaddr );
           if (  rc < 0 ) {
           printf(  "Could not set IP address: %s\n",   strerror(  errno ) );
           return;
           }
           }
          
           if (  f_up != 0 ) {
           flags |= IFF_UP;
           }
          
           if (  f_down != 0 ) {
           printf(  "Warning: taking interfaces down is not supported\n" );
           }
          
           rc = rtems_bsdnet_ifconfig(  iface,   SIOCSIFFLAGS,   &flags );
           if (  rc < 0 ) {
           printf(  "Could not set interface flags: %s\n",   strerror(  errno ) );
           return;
           }
          }
          
          
          
     235  void mon_route(  int argc,   char *argv[],  
           uint32_t command_arg __attribute__(  (  unused ) ),  
           bool verbose __attribute__(  (  unused ) ) )
          {
           int cmd;
           struct sockaddr_in dst;
           struct sockaddr_in gw;
           struct sockaddr_in netmask;
           int f_host;
           int f_gw = 0;
           int cur_idx;
           int flags;
           int rc;
          
           memset(  &dst,   0,   sizeof(  dst ) );
           memset(  &gw,   0,   sizeof(  gw ) );
           memset(  &netmask,   0,   sizeof(  netmask ) );
          
           dst.sin_len = sizeof(  dst );
           dst.sin_family = AF_INET;
           dst.sin_addr.s_addr = inet_addr(  "0.0.0.0" );
          
           gw.sin_len = sizeof(  gw );
           gw.sin_family = AF_INET;
           gw.sin_addr.s_addr = inet_addr(  "0.0.0.0" );
          
           netmask.sin_len = sizeof(  netmask );
           netmask.sin_family = AF_INET;
           netmask.sin_addr.s_addr = inet_addr(  "255.255.255.0" );
          
           if (  argc < 2 ) {
           rtems_bsdnet_show_inet_routes(   );
           return;
           }
          
           if (  strcmp(  argv[1],   "add" ) == 0 ) {
           cmd = RTM_ADD;
           } else if (  strcmp(  argv[1],   "del" ) == 0 ) {
           cmd = RTM_DELETE;
           } else {
           printf(  "invalid command: %s\n",   argv[1] );
           printf(  "\tit should be 'add' or 'del'\n" );
           return;
           }
          
           if (  argc < 3 ) {
           printf(  "not enough arguments\n" );
           return;
           }
          
           if (  strcmp(  argv[2],   "-host" ) == 0 ) {
           f_host = 1;
           } else if (  strcmp(  argv[2],   "-net" ) == 0 ) {
           f_host = 0;
           } else {
           printf(  "Invalid type: %s\n",   argv[1] );
           printf(  "\tit should be '-host' or '-net'\n" );
           return;
           }
          
           if (  argc < 4 ) {
           printf(  "not enough arguments\n" );
           return;
           }
          
           inet_pton(  AF_INET,   argv[3],   &dst.sin_addr );
          
           cur_idx = 4;
           while(  cur_idx < argc ) {
           if (  strcmp(  argv[cur_idx],   "gw" ) == 0 ) {
           if (  (  cur_idx +1 ) >= argc ) {
           printf(  "no gateway address\n" );
           return;
           }
           f_gw = 1;
           inet_pton(  AF_INET,   argv[cur_idx + 1],   &gw.sin_addr );
           cur_idx += 1;
           } else if(  strcmp(  argv[cur_idx],   "netmask" ) == 0 ) {
           if (  (  cur_idx +1 ) >= argc ) {
           printf(  "no netmask address\n" );
           return;
           }
           f_gw = 1;
           inet_pton(  AF_INET,   argv[cur_idx + 1],   &netmask.sin_addr );
           cur_idx += 1;
           } else {
           printf(  "Unknown argument: %s\n",   argv[cur_idx] );
           return;
           }
           cur_idx += 1;
           }
          
           flags = RTF_STATIC;
           if (  f_gw != 0 ) {
           flags |= RTF_GATEWAY;
           }
           if (  f_host != 0 ) {
           flags |= RTF_HOST;
           }
          
           rc = rtems_bsdnet_rtrequest(  cmd,  
           (  struct sockaddr* ) &dst,  
           (  struct sockaddr* ) &gw,  
           (  struct sockaddr* ) &netmask,   flags,   NULL );
           if (  rc < 0 ) {
           printf(  "Error adding route\n" );
           }
          }

libmisc/monitor/mon-object.c

       1  /*
           * RTEMS Monitor "object" support.
           *
           * Used to traverse object lists and print them out.
           * An object can be an RTEMS object (  chain based stuff ) or
           * a "misc" object such as a device driver.
           *
           * Each object has its own file in this directory (  eg: extension.c )
           * That file provides routines to convert a "native" structure
           * to its canonical form,   print a canonical structure,   etc.
           *
           * TODO:
           * should allow for non-numeric id's???
           *
           * $Id: mon-object.c,  v 1.30 2008/12/18 15:25:27 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          #include <rtems/monitor.h>
          #if defined(  RTEMS_POSIX_API )
           #include <rtems/posix/pthread.h>
          #endif
          
          #include <stdio.h>
          #include <stdlib.h> /* strtoul(   ) */
          #include <string.h> /* memcpy(   ) */
          
          #define NUMELEMS(  arr ) (  sizeof(  arr ) / sizeof(  arr[0] ) )
          
          /*
           * add:
           * next
           */
          
          static const rtems_monitor_object_info_t rtems_monitor_object_info[] =
          {
           { RTEMS_MONITOR_OBJECT_CONFIG,  
           (  void * ) 0,  
           sizeof(  rtems_monitor_config_t ),  
           (  rtems_monitor_object_next_fn ) rtems_monitor_config_next,  
           (  rtems_monitor_object_canonical_fn ) rtems_monitor_config_canonical,  
           (  rtems_monitor_object_dump_header_fn ) rtems_monitor_config_dump_header,  
           (  rtems_monitor_object_dump_fn ) rtems_monitor_config_dump,  
           },  
           { RTEMS_MONITOR_OBJECT_MPCI,  
           (  void * ) 0,  
          #if defined(  RTEMS_MULTIPROCESSING )
           sizeof(  rtems_monitor_mpci_t ),  
           (  rtems_monitor_object_next_fn ) rtems_monitor_mpci_next,  
           (  rtems_monitor_object_canonical_fn ) rtems_monitor_mpci_canonical,  
           (  rtems_monitor_object_dump_header_fn ) rtems_monitor_mpci_dump_header,  
           (  rtems_monitor_object_dump_fn ) rtems_monitor_mpci_dump,  
          #else
           0,  
           (  rtems_monitor_object_next_fn ) 0,  
           (  rtems_monitor_object_canonical_fn ) 0,  
           (  rtems_monitor_object_dump_header_fn ) 0,  
           (  rtems_monitor_object_dump_fn ) 0,  
          #endif
           },  
           { RTEMS_MONITOR_OBJECT_INIT_TASK,  
           (  void * ) 0,  
           sizeof(  rtems_monitor_init_task_t ),  
           (  rtems_monitor_object_next_fn ) rtems_monitor_init_task_next,  
           (  rtems_monitor_object_canonical_fn ) rtems_monitor_init_task_canonical,  
           (  rtems_monitor_object_dump_header_fn ) rtems_monitor_init_task_dump_header,  
           (  rtems_monitor_object_dump_fn ) rtems_monitor_init_task_dump,  
           },  
           { RTEMS_MONITOR_OBJECT_TASK,  
           (  void * ) &_RTEMS_tasks_Information,  
           sizeof(  rtems_monitor_task_t ),  
           (  rtems_monitor_object_next_fn ) rtems_monitor_manager_next,  
           (  rtems_monitor_object_canonical_fn ) rtems_monitor_task_canonical,  
           (  rtems_monitor_object_dump_header_fn ) rtems_monitor_task_dump_header,  
           (  rtems_monitor_object_dump_fn ) rtems_monitor_task_dump,  
           },  
           { RTEMS_MONITOR_OBJECT_QUEUE,  
           (  void * ) &_Message_queue_Information,  
           sizeof(  rtems_monitor_queue_t ),  
           (  rtems_monitor_object_next_fn ) rtems_monitor_manager_next,  
           (  rtems_monitor_object_canonical_fn ) rtems_monitor_queue_canonical,  
           (  rtems_monitor_object_dump_header_fn ) rtems_monitor_queue_dump_header,  
           (  rtems_monitor_object_dump_fn ) rtems_monitor_queue_dump,  
           },  
           { RTEMS_MONITOR_OBJECT_SEMAPHORE,  
           (  void * ) &_Semaphore_Information,  
           sizeof(  rtems_monitor_sema_t ),  
           (  rtems_monitor_object_next_fn ) rtems_monitor_manager_next,  
           (  rtems_monitor_object_canonical_fn ) rtems_monitor_sema_canonical,  
           (  rtems_monitor_object_dump_header_fn ) rtems_monitor_sema_dump_header,  
           (  rtems_monitor_object_dump_fn ) rtems_monitor_sema_dump,  
           },  
           { RTEMS_MONITOR_OBJECT_REGION,  
           (  void * ) &_Region_Information,  
           sizeof(  rtems_monitor_region_t ),  
           (  rtems_monitor_object_next_fn ) rtems_monitor_manager_next,  
           (  rtems_monitor_object_canonical_fn ) rtems_monitor_region_canonical,  
           (  rtems_monitor_object_dump_header_fn ) rtems_monitor_region_dump_header,  
           (  rtems_monitor_object_dump_fn ) rtems_monitor_region_dump,  
           },  
           { RTEMS_MONITOR_OBJECT_PARTITION,  
           (  void * ) &_Partition_Information,  
           sizeof(  rtems_monitor_part_t ),  
           (  rtems_monitor_object_next_fn ) rtems_monitor_manager_next,  
           (  rtems_monitor_object_canonical_fn ) rtems_monitor_part_canonical,  
           (  rtems_monitor_object_dump_header_fn ) rtems_monitor_part_dump_header,  
           (  rtems_monitor_object_dump_fn ) rtems_monitor_part_dump,  
           },  
           { RTEMS_MONITOR_OBJECT_EXTENSION,  
           (  void * ) &_Extension_Information,  
           sizeof(  rtems_monitor_extension_t ),  
           (  rtems_monitor_object_next_fn ) rtems_monitor_manager_next,  
           (  rtems_monitor_object_canonical_fn ) rtems_monitor_extension_canonical,  
           (  rtems_monitor_object_dump_header_fn ) rtems_monitor_extension_dump_header,  
           (  rtems_monitor_object_dump_fn ) rtems_monitor_extension_dump,  
           },  
           { RTEMS_MONITOR_OBJECT_DRIVER,  
           (  void * ) 0,  
           sizeof(  rtems_monitor_driver_t ),  
           (  rtems_monitor_object_next_fn ) rtems_monitor_driver_next,  
           (  rtems_monitor_object_canonical_fn ) rtems_monitor_driver_canonical,  
           (  rtems_monitor_object_dump_header_fn ) rtems_monitor_driver_dump_header,  
           (  rtems_monitor_object_dump_fn ) rtems_monitor_driver_dump,  
           },  
          #if defined(  RTEMS_POSIX_API )
           { RTEMS_MONITOR_OBJECT_PTHREAD,  
           (  void * ) &_POSIX_Threads_Information,  
           sizeof(  rtems_monitor_task_t ),  
           (  rtems_monitor_object_next_fn ) rtems_monitor_manager_next,  
           (  rtems_monitor_object_canonical_fn ) rtems_monitor_task_canonical,  
           (  rtems_monitor_object_dump_header_fn ) rtems_monitor_task_dump_header,  
           (  rtems_monitor_object_dump_fn ) rtems_monitor_task_dump,  
           },  
          #endif
          };
          
          /*
           * Allow id's to be specified without the node number or
           * type for convenience.
           */
          
          rtems_id
     148  rtems_monitor_id_fixup(  
           rtems_id id,  
           uint32_t default_node,  
           rtems_monitor_object_type_t type
           )
          {
           uint32_t node;
          
           node = rtems_object_id_get_node(  id );
           if (  node == 0 )
           {
           if (  rtems_object_id_get_class(  id ) != OBJECTS_CLASSIC_NO_CLASS )
           type = rtems_object_id_get_class(  id );
          
           id = rtems_build_id(  
           OBJECTS_CLASSIC_API,  
           type,  
           default_node,  
           rtems_object_id_get_index(  id )
            );
           }
           return id;
          }
          
          
          const rtems_monitor_object_info_t *
     174  rtems_monitor_object_lookup(  
           rtems_monitor_object_type_t type
           )
          {
           const rtems_monitor_object_info_t *p;
           for (  p = &rtems_monitor_object_info[0];
           p < &rtems_monitor_object_info[NUMELEMS(  rtems_monitor_object_info )];
           p++ )
           {
           if (  p->type == type )
           return p;
           }
           return 0;
          }
          
          rtems_id
     190  rtems_monitor_object_canonical_next_remote(  
           rtems_monitor_object_type_t type,  
           rtems_id id,  
           void *canonical
           )
          {
           rtems_id next_id;
           rtems_status_code status;
           rtems_monitor_server_request_t request;
           rtems_monitor_server_response_t response;
          
           /*
           * Send request
           */
          
           request.command = RTEMS_MONITOR_SERVER_CANONICAL;
           request.argument0 = (  uint32_t ) type;
           request.argument1 = (  uint32_t ) id;
          
           status = rtems_monitor_server_request(  
           rtems_object_id_get_node(  id ),   &request,   &response );
           if (  status != RTEMS_SUCCESSFUL )
           goto failed;
          
           /*
           * process response
           */
          
           next_id = (  rtems_id ) response.result0;
           if (  next_id != RTEMS_OBJECT_ID_FINAL )
           (  void ) memcpy(  canonical,   &response.payload,   response.result1 );
          
           return next_id;
          
          failed:
           return RTEMS_OBJECT_ID_FINAL;
          
          }
          
          
          rtems_id
     231  rtems_monitor_object_canonical_next(  
           const rtems_monitor_object_info_t *info,  
           rtems_id id,  
           void *canonical
           )
          {
           rtems_id next_id;
           void *raw_item;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   ! _Objects_Is_local_id(  id )  ) {
           next_id = rtems_monitor_object_canonical_next_remote(  
           info->type,  
           id,  
           canonical
            );
           } else
          #endif
           {
           next_id = id;
          
           raw_item = (  void * ) info->next(  
           info->object_information,  
           canonical,  
           &next_id
            );
          
           if (  raw_item ) {
           info->canonical(  canonical,   raw_item );
           _Thread_Enable_dispatch(   );
           }
           }
           return next_id;
          }
          
          
          /*
           * this is routine server invokes locally to get the type
           */
          
          rtems_id
     272  rtems_monitor_object_canonical_get(  
           rtems_monitor_object_type_t type,  
           rtems_id id,  
           void *canonical,  
           size_t *size_p
           )
          {
           const rtems_monitor_object_info_t *info;
           rtems_id next_id;
          
           *size_p = 0;
          
           info = rtems_monitor_object_lookup(  type );
          
           if (  info == 0 )
           return RTEMS_OBJECT_ID_FINAL;
          
           next_id = rtems_monitor_object_canonical_next(  info,   id,   canonical );
           *size_p = info->size;
          
           return next_id;
          }
          
          
          void
     297  rtems_monitor_object_dump_1(  
           const rtems_monitor_object_info_t *info,  
           rtems_id id,  
           bool verbose
           )
          {
           rtems_id next_id;
           rtems_monitor_union_t canonical;
          
           if (  (  next_id = rtems_monitor_object_canonical_next(  
           info,  
           id,  
           &canonical ) ) != RTEMS_OBJECT_ID_FINAL )
           {
           /*
           * If the one we actually got is the one we wanted,   then
           * print it out.
           * For ones that have an id field,   this works fine,  
           * for all others,   always dump it out.
           *
           * HACK: the way we determine whether there is an id is a hack.
           *
           * by the way: the reason we try to not have an id,   is that some
           * of the canonical structures are almost too big for shared
           * memory driver (  eg: mpci )
           */
          
           if (  (  info->next != rtems_monitor_manager_next ) ||
           (  id == canonical.generic.id ) )
           info->dump(  &canonical,   verbose );
           }
          }
          
          void
     331  rtems_monitor_object_dump_all(  
           const rtems_monitor_object_info_t *info,  
           bool verbose
           )
          {
           rtems_id next_id;
           rtems_monitor_union_t canonical;
          
           next_id = RTEMS_OBJECT_ID_INITIAL(  OBJECTS_CLASSIC_API,   info->type,   rtems_monitor_default_node );
          
           while (  (  next_id = rtems_monitor_object_canonical_next(  
           info,  
           next_id,  
           &canonical ) ) != RTEMS_OBJECT_ID_FINAL )
           {
           info->dump(  &canonical,   verbose );
           }
          }
          
          void
     351  rtems_monitor_object_cmd(  
           int argc,  
           char **argv,  
           const rtems_monitor_command_arg_t *command_arg,  
           bool verbose
           )
          {
           int arg;
           const rtems_monitor_object_info_t *info = 0;
           rtems_monitor_object_type_t type;
          
           /* what is the default type? */
           type = command_arg->monitor_object;
          
           if (  argc == 1 )
           {
           if (  type == RTEMS_MONITOR_OBJECT_INVALID )
           {
           fprintf(  stdout,  "A type must be specified to \"dump all\"\n" );
           goto done;
           }
          
           info = rtems_monitor_object_lookup(  type );
           if (  info == 0 )
           goto not_found;
          
           if (  info->dump_header )
           info->dump_header(  verbose );
           rtems_monitor_object_dump_all(  info,   verbose );
           }
           else
           {
           uint32_t default_node = rtems_monitor_default_node;
           rtems_monitor_object_type_t last_type = RTEMS_MONITOR_OBJECT_INVALID;
           rtems_id id;
          
           for (  arg=1; argv[arg]; arg++ )
           {
           id = (  rtems_id ) strtoul(  argv[arg],   0,   16 );
           id = rtems_monitor_id_fixup(  id,   default_node,   type );
           type = (  rtems_monitor_object_type_t ) rtems_object_id_get_class(  id );
          
           /*
           * Allow the item type to change in the middle
           * of the command. If the type changes,   then
           * just dump out a new header and keep on going.
           */
           if (  type != last_type )
           {
           info = rtems_monitor_object_lookup(  type );
           if (  info == 0 )
           goto not_found;
          
           if (  info->dump_header )
           info->dump_header(  verbose );
           }
          
           if (  info == 0 )
           {
          not_found: fprintf(  stdout,  "Invalid or unsupported type %d\n",   type );
           goto done;
           }
          
           rtems_monitor_object_dump_1(  info,   id,   verbose );
          
           default_node = rtems_object_id_get_node(  id );
          
           last_type = type;
           }
           }
          done:
           return;
          }

libmisc/monitor/mon-part.c

       1  /*
           * RTEMS Monitor partition support
           *
           * $Id: mon-part.c,  v 1.7 2010/04/12 15:25:43 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include "monitor.h"
          #include <rtems/rtems/attr.inl>
          #include <stdio.h>
          #include <string.h> /* memcpy(   ) */
          
          void
      18  rtems_monitor_part_canonical(  
           rtems_monitor_part_t *canonical_part,  
           void *part_void
           )
          {
           Partition_Control *rtems_part = (  Partition_Control * ) part_void;
          
           canonical_part->attribute = rtems_part->attribute_set;
           canonical_part->start_addr = rtems_part->starting_address;
           canonical_part->length = rtems_part->length;
           canonical_part->buf_size = rtems_part->buffer_size;
           canonical_part->used_blocks = rtems_part->number_of_used_blocks;
          }
          
          
          void
      34  rtems_monitor_part_dump_header(  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           printf(  "\
           ID NAME ATTR STARTADDR LENGTH BUF_SIZE USED_BLOCKS\n" );
          /*23456789 123456789 123456789 123456789 123456789 123456789 123456789 1234
           1 2 3 4 5 6 7 */
          
           rtems_monitor_separator(   );
          }
          
          /*
           */
          
          void
      50  rtems_monitor_part_dump(  
           rtems_monitor_part_t *monitor_part,  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           int length = 0;
          
           length += rtems_monitor_dump_id(  monitor_part->id );
           length += rtems_monitor_pad(  11,   length );
           length += rtems_monitor_dump_name(  monitor_part->id );
           length += rtems_monitor_pad(  18,   length );
           length += rtems_monitor_dump_attributes(  monitor_part->attribute );
           length += rtems_monitor_pad(  30,   length );
           length += rtems_monitor_dump_addr(  monitor_part->start_addr );
           length += rtems_monitor_pad(  40,   length );
           length += rtems_monitor_dump_hex(  monitor_part->length );
           length += rtems_monitor_pad(  50,   length );
           length += rtems_monitor_dump_hex(  monitor_part->buf_size );
           length += rtems_monitor_pad(  60,   length );
           length += rtems_monitor_dump_hex(  monitor_part->used_blocks );
           printf(  "\n" );
          }
          

libmisc/monitor/mon-prmisc.c

       1  /*
           * Print misc stuff for the monitor dump routines
           * Each routine returns the number of characters it output.
           *
           * TODO:
           *
           * $Id: mon-prmisc.c,  v 1.25 2010/04/12 15:23:41 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/monitor.h>
          
          #include <rtems/assoc.h>
          
          #include <stdio.h>
          #include <ctype.h>
          #include <inttypes.h>
          
          void
      24  rtems_monitor_separator(  void )
          {
           fprintf(  stdout,  "------------------------------------------------------------------------------\n" );
          }
          
          uint32_t
      30  rtems_monitor_pad(  
           uint32_t destination_column,  
           uint32_t current_column
           )
          {
           int pad_length;
          
           if (  destination_column <= current_column )
           pad_length = 1;
           else
           pad_length = destination_column - current_column;
          
           return fprintf(  stdout,  "%*s",   pad_length,   "" );
          }
          
          int
      46  rtems_monitor_dump_decimal(  uint32_t num )
          {
           return fprintf(  stdout,  "%4" PRId32,   num );
          }
          
          int
      52  rtems_monitor_dump_addr(  void *addr )
          {
           return fprintf(  stdout,  "0x%p",   addr );
          }
          
          int
      58  rtems_monitor_dump_hex(  uint32_t num )
          {
           return fprintf(  stdout,  "0x%" PRIx32,   num );
          }
          
          int
      64  rtems_monitor_dump_assoc_bitfield(  
           const rtems_assoc_t *ap,  
           const char *separator,  
           uint32_t value
            )
          {
           uint32_t b;
           uint32_t length = 0;
           const char *name;
          
           for (  b = 1; b; b <<= 1 )
           if (  b & value )
           {
           if (  length )
           length += fprintf(  stdout,  "%s",   separator );
          
           name = rtems_assoc_name_by_local(  ap,   b );
          
           if (  name )
           length += fprintf(  stdout,  "%s",   name );
           else
           length += fprintf(  stdout,  "0x%" PRIx32,   b );
           }
          
           return length;
          }
          
          int
      92  rtems_monitor_dump_id(  rtems_id id )
          {
          #if defined(  RTEMS_USE_16_BIT_OBJECT )
           return fprintf(  stdout,  "%08" PRIx16,   id );
          #else
           return fprintf(  stdout,  "%08" PRIx32,   id );
          #endif
          }
          
          int
     102  rtems_monitor_dump_name(  rtems_id id )
          {
           char name_buffer[18];
          
           rtems_object_get_name(   id,   sizeof(  name_buffer ),   name_buffer  );
          
           return fprintf(   stdout,   name_buffer  );
          }
          
          int
     112  rtems_monitor_dump_priority(  rtems_task_priority priority )
          {
           return fprintf(  stdout,  "%3" PRId32,   priority );
          }
          
          
          static const rtems_assoc_t rtems_monitor_state_assoc[] = {
           { "DORM",   STATES_DORMANT,   0 },  
           { "SUSP",   STATES_SUSPENDED,   0 },  
           { "TRANS",   STATES_TRANSIENT,   0 },  
           { "DELAY",   STATES_DELAYING,   0 },  
           { "Wtime",   STATES_WAITING_FOR_TIME,   0 },  
           { "Wbuf",   STATES_WAITING_FOR_BUFFER,   0 },  
           { "Wseg",   STATES_WAITING_FOR_SEGMENT,   0 },  
           { "Wmsg" ,   STATES_WAITING_FOR_MESSAGE,   0 },  
           { "Wevnt",   STATES_WAITING_FOR_EVENT,   0 },  
           { "Wsem",   STATES_WAITING_FOR_SEMAPHORE,   0 },  
           { "Wmutex",   STATES_WAITING_FOR_MUTEX,   0 },  
           { "Wcvar",   STATES_WAITING_FOR_CONDITION_VARIABLE,   0 },  
           { "Wjatx",   STATES_WAITING_FOR_JOIN_AT_EXIT,   0 },  
           { "Wrpc",   STATES_WAITING_FOR_RPC_REPLY,   0 },  
           { "WRATE",   STATES_WAITING_FOR_PERIOD,   0 },  
           { "Wsig",   STATES_WAITING_FOR_SIGNAL,   0 },  
           { "Wbar",   STATES_WAITING_FOR_BARRIER,   0 },  
           { "Wrwlk",   STATES_WAITING_FOR_RWLOCK,   0 },  
           { "Wisig",   STATES_INTERRUPTIBLE_BY_SIGNAL,   0 },  
           { 0,   0,   0 },  
          };
          
          int
     142  rtems_monitor_dump_state(  States_Control state )
          {
           int length = 0;
          
           if (  state == STATES_READY ) /* assoc doesn't deal with this as it is 0 */
           length += fprintf(  stdout,  "READY" );
          
           length += rtems_monitor_dump_assoc_bitfield(  rtems_monitor_state_assoc,  
           ":",  
           state );
           return length;
          }
          
          static const rtems_assoc_t rtems_monitor_attribute_assoc[] = {
           { "GL",   RTEMS_GLOBAL,   0 },  
           { "PR",   RTEMS_PRIORITY,   0 },  
           { "FL",   RTEMS_FLOATING_POINT,   0 },  
           { "BI",   RTEMS_BINARY_SEMAPHORE,   0 },  
           { "SB",   RTEMS_SIMPLE_BINARY_SEMAPHORE,   0 },  
           { "IN",   RTEMS_INHERIT_PRIORITY,   0 },  
           { "CE",   RTEMS_PRIORITY_CEILING,   0 },  
           { "AR",   RTEMS_BARRIER_AUTOMATIC_RELEASE,   0 },  
           { "ST",   RTEMS_SYSTEM_TASK,   0 },  
           { 0,   0,   0 },  
          };
          
          int
     169  rtems_monitor_dump_attributes(  rtems_attribute attributes )
          {
           int length = 0;
          
           if (  attributes == RTEMS_DEFAULT_ATTRIBUTES ) /* value is 0 */
           length += fprintf(  stdout,  "DEFAULT" );
          
           length += rtems_monitor_dump_assoc_bitfield(  rtems_monitor_attribute_assoc,  
           ":",  
           attributes );
           return length;
          }
          
          static const rtems_assoc_t rtems_monitor_modes_assoc[] = {
           { "nP",   RTEMS_NO_PREEMPT,   0 },  
           { "T",   RTEMS_TIMESLICE,   0 },  
           { "nA",   RTEMS_NO_ASR,   0 },  
           { 0,   0,   0 },  
          };
          
          int
     190  rtems_monitor_dump_modes(  rtems_mode modes )
          {
           uint32_t length = 0;
          
           if (  modes == RTEMS_DEFAULT_MODES ) /* value is 0 */
           length += fprintf(  stdout,  "P:T:nA" );
          
           length += rtems_monitor_dump_assoc_bitfield(  rtems_monitor_modes_assoc,  
           ":",  
           modes );
           return length;
          }
          
          static const rtems_assoc_t rtems_monitor_events_assoc[] = {
           { "0",   RTEMS_EVENT_0,   0 },  
           { "1",   RTEMS_EVENT_1,   0 },  
           { "2",   RTEMS_EVENT_2,   0 },  
           { "3",   RTEMS_EVENT_3,   0 },  
           { "4",   RTEMS_EVENT_4,   0 },  
           { "5",   RTEMS_EVENT_5,   0 },  
           { "6",   RTEMS_EVENT_6,   0 },  
           { "7",   RTEMS_EVENT_7,   0 },  
           { "8",   RTEMS_EVENT_8,   0 },  
           { "9",   RTEMS_EVENT_9,   0 },  
           { "10",   RTEMS_EVENT_10,   0 },  
           { "11",   RTEMS_EVENT_11,   0 },  
           { "12",   RTEMS_EVENT_12,   0 },  
           { "13",   RTEMS_EVENT_13,   0 },  
           { "14",   RTEMS_EVENT_14,   0 },  
           { "15",   RTEMS_EVENT_15,   0 },  
           { "16",   RTEMS_EVENT_16,   0 },  
           { "17",   RTEMS_EVENT_17,   0 },  
           { "18",   RTEMS_EVENT_18,   0 },  
           { "19",   RTEMS_EVENT_19,   0 },  
           { "20",   RTEMS_EVENT_20,   0 },  
           { "21",   RTEMS_EVENT_21,   0 },  
           { "22",   RTEMS_EVENT_22,   0 },  
           { "23",   RTEMS_EVENT_23,   0 },  
           { "24",   RTEMS_EVENT_24,   0 },  
           { "25",   RTEMS_EVENT_25,   0 },  
           { "26",   RTEMS_EVENT_26,   0 },  
           { "27",   RTEMS_EVENT_27,   0 },  
           { "28",   RTEMS_EVENT_28,   0 },  
           { "29",   RTEMS_EVENT_29,   0 },  
           { "30",   RTEMS_EVENT_30,   0 },  
           { "31",   RTEMS_EVENT_31,   0 },  
           { 0,   0,   0 },  
          };
          
          int
     240  rtems_monitor_dump_events(  rtems_event_set events )
          {
           if (  events == EVENT_SETS_NONE_PENDING ) /* value is 0 */
           return fprintf(  stdout,  " NONE " );
          
           return fprintf(  stdout,  "%08" PRIx32,   events );
          }
          
          int
     249  rtems_monitor_dump_notepad(  uint32_t *notepad )
          {
           int length = 0;
           int i;
          
           for (  i=0; i < RTEMS_NUMBER_NOTEPADS; i++ )
           if (  notepad[i] )
           length += fprintf(  stdout,  "%d: 0x%" PRIx32,   i,   notepad[i] );
          
           return length;
          }

libmisc/monitor/mon-queue.c

       1  /*
           * $Id: mon-queue.c,  v 1.11 2009/01/02 13:01:21 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/monitor.h>
          
          #include <stdio.h>
          
          void
      15  rtems_monitor_queue_canonical(  
           rtems_monitor_queue_t *canonical_queue,  
           void *queue_void
           )
          {
           Message_queue_Control *rtems_queue = (  Message_queue_Control * ) queue_void;
          
           canonical_queue->attributes = rtems_queue->attribute_set;
           canonical_queue->maximum_message_size = rtems_queue->message_queue.maximum_message_size;
           canonical_queue->maximum_pending_messages = rtems_queue->message_queue.maximum_pending_messages;
           canonical_queue->number_of_pending_messages = rtems_queue->message_queue.number_of_pending_messages;
          }
          
          void
      29  rtems_monitor_queue_dump_header(  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           fprintf(  stdout,  "\
           ID NAME ATTRIBUTES PEND MAXPEND MAXSIZE\n" );
          /*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
          0 1 2 3 4 5 6 7 */
           rtems_monitor_separator(   );
          }
          
          
          /*
           * Dump out the "next" queue indicated by 'id'.
           * Returns next one to check.
           * Returns RTEMS_OBJECT_ID_FINAL when all done
           */
          
          void
      48  rtems_monitor_queue_dump(  
           rtems_monitor_queue_t *monitor_queue,  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           uint32_t length = 0;
          
           length += rtems_monitor_dump_id(  monitor_queue->id );
           length += rtems_monitor_pad(  11,   length );
           length += rtems_monitor_dump_name(  monitor_queue->id );
           length += rtems_monitor_pad(  19,   length );
           length += rtems_monitor_dump_attributes(  monitor_queue->attributes );
           length += rtems_monitor_pad(  31,   length );
           length += rtems_monitor_dump_decimal(  monitor_queue->number_of_pending_messages );
           length += rtems_monitor_pad(  39,   length );
           length += rtems_monitor_dump_decimal(  monitor_queue->maximum_pending_messages );
           length += rtems_monitor_pad(  48,   length );
           length += rtems_monitor_dump_decimal(  monitor_queue->maximum_message_size );
          
           fprintf(  stdout,  "\n" );
          }

libmisc/monitor/mon-region.c

       1  /*
           * RTEMS Monitor region support
           *
           * $Id: mon-region.c,  v 1.7 2010/04/12 15:25:43 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include "monitor.h"
          #include <rtems/rtems/attr.inl>
          #include <stdio.h>
          #include <string.h> /* memcpy(   ) */
          
          void
      18  rtems_monitor_region_canonical(  
           rtems_monitor_region_t *canonical_region,  
           void *region_void
           )
          {
           Region_Control *rtems_region = (  Region_Control * ) region_void;
          
           canonical_region->attribute = rtems_region->attribute_set;
           canonical_region->start_addr = rtems_region->starting_address;
           canonical_region->length = rtems_region->length;
           canonical_region->page_size = rtems_region->page_size;
           canonical_region->max_seg_size = rtems_region->maximum_segment_size;
           canonical_region->used_blocks = rtems_region->number_of_used_blocks;
          }
          
          
          void
      35  rtems_monitor_region_dump_header(  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           printf(  "\
           ID NAME ATTR STARTADDR LENGTH PAGE_SIZE USED_BLOCKS\n" );
          /*23456789 123456789 123456789 123456789 123456789 123456789 123456789 1234
           1 2 3 4 5 6 7 */
          
           rtems_monitor_separator(   );
          }
          
          /*
           */
          
          void
      51  rtems_monitor_region_dump(  
           rtems_monitor_region_t *monitor_region,  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           int length = 0;
          
           length += rtems_monitor_dump_id(  monitor_region->id );
           length += rtems_monitor_pad(  11,   length );
           length += rtems_monitor_dump_name(  monitor_region->id );
           length += rtems_monitor_pad(  18,   length );
           length += rtems_monitor_dump_attributes(  monitor_region->attribute );
           length += rtems_monitor_pad(  30,   length );
           length += rtems_monitor_dump_addr(  monitor_region->start_addr );
           length += rtems_monitor_pad(  40,   length );
           length += rtems_monitor_dump_hex(  monitor_region->length );
           length += rtems_monitor_pad(  50,   length );
           length += rtems_monitor_dump_hex(  monitor_region->page_size );
           length += rtems_monitor_pad(  60,   length );
           length += rtems_monitor_dump_hex(  monitor_region->used_blocks );
           printf(  "\n" );
          }
          

libmisc/monitor/mon-sema.c

       1  /*
           * RTEMS Monitor semaphore support
           *
           * $Id: mon-sema.c,  v 1.6 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include "monitor.h"
          #include <rtems/rtems/attr.inl>
          #include <stdio.h>
          #include <string.h> /* memcpy(   ) */
          
          void
      18  rtems_monitor_sema_canonical(  
           rtems_monitor_sema_t *canonical_sema,  
           void *sema_void
           )
          {
           Semaphore_Control *rtems_sema = (  Semaphore_Control * ) sema_void;
          
           canonical_sema->attribute = rtems_sema->attribute_set;
           canonical_sema->priority_ceiling =
           rtems_sema->Core_control.mutex.Attributes.priority_ceiling;
          
           canonical_sema->holder_id =
           rtems_sema->Core_control.mutex.holder_id;
          
           if (  _Attributes_Is_counting_semaphore(  canonical_sema->attribute ) ) {
           /* we have a counting semaphore */
           canonical_sema->cur_count =
           rtems_sema->Core_control.semaphore.count;
          
           canonical_sema->max_count =
           rtems_sema->Core_control.semaphore.Attributes.maximum_count;
           }
           else {
           /* we have a binary semaphore (  mutex ) */
           canonical_sema->cur_count = rtems_sema->Core_control.mutex.lock;
           canonical_sema->max_count = 1; /* mutex is either 0 or 1 */
           }
          }
          
          
          void
      49  rtems_monitor_sema_dump_header(  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           printf(  "\
           ID NAME ATTR PRICEIL CURR_CNT HOLDID \n" );
          /*23456789 123456789 123456789 123456789 123456789 123456789 123456789 1234
           1 2 3 4 5 6 7 */
          
           rtems_monitor_separator(   );
          }
          
          /*
           */
          
          void
      65  rtems_monitor_sema_dump(  
           rtems_monitor_sema_t *monitor_sema,  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           int length = 0;
          
           length += rtems_monitor_dump_id(  monitor_sema->id );
           length += rtems_monitor_pad(  11,   length );
           length += rtems_monitor_dump_name(  monitor_sema->id );
           length += rtems_monitor_pad(  18,   length );
           length += rtems_monitor_dump_attributes(  monitor_sema->attribute );
           length += rtems_monitor_pad(  30,   length );
           length += rtems_monitor_dump_priority(  monitor_sema->priority_ceiling );
           length += rtems_monitor_pad(  38,   length );
           length += rtems_monitor_dump_decimal(  monitor_sema->cur_count );
           length += rtems_monitor_pad(  47,   length );
           length += rtems_monitor_dump_id(  monitor_sema->holder_id );
           printf(  "\n" );
          }

libmisc/monitor/mon-server.c

       1  /*
           * RTEMS monitor server (  handles requests for info from RTEMS monitors
           * running on other nodes )
           *
           * $Id: mon-server.c,  v 1.14 2009/01/02 13:01:21 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          
          #include <stdio.h>
          #include <string.h>
          #include <stdlib.h>
          #include <unistd.h>
          
          #include <rtems/monitor.h>
          
          /*
           * Various id's for the server
           */
          
          rtems_id rtems_monitor_server_task_id;
          rtems_id rtems_monitor_server_request_queue_id; /* our server */
          rtems_id *rtems_monitor_server_request_queue_ids; /* all servers */
          rtems_id rtems_monitor_server_response_queue_id; /* our server */
          
          
          /*
           * Send a request to a server task
           */
          
          rtems_status_code
      36  rtems_monitor_server_request(  
           uint32_t server_node,  
           rtems_monitor_server_request_t *request,  
           rtems_monitor_server_response_t *response
           )
          {
           rtems_id server_id;
           rtems_status_code status;
           size_t size;
          
           /*
           * What is id of monitor on target node?
           * Look it up if we don't know it yet.
           */
          
           server_id = rtems_monitor_server_request_queue_ids[server_node];
           if (  server_id == 0 )
           {
           status = rtems_message_queue_ident(  RTEMS_MONITOR_QUEUE_NAME,  
           server_node,  
           &server_id );
           if (  status != RTEMS_SUCCESSFUL )
           {
           rtems_error(  status,   "ident of remote server failed" );
           goto done;
           }
          
           rtems_monitor_server_request_queue_ids[server_node] = server_id;
           }
          
           request->return_id = rtems_monitor_server_response_queue_id;
          
           status = rtems_message_queue_send(  server_id,   request,   sizeof(  *request ) );
           if (  status != RTEMS_SUCCESSFUL )
           {
           rtems_error(  status,   "monitor server request send failed" );
           goto done;
           }
          
           /*
           * Await response,   if requested
           */
          
           if (  response )
           {
           status = rtems_message_queue_receive(  rtems_monitor_server_response_queue_id,  
           response,  
           &size,  
           RTEMS_WAIT,  
           100 );
           if (  status != RTEMS_SUCCESSFUL )
           {
           rtems_error(  status,   "server did not respond" );
          
           /* maybe server task was restarted; look it up again next time */
           rtems_monitor_server_request_queue_ids[server_node] = 0;
          
           goto done;
           }
          
           if (  response->command != RTEMS_MONITOR_SERVER_RESPONSE )
           {
           status = RTEMS_INCORRECT_STATE;
           goto done;
           }
           }
          
          done:
           return status;
          }
          
          
          
          /*
           * monitor server task
           */
          
          void
     114  rtems_monitor_server_task(  
           rtems_task_argument monitor_flags __attribute__(  (  unused ) )
           )
          {
           rtems_monitor_server_request_t request;
           rtems_monitor_server_response_t response;
           rtems_status_code status;
           size_t size;
          
           for (  ;; )
           {
           status = rtems_message_queue_receive(  
           rtems_monitor_server_request_queue_id,  
           &request,  
           &size,  
           RTEMS_WAIT,  
           (  rtems_interval ) 0 );
          
           if (  status != RTEMS_SUCCESSFUL )
           {
           rtems_error(  status,   "monitor server msg queue receive error" );
           goto failed;
           }
          
           if (  size != sizeof(  request ) )
           {
           rtems_error(  0,   "monitor server bad size on receive" );
           goto failed;
           }
          
           switch (  request.command )
           {
           case RTEMS_MONITOR_SERVER_CANONICAL:
           {
           rtems_monitor_object_type_t object_type;
           rtems_id id;
           rtems_id next_id;
          
           object_type = (  rtems_monitor_object_type_t ) request.argument0;
           id = (  rtems_id ) request.argument1;
           next_id = rtems_monitor_object_canonical_get(  object_type,  
           id,  
           &response.payload,  
           &size );
          
           response.command = RTEMS_MONITOR_SERVER_RESPONSE;
           response.result0 = next_id;
           response.result1 = size;
          
          #define SERVER_OVERHEAD (  RTEMS_offsetof(  rtems_monitor_server_response_t,   \
           payload ) )
          
           status = rtems_message_queue_send(  request.return_id,  
           &response,  
           size + SERVER_OVERHEAD );
           if (  status != RTEMS_SUCCESSFUL )
           {
           rtems_error(  status,   "response send failed" );
           goto failed;
           }
           break;
           }
          
           default:
           {
           rtems_error(  0,   "invalid command to monitor server: %d",   request.command );
           goto failed;
           }
           }
           }
          
          failed:
           rtems_task_delete(  RTEMS_SELF );
          }
          
          
          /*
           * Kill off any old server
           * Not sure if this is useful,   but it doesn't help
           */
          
     195  void
          rtems_monitor_server_kill(  void )
          {
           if (  rtems_monitor_server_task_id )
           rtems_task_delete(  rtems_monitor_server_task_id );
           rtems_monitor_server_task_id = 0;
          
           if (  rtems_monitor_server_request_queue_id )
           rtems_message_queue_delete(  rtems_monitor_server_request_queue_id );
           rtems_monitor_server_request_queue_ids = 0;
          
           if (  rtems_monitor_server_response_queue_id )
           rtems_message_queue_delete(  rtems_monitor_server_response_queue_id );
           rtems_monitor_server_response_queue_id = 0;
          
           if (  rtems_monitor_server_request_queue_ids )
           free(  rtems_monitor_server_request_queue_ids );
           rtems_monitor_server_request_queue_ids = 0;
          }
          
          
     216  void
          rtems_monitor_server_init(  
           uint32_t monitor_flags __attribute__(  (  unused ) )
           )
          {
           #if defined(  RTEMS_MULTIPROCESSING )
           rtems_status_code status;
          
           if (  _System_state_Is_multiprocessing &&
           (  _Configuration_MP_table->maximum_nodes > 1 ) )
           {
           uint32_t maximum_nodes = _Configuration_MP_table->maximum_nodes;
          
           /*
           * create the msg que our server will listen
           * Since we only get msgs from other RTEMS monitors,   we just
           * need reserve space for 1 msg from each node.
           */
          
           status = rtems_message_queue_create(  
           RTEMS_MONITOR_QUEUE_NAME,  
           maximum_nodes,  
           sizeof(  rtems_monitor_server_request_t ),  
           RTEMS_GLOBAL,  
           &rtems_monitor_server_request_queue_id );
          
           if (  status != RTEMS_SUCCESSFUL )
           {
           rtems_error(  status,   "could not create monitor server message queue" );
           goto done;
           }
          
           /*
           * create the msg que our responses will come on
           * Since monitor just does one thing at a time,   we only need 1 item
           * message queue.
           */
          
           status = rtems_message_queue_create(  
           RTEMS_MONITOR_RESPONSE_QUEUE_NAME,  
           1,   /* depth */
           sizeof(  rtems_monitor_server_response_t ),  
           RTEMS_GLOBAL,  
           &rtems_monitor_server_response_queue_id );
          
           if (  status != RTEMS_SUCCESSFUL )
           {
           rtems_error(  status,   "could not create monitor response message queue" );
           goto done;
           }
          
           /* need an id for queue of each other server we might talk to */
           /* indexed by node,   so add 1 to maximum_nodes */
           rtems_monitor_server_request_queue_ids =
           (  rtems_id * ) malloc(  (  maximum_nodes + 1 ) * sizeof(  rtems_id ) );
           (  void ) memset(  rtems_monitor_server_request_queue_ids,  
           0,  
           (  maximum_nodes + 1 ) * sizeof(  rtems_id ) );
          
           rtems_monitor_server_request_queue_ids[rtems_monitor_node] =
           rtems_monitor_server_request_queue_id;
          
           /*
           * create the server task
           */
           status = rtems_task_create(  RTEMS_MONITOR_SERVER_NAME,  
           1,  
           0 /* default stack */,  
           RTEMS_INTERRUPT_LEVEL(  0 ),  
           RTEMS_DEFAULT_ATTRIBUTES,  
           &rtems_monitor_server_task_id );
           if (  status != RTEMS_SUCCESSFUL )
           {
           rtems_error(  status,   "could not create monitor server task" );
           goto done;
           }
          
           /*
           * Start the server task
           */
           status = rtems_task_start(  rtems_monitor_server_task_id,  
           rtems_monitor_server_task,  
           monitor_flags );
           if (  status != RTEMS_SUCCESSFUL )
           {
           rtems_error(  status,   "could not start monitor server" );
           goto done;
           }
           }
          
          done:
           #endif
           return;
          }

libmisc/monitor/mon-symbols.c

       1  /*
           * File: symbols.c
           *
           * Description:
           * Symbol table manager for the RTEMS monitor.
           * These routines may be used by other system resources also.
           *
           *
           * TODO:
           *
           * $Id: mon-symbols.c,  v 1.34 2010/08/26 21:41:41 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          #ifdef HAVE_STRINGS_H
          #include <strings.h>
          #endif
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #include <rtems.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <inttypes.h>
          
          #include <rtems/monitor.h>
          #include "symbols.h"
          
          
          rtems_symbol_table_t *
      34  rtems_symbol_table_create(  void )
          {
           rtems_symbol_table_t *table;
          
           table = (  rtems_symbol_table_t * ) malloc(  sizeof(  rtems_symbol_table_t ) );
           memset(  (  void * ) table,   0,   sizeof(  *table ) );
          
           table->growth_factor = 30; /* 30 percent */
          
           return table;
          }
          
          void
      47  rtems_symbol_table_destroy(  rtems_symbol_table_t *table )
          {
           rtems_symbol_string_block_t *p,   *pnext;
          
           if (  table )
           {
           if (  table->addresses )
           (  void ) free(  table->addresses );
           table->addresses = 0;
           p = table->string_buffer_head;
           while (  p )
           {
           pnext = p->next;
           free(  p );
           p = pnext;
           }
           table->string_buffer_head = 0;
           table->string_buffer_current = 0;
          
           free(  table );
           }
          }
          
          rtems_symbol_t *
      71  rtems_symbol_create(  
           rtems_symbol_table_t *table,  
           const char *name,  
           uint32_t value
            )
          {
           size_t symbol_length;
           size_t newsize;
           rtems_symbol_t *sp;
          
           symbol_length = strlen(  name ) + 1; /* include '\000' in length */
          
           /* need to grow the table? */
           if (  table->next >= table->size )
           {
           if (  table->size == 0 )
           newsize = 100;
           else
           newsize = table->size + (  table->size / (  100 / table->growth_factor ) );
          
           table->addresses = (  rtems_symbol_t * ) realloc(  (  void * ) table->addresses,   newsize * sizeof(  rtems_symbol_t ) );
           if (  table->addresses == 0 ) /* blew it; lost orig */
           goto failed;
           table->size = newsize;
           }
          
           sp = &table->addresses[table->next];
           sp->value = value;
          
           /* Have to add it to string pool */
           /* need to grow pool? */
          
           if (  (  table->string_buffer_head == 0 ) ||
           (  table->strings_next + symbol_length ) >= SYMBOL_STRING_BLOCK_SIZE )
           {
           rtems_symbol_string_block_t *p;
          
           p = (  rtems_symbol_string_block_t * ) malloc(  sizeof(  rtems_symbol_string_block_t ) );
           if (  p == 0 )
           goto failed;
           p->next = 0;
           if (  table->string_buffer_head == 0 )
           table->string_buffer_head = p;
           else
           table->string_buffer_current->next = p;
           table->string_buffer_current = p;
          
           table->strings_next = 0;
           }
          
           sp->name = table->string_buffer_current->buffer + table->strings_next;
           (  void ) strcpy(  sp->name,   name );
          
           table->strings_next += symbol_length;
           table->sorted = 0;
           table->next++;
          
           return sp;
          
          /* XXX Not sure what to do here. We've possibly destroyed the initial
           symbol table due to realloc failure */
          failed:
           return 0;
          }
          
          /*
           * Qsort entry point for compare by address
           */
          
          static int
     141  rtems_symbol_compare(  const void *e1,  
           const void *e2 )
          {
           rtems_symbol_t *s1,   *s2;
           s1 = (  rtems_symbol_t * ) e1;
           s2 = (  rtems_symbol_t * ) e2;
          
           if (  s1->value < s2->value )
           return -1;
           if (  s1->value > s2->value )
           return 1;
           return 0;
          }
          
          
          /*
           * Sort the symbol table using qsort
           */
          
          static void
     161  rtems_symbol_sort(  rtems_symbol_table_t *table )
          {
           qsort(  (  void * ) table->addresses,   (  size_t ) table->next,  
           sizeof(  rtems_symbol_t ),   rtems_symbol_compare );
           table->sorted = 1;
          }
          
          
          /*
           * Search the symbol table by address
           * This code based on CYGNUS newlib bsearch,   but changed
           * to allow for finding closest symbol <= key
           */
          
          rtems_symbol_t *
     176  rtems_symbol_value_lookup(  
           rtems_symbol_table_t *table,  
           uint32_t value
            )
          {
           rtems_symbol_t *sp;
           rtems_symbol_t *base;
           rtems_symbol_t *best = 0;
           uint32_t distance;
           uint32_t best_distance = ~0;
           uint32_t elements;
          
           if (  table == 0 )
           table = rtems_monitor_symbols;
          
           if (  (  table == 0 ) || (  table->size == 0 ) )
           return 0;
          
           if (  table->sorted == 0 )
           rtems_symbol_sort(  table );
          
           base = table->addresses;
           elements = table->next;
          
           while (  elements )
           {
           sp = base + (  elements / 2 );
           if (  value < sp->value )
           elements /= 2;
           else if (  value > sp->value )
           {
           distance = value - sp->value;
           if (  distance < best_distance )
           {
           best_distance = distance;
           best = sp;
           }
           base = sp + 1;
           elements = (  elements / 2 ) - (  elements % 2 ? 0 : 1 );
           }
           else
           return sp;
           }
          
           if (  value == base->value )
           return base;
          
           return best;
          }
          
          /*
           * Search the symbol table for the exact matching address.
           * If the symbol table has already been sorted,   then
           * call the regular symbol value lookup,   however,   it it
           * has not yet been sorted,   search it sequentially.
           * This routine is primarily used for low level symbol
           * lookups (  eg. from exception handler and interrupt routines )
           * where the penality of sorted is not wanted and where
           * an exact match is needed such that symbol table order
           * is not important.
           */
          const rtems_symbol_t *
     238  rtems_symbol_value_lookup_exact(  
           rtems_symbol_table_t *table,  
           uint32_t value
            )
          {
           uint32_t s;
           rtems_symbol_t *sp;
          
           if (  table == 0 )
           {
           table = rtems_monitor_symbols;
           if (  table == 0 )
           return NULL;
           }
          
           if (  table->sorted )
           {
           sp = rtems_symbol_value_lookup(  table,   value );
           if (   rtems_symbol_value(  sp ) == value  )
           return sp;
           else
           return NULL; /* not an exact match */
           }
          
           for (  s = 0,   sp = table->addresses; s < table->next; s++,   sp++ )
           {
           if (   sp->value == value  )
           return sp;
           }
          
           return NULL;
          
          }
          
          
          /*
           * Search the symbol table by string name (  case independent )
           */
          
          rtems_symbol_t *
     278  rtems_symbol_name_lookup(  
           rtems_symbol_table_t *table,  
           const char *name
            )
          {
           uint32_t s;
           rtems_symbol_t *sp;
          
           if (  table == 0 )
           {
           table = rtems_monitor_symbols;
           if (  table == 0 )
           return NULL;
           }
          
           for (  s = 0,   sp = table->addresses; s < table->next; s++,   sp++ )
           {
           if (   strcasecmp(  sp->name,   name ) == 0  )
           return sp;
           }
          
           return NULL;
          }
          
          void *
     303  rtems_monitor_symbol_next(  
           void *object_info,  
           rtems_monitor_symbol_t *canonical __attribute__(  (  unused ) ),  
           rtems_id *next_id
           )
          {
           rtems_symbol_table_t *table;
           uint32_t n = rtems_object_id_get_index(  *next_id );
          
           table = *(  rtems_symbol_table_t ** ) object_info;
           if (  table == 0 )
           goto failed;
          
           if (  n >= table->next )
           goto failed;
          
           /* NOTE: symbols do not have id and name fields */
          
           if (  table->sorted == 0 )
           rtems_symbol_sort(  table );
          
           _Thread_Disable_dispatch(   );
          
           *next_id += 1;
           return (  void * ) (  table->addresses + n );
          
          failed:
           *next_id = RTEMS_OBJECT_ID_FINAL;
           return 0;
          }
          
          void
     335  rtems_monitor_symbol_canonical(  
           rtems_monitor_symbol_t *canonical_symbol,  
           rtems_symbol_t *sp
           )
          {
           canonical_symbol->value = sp->value;
           canonical_symbol->offset = 0;
           strncpy(  canonical_symbol->name,   sp->name,   sizeof(  canonical_symbol->name )-1 );
          }
          
          
          void
     347  rtems_monitor_symbol_canonical_by_name(  
           rtems_monitor_symbol_t *canonical_symbol,  
           const char *name
           )
          {
           rtems_symbol_t *sp;
          
           sp = rtems_symbol_name_lookup(  0,   name );
          
           canonical_symbol->value = sp ? sp->value : 0;
          
           strncpy(  canonical_symbol->name,   name,   sizeof(  canonical_symbol->name ) - 1 );
           canonical_symbol->offset = 0;
          }
          
          void
     363  rtems_monitor_symbol_canonical_by_value(  
           rtems_monitor_symbol_t *canonical_symbol,  
           void *value_void_p
           )
          {
           uintptr_t value = (  uintptr_t ) value_void_p;
           rtems_symbol_t *sp;
          
           sp = rtems_symbol_value_lookup(  0,   value );
           if (  sp )
           {
           canonical_symbol->value = sp->value;
           canonical_symbol->offset = value - sp->value;
           strncpy(  canonical_symbol->name,   sp->name,   sizeof(  canonical_symbol->name )-1 );
           }
           else
           {
           canonical_symbol->value = value;
           canonical_symbol->offset = 0;
           canonical_symbol->name[0] = '\0';
           }
          }
          
          
          uint32_t
     388  rtems_monitor_symbol_dump(  
           rtems_monitor_symbol_t *canonical_symbol,  
           bool verbose
           )
          {
           uint32_t length = 0;
          
           /*
           * print the name if it exists AND if value is non-zero
           * Ie: don't print some garbage symbol for address 0
           */
          
           if (  canonical_symbol->name[0] && (  canonical_symbol->value != 0 ) )
           {
           if (  canonical_symbol->offset == 0 )
           length += fprintf(  stdout,  "%.*s",  
           (  int ) sizeof(  canonical_symbol->name ),  
           canonical_symbol->name );
           else
           length += fprintf(  stdout,  "<%.*s+0x%" PRIx32 ">",  
           (  int ) sizeof(  canonical_symbol->name ),  
           canonical_symbol->name,  
           canonical_symbol->offset );
           if (  verbose )
           length += fprintf(  stdout,  
           " [0x%" PRIx32 "]",   canonical_symbol->value );
           }
           else
           length += fprintf(  stdout,  "[0x%" PRIx32 "]",   canonical_symbol->value );
          
           return length;
          }
          
          
          void
     423  rtems_monitor_symbol_dump_all(  
           rtems_symbol_table_t *table,  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           uint32_t s;
           rtems_symbol_t *sp;
          
           if (  table == 0 )
           {
           table = rtems_monitor_symbols;
           if (  table == 0 )
           return;
           }
          
           if (  table->sorted == 0 )
           rtems_symbol_sort(  table );
          
           for (  s = 0,   sp = table->addresses; s < table->next; s++,   sp++ )
           {
           rtems_monitor_symbol_t canonical_symbol;
          
           rtems_monitor_symbol_canonical(  &canonical_symbol,   sp );
           rtems_monitor_symbol_dump(  &canonical_symbol,   true );
           fprintf(  stdout,  "\n" );
           }
          }
          
          
          /*
           * 'symbol' command
           */
          
     456  void rtems_monitor_symbol_cmd(  
           int argc,  
           char **argv,  
           const rtems_monitor_command_arg_t *command_arg,  
           bool verbose
           )
          {
           int arg;
           rtems_symbol_table_t *table;
          
           table = *command_arg->symbol_table;
           if (  table == 0 )
           {
           table = rtems_monitor_symbols;
           if (  table == 0 )
           return;
           }
          
           /*
           * Use object command to dump out whole symbol table
           */
           if (  argc == 1 )
           rtems_monitor_symbol_dump_all(  table,   verbose );
           else
           {
           rtems_monitor_symbol_t canonical_symbol;
          
           for (  arg=1; argv[arg]; arg++ )
           {
           rtems_monitor_symbol_canonical_by_name(  &canonical_symbol,   argv[arg] );
           rtems_monitor_symbol_dump(  &canonical_symbol,   verbose );
           fprintf(  stdout,  "\n" );
           }
           }
          }

libmisc/monitor/mon-task.c

       1  /*
           * RTEMS Monitor task support
           *
           * $Id: mon-task.c,  v 1.17 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/monitor.h>
          
          #include <stdio.h>
          #include <string.h> /* memcpy(   ) */
          
          void
      18  rtems_monitor_task_canonical(  
           rtems_monitor_task_t *canonical_task,  
           void *thread_void
           )
          {
           Thread_Control *rtems_thread = (  Thread_Control * ) thread_void;
           RTEMS_API_Control *api;
          
           api = rtems_thread->API_Extensions[ THREAD_API_RTEMS ];
          
           canonical_task->entry = rtems_thread->Start.entry_point;
           canonical_task->argument = rtems_thread->Start.numeric_argument;
           canonical_task->stack = rtems_thread->Start.Initial_stack.area;
           canonical_task->stack_size = rtems_thread->Start.Initial_stack.size;
           canonical_task->priority = rtems_thread->current_priority;
           canonical_task->state = rtems_thread->current_state;
           canonical_task->wait_id = rtems_thread->Wait.id;
           canonical_task->events = api->pending_events;
           /*
           * FIXME: make this optionally cpu_time_executed
           */
          #if 0
           canonical_task->ticks = rtems_thread->cpu_time_executed;
          #else
           canonical_task->ticks = 0;
          #endif
          
          /* XXX modes and attributes only exist in the RTEMS API .. */
          /* XXX not directly in the core thread.. they will have to be derived */
          /* XXX if they are important enough to include anymore. */
           canonical_task->modes = 0; /* XXX FIX ME.... rtems_thread->current_modes; */
           canonical_task->attributes = 0 /* XXX FIX ME rtems_thread->API_Extensions[ THREAD_API_RTEMS ]->attribute_set */;
           (  void ) memcpy(  canonical_task->notepad,   api ->Notepads,   sizeof(  canonical_task->notepad ) );
          /* XXX more to fix */
          /*
           (  void ) memcpy(  &canonical_task->wait_args,   &rtems_thread->Wait.Extra,   sizeof(  canonical_task->wait_args ) );
          */
          }
          
          
          void
      59  rtems_monitor_task_dump_header(  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           fprintf(  stdout,  "\
           ID NAME PRI STATE MODES EVENTS WAITID WAITARG NOTES\n\
          " );
          /*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
          0 1 2 3 4 5 6 7 */
          
           rtems_monitor_separator(   );
          }
          
          /*
           */
          
          void
      76  rtems_monitor_task_dump(  
           rtems_monitor_task_t *monitor_task,  
           bool verbose __attribute__(  (  unused ) )
           )
          {
           int length = 0;
          
           length += rtems_monitor_dump_id(  monitor_task->id );
           length += rtems_monitor_pad(  11,   length );
           length += rtems_monitor_dump_name(  monitor_task->id );
           length += rtems_monitor_pad(  26,   length );
           length += rtems_monitor_dump_priority(  monitor_task->priority );
           length += rtems_monitor_pad(  29,   length );
           length += rtems_monitor_dump_state(  monitor_task->state );
           length += rtems_monitor_pad(  37,   length );
           length += rtems_monitor_dump_modes(  monitor_task->modes );
           length += rtems_monitor_pad(  45,   length );
           length += rtems_monitor_dump_events(  monitor_task->events );
           if (  monitor_task->wait_id )
           {
           length += rtems_monitor_pad(  54,   length );
           length += rtems_monitor_dump_id(  monitor_task->wait_id );
           length += rtems_monitor_pad(  63,   length );
           length += rtems_monitor_dump_hex(  monitor_task->wait_args );
           }
          
           length += rtems_monitor_pad(  72,   length );
           length += rtems_monitor_dump_notepad(  monitor_task->notepad );
           fprintf(  stdout,  "\n" );
          }

libmisc/serdbg/serdbg.c

       1  /*===============================================================*\
          | Project: RTEMS remote gdb over serial line |
          +-----------------------------------------------------------------+
          | File: serdbg.c |
          +-----------------------------------------------------------------+
          | Copyright (  c ) 2002 IMD |
          | Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
          | <Thomas.Doerfler@imd-systems.de> |
          | all rights reserved |
          +-----------------------------------------------------------------+
          | this file contains intialization and utility functions to add |
          | a gdb remote debug stub to an RTEMS system |
          | |
          +-----------------------------------------------------------------+
          | date history ID |
          | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
          | 04.04.02 creation doe |
          \*===============================================================*/
          /*
           * $Id: serdbg.c,  v 1.7 2008/09/01 11:28:56 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <stdio.h>
          #include <string.h>
          #include <fcntl.h>
          #include <errno.h>
          #include <rtems/serdbg.h>
          
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
      38  int serdbg_init_dbg
          (  
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | initialize remote gdb session over serial line |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
           void
           )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | rtems_status_code |
          \*=========================================================================*/
          {
           static bool is_initialized = false;
          
           rtems_status_code rc = RTEMS_SUCCESSFUL;
          
           if (  is_initialized ) {
           return RTEMS_SUCCESSFUL;
           }
           is_initialized = true;
           /*
           * try to open serial device
           */
           if (  rc == RTEMS_SUCCESSFUL ) {
           if (  (  serdbg_conf.open_io != NULL ) &&
           (  0 > serdbg_conf.open_io(  serdbg_conf.devname,  serdbg_conf.baudrate ) ) ) {
           fprintf(  stderr,  
           "remote_gdb_init: cannot open device %s "
           "for gdb connection:%s\n",  serdbg_conf.devname,  strerror(  errno ) );
           rc = RTEMS_IO_ERROR;
           }
           }
           /*
           * initialize gdb stub
           */
           if (  rc == RTEMS_SUCCESSFUL ) {
           set_debug_traps(   );
           }
           /*
           * now activate gdb stub
           */
           if (  (  rc == RTEMS_SUCCESSFUL ) &&
           !serdbg_conf.skip_init_bkpt ) {
           breakpoint(   );
           }
          
           /*
           * return to original function
           * this may be already unter gdb control
           */
           return rc;
          }

libmisc/serdbg/serdbgio.c

       1  /*===============================================================*\
          | File: serdbgio.c |
          +-----------------------------------------------------------------+
          | Copyright (  c ) 2002 IMD |
          | Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
          | Hebststr. 8,   82178 Puchheim,   Germany |
          | <Thomas.Doerfler@imd-systems.de> |
          | The license and distribution terms for this file may be |
          | found in the file LICENSE in this distribution or at |
          | http://www.rtems.com/license/LICENSE. |
          | all rights reserved |
          +-----------------------------------------------------------------+
          | TERMIOS serial gdb interface support |
          | the functions in this file allow the standard gdb stubs like |
          | "m68k-stub.c" to access any serial interfaces that work with |
          | RTEMS termios in polled mode |
          | |
          +-----------------------------------------------------------------+
          | date history ID |
          | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
          | 10.05.02 creation doe |
          |*****************************************************************|
          |* $Id: serdbgio.c,  v 1.9 2008/09/01 11:28:56 ralf Exp $
           *
          |*****************************************************************|
          \*===============================================================*/
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          #include <errno.h>
          #include <unistd.h> /* close */
          #include <stdio.h>
          #include <fcntl.h>
          #include <termios.h>
          
          #include <rtems/termiostypes.h>
          #include <rtems/serdbg.h>
          
          
          /*
           * internal variables
           */
          int serdbg_fd = -1;
          struct rtems_termios_tty *serdbg_tty;
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
      53  int serdbg_open
          
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | try to open given serial debug port |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
          (  
           const char *dev_name,   /* name of device to open */
           uint32_t baudrate /* baud rate to use */
           )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | 0 on success,   -1 and errno otherwise |
          \*=========================================================================*/
          {
           bool err_occurred = false;
           rtems_libio_t *iop = NULL;
           struct termios act_termios;
           tcflag_t baudcode = B0;
          
          #define FD_STORE_CNT 3
           int fd_store[FD_STORE_CNT];
           int fd_store_used = 0;
          
           /*
           * translate baudrate into baud code
           */
           switch(  baudrate ) {
           case 50: baudcode = B50; break;
           case 75: baudcode = B75; break;
           case 110: baudcode = B110; break;
           case 134: baudcode = B134; break;
           case 150: baudcode = B150; break;
           case 200: baudcode = B200; break;
           case 300: baudcode = B300; break;
           case 600: baudcode = B600; break;
           case 1200: baudcode = B1200; break;
           case 1800: baudcode = B1800; break;
           case 2400: baudcode = B2400; break;
           case 4800: baudcode = B4800; break;
           case 9600: baudcode = B9600; break;
           case 19200: baudcode = B19200; break;
           case 38400: baudcode = B38400; break;
           case 57600: baudcode = B57600; break;
           case 115200: baudcode = B115200; break;
           case 230400: baudcode = B230400; break;
           case 460800: baudcode = B460800; break;
           default : err_occurred = true; errno = EINVAL; break;
           }
          
           /*
           * open device for serdbg operation
           * skip any fds that are between 0..2,   because they are
           * reserved for stdin/out/err
           */
           if (  !err_occurred &&
           (  dev_name != NULL ) &&
           (  dev_name[0] != '\0' ) ) {
           do {
           serdbg_fd = open(  dev_name,  O_RDWR );
           if (  serdbg_fd < 0 ) {
           err_occurred = true;
           }
           else {
           if (  serdbg_fd < 3 ) {
           if (  fd_store_used >= FD_STORE_CNT ) {
           err_occurred = true;
           }
           else {
           fd_store[fd_store_used++] = serdbg_fd;
           }
           }
           }
           } while (  !err_occurred &&
           (  serdbg_fd < 3 ) );
           }
           /*
           * close any fds,   that have been placed in fd_store
           * so fd 0..2 are reusable again
           */
           while (  --fd_store_used >= 0 ) {
           close(  fd_store[fd_store_used] );
           }
          
           /*
           * capture tty structure
           */
           if (  !err_occurred ) {
           iop = &rtems_libio_iops[serdbg_fd];
           serdbg_tty = iop->data1;
           }
           /*
           * set device baudrate
           * (  and transp mode,   this is not really needed )
           * ...
           */
           /*
           * ... get fd settings
           */
           if (  !err_occurred &&
           (  0 != tcgetattr(  serdbg_fd,  &act_termios ) ) ) {
           err_occurred = true;
           }
           if (  !err_occurred ) {
           act_termios.c_iflag
           &= ~(  IGNBRK|BRKINT|PARMRK|ISTRIP
           |INLCR|IGNCR|ICRNL|IXON );
           act_termios.c_oflag
           &= ~OPOST;
          
           act_termios.c_lflag
           &= ~(  ECHO|ECHONL|ICANON|ISIG|IEXTEN );
          
           cfsetospeed(  &act_termios,  baudcode );
           cfsetispeed(  &act_termios,  baudcode );
          
           if (  0 != tcsetattr(  serdbg_fd,  TCSANOW,  &act_termios ) ) {
           err_occurred = true;
           }
           }
           return (  err_occurred
           ? -1
           : 0 );
          }
          
     180  void putDebugChar(  char c ) __attribute__ (  (  __weak__ ) );
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
     184  void putDebugChar
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | send one character to serial port |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
          (  
           char c /* character to print */
           )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | <none> |
          \*=========================================================================*/
          {
           /*
           * call serdbg polling callout,   if available
           */
           if (  serdbg_conf.callout != NULL ) {
           serdbg_conf.callout(   );
           }
           /*
           * check,   whether debug serial port is available
           */
           if (  (  serdbg_tty != NULL ) &&
           (  serdbg_tty->device.write != NULL ) ) {
           /*
           * send character to debug serial port
           */
           serdbg_tty->device.write(  serdbg_tty->minor,  &c,  1 );
           }
          }
          
     217  int getDebugChar(  void ) __attribute__ (  (  __weak__ ) );
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
     221  int getDebugChar
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | wait for one character from serial port |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
          (  
           void /* none */
           )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | received character |
          \*=========================================================================*/
          {
           int c = -1;
           /*
           * check,   whether debug serial port is available
           */
           if (  (  serdbg_tty != NULL ) &&
           (  serdbg_tty->device.pollRead != NULL ) ) {
           do {
           /*
           * call serdbg polling callout,   if available
           */
           if (  serdbg_conf.callout != NULL ) {
           serdbg_conf.callout(   );
           }
           /*
           * get character from debug serial port
           */
           c = serdbg_tty->device.pollRead(  serdbg_tty->minor );
           } while (  c < 0 );
           }
           return c;
          }

libmisc/serdbg/termios_printk.c

       1  /*===============================================================*\
          | File: termios_printk.c |
          +-----------------------------------------------------------------+
          | Copyright (  c ) 2002 IMD |
          | Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
          | Hebststr. 8,   82178 Puchheim,   Germany |
          | <Thomas.Doerfler@imd-systems.de> |
          | The license and distribution terms for this file may be |
          | found in the file LICENSE in this distribution or at |
          | http://www.rtems.com/license/LICENSE. |
          | all rights reserved |
          +-----------------------------------------------------------------+
          | TERMIOS printk support |
          | this module performs low-level printk output using |
          | a polled termios driver |
          | |
          +-----------------------------------------------------------------+
          | date history ID |
          | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
          | 13.05.02 creation doe |
          |*****************************************************************|
          |* $Id: termios_printk.c,  v 1.9 2009/01/02 13:01:21 ralf Exp $
           *
          |*****************************************************************|
          \*===============================================================*/
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/libio_.h>
          #include <errno.h>
          #include <stdio.h>
          #include <fcntl.h>
          #include <termios.h>
          
          #include <rtems/termiostypes.h>
          #include <rtems/bspIo.h>
          #include <rtems/termios_printk.h>
          
          /*
           * internal variables
           */
          int termios_printk_fd = -1;
          struct rtems_termios_tty *termios_printk_tty;
          
      48  static void _termios_printk_null_char(  
           char c __attribute__(  (  unused ) ) )
          {
           return;
          }
          
          BSP_output_char_function_type BSP_output_char = _termios_printk_null_char;
          BSP_polling_getchar_function_type BSP_poll_char;
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
      60  void termios_printk_outputchar
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | send one character to serial port |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
          (  
           char c /* character to print */
           )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | <none> |
          \*=========================================================================*/
          {
           static const char cr = '\r';
           /*
           * check,   whether printk serial port is available
           */
          
           if (  (  termios_printk_tty != NULL ) &&
           (  termios_printk_tty->device.write != NULL ) ) {
           /*
           * call termios_printk polling callout,   if available
           */
           if (  termios_printk_conf.callout != NULL ) {
           termios_printk_conf.callout(   );
           }
           /*
           * send character to debug serial port
           */
           if (  c == '\n' ) {
           termios_printk_tty->device.write(  termios_printk_tty->minor,  &cr,  1 );
           }
           termios_printk_tty->device.write(  termios_printk_tty->minor,  &c,  1 );
           }
          }
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
     101  int termios_printk_inputchar
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | wait for one character from serial port |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
          (  
           void /* none */
           )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | received character |
          \*=========================================================================*/
          {
           int c = -1;
           /*
           * check,   whether debug serial port is available
           */
           if (  (  termios_printk_tty != NULL ) &&
           (  termios_printk_tty->device.pollRead != NULL ) ) {
           do {
           /*
           * call termios_printk polling callout,   if available
           */
           if (  termios_printk_conf.callout != NULL ) {
           termios_printk_conf.callout(   );
           }
           /*
           * get character from debug serial port
           */
           c = termios_printk_tty->device.pollRead(  termios_printk_tty->minor );
           } while (  c < 0 );
           }
           return c;
          }
          
          
          /*=========================================================================*\
          | Function: |
          \*-------------------------------------------------------------------------*/
     142  int termios_printk_open
          
          /*-------------------------------------------------------------------------*\
          | Purpose: |
          | try to open given serial debug port |
          +---------------------------------------------------------------------------+
          | Input Parameters: |
          \*-------------------------------------------------------------------------*/
          (  
           const char *dev_name,   /* name of device to open */
           uint32_t baudrate /* baud rate to use */
           )
          /*-------------------------------------------------------------------------*\
          | Return Value: |
          | 0 on success,   -1 and errno otherwise |
          \*=========================================================================*/
          {
           bool err_occurred = false;
           rtems_libio_t *iop = NULL;
           struct termios act_termios;
           tcflag_t baudcode = B0;
          
           if (  termios_printk_fd >= 0 ) {
           /*
           * already initialized
           */
           return 0;
           }
           /*
           * translate baudrate into baud code
           */
           switch(  baudrate ) {
           case 50: baudcode = B50; break;
           case 75: baudcode = B75; break;
           case 110: baudcode = B110; break;
           case 134: baudcode = B134; break;
           case 150: baudcode = B150; break;
           case 200: baudcode = B200; break;
           case 300: baudcode = B300; break;
           case 600: baudcode = B600; break;
           case 1200: baudcode = B1200; break;
           case 1800: baudcode = B1800; break;
           case 2400: baudcode = B2400; break;
           case 4800: baudcode = B4800; break;
           case 9600: baudcode = B9600; break;
           case 19200: baudcode = B19200; break;
           case 38400: baudcode = B38400; break;
           case 57600: baudcode = B57600; break;
           case 115200: baudcode = B115200; break;
           case 230400: baudcode = B230400; break;
           case 460800: baudcode = B460800; break;
           default : err_occurred = true; errno = EINVAL; break;
           }
           /*
           * open device for serdbg operation
           */
           if (  !err_occurred &&
           (  dev_name != NULL ) &&
           (  dev_name[0] != '\0' ) ) {
           termios_printk_fd = open(  dev_name,  O_RDWR );
           if (  termios_printk_fd < 0 ) {
           err_occurred = true;
           }
           }
           /*
           * capture tty structure
           */
           if (  !err_occurred ) {
           iop = &rtems_libio_iops[termios_printk_fd];
           termios_printk_tty = iop->data1;
           }
           /*
           * set device baudrate
           * (  and transp mode,   this is not really needed )
           * ...
           */
           /*
           * ... get fd settings
           */
           if (  !err_occurred &&
           (  0 != tcgetattr(  termios_printk_fd,  &act_termios ) ) ) {
           err_occurred = true;
           }
           if (  !err_occurred ) {
          
           cfsetospeed(  &act_termios,  baudcode );
           cfsetispeed(  &act_termios,  baudcode );
          
           if (  0 != tcsetattr(  termios_printk_fd,  TCSANOW,  &act_termios ) ) {
           err_occurred = true;
           }
           }
           if (  !err_occurred ) {
           BSP_output_char = termios_printk_outputchar;
           BSP_poll_char = termios_printk_inputchar;
           }
           return (  err_occurred
           ? -1
           : 0 );
          }

libmisc/shell/cat_file.c

       1  /*
           * CAT Command Implementation
           *
           * Author:
           * WORK: fernando.ruiz@ctv.es
           * HOME: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: cat_file.c,  v 1.5 2008/12/18 15:25:27 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          
      21  int rtems_shell_cat_file(  FILE * out,  const char * name ) {
           FILE * fd;
           int c;
          
           if (  out ) {
           fd = fopen(  name,  "r" );
           if (  !fd ) {
           return -1;
           }
           while (  (  c=fgetc(  fd ) )!=EOF )
           fputc(  c,  out );
           fclose(  fd );
           }
           return 0;
          }
          
          

libmisc/shell/cmds.c

       1  /*
           * XXX -- Just monitor commands until those can be integrated better
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: cmds.c,  v 1.26 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <string.h>
          #include <stdlib.h>
          
          #include <rtems.h>
          #include <rtems/monitor.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
          /*-----------------------------------------------------------*
           * with this you can call at all the rtems monitor commands.
           * Not all work fine but you can show the rtems status and more.
           *-----------------------------------------------------------*/
      32  int rtems_shell_main_monitor(  int argc,   char **argv ) {
           const rtems_monitor_command_entry_t *command = NULL;
          
           if (  argc < 1 ) {
           return 1;
           }
          
           command = rtems_monitor_command_lookup(  argv [0] );
          
           if (  command == NULL ) {
           return 1;
           }
          
           command->command_function(  argc,   argv,   &command->command_arg,   0 );
          
           return 0;
          }
          
      50  static bool rtems_shell_register_command(  const rtems_monitor_command_entry_t *e,   void *arg __attribute__(  (  unused ) ) )
          {
           /* Exclude EXIT (  alias quit )*/
           if (  strcmp(  "exit",   e->command ) != 0 ) {
           rtems_shell_cmd_t *shell_cmd =
           (  rtems_shell_cmd_t * ) malloc(  sizeof(  rtems_shell_cmd_t ) );
          
           if (  shell_cmd != NULL ) {
           shell_cmd->name = e->command;
           shell_cmd->topic = "monitor";
           shell_cmd->usage = e->usage;
           shell_cmd->command = rtems_shell_main_monitor;
           shell_cmd->alias = NULL;
           shell_cmd->next = NULL;
          
           if (  rtems_shell_add_cmd_struct(  shell_cmd ) == NULL ) {
           free(  shell_cmd );
           }
           }
           }
          
           return true;
          }
          
      74  void rtems_shell_register_monitor_commands(  void )
          {
           rtems_monitor_command_iterate(  rtems_shell_register_command,   NULL );
          }

libmisc/shell/cmp-ls.c

       1  /* $NetBSD: cmp.c,  v 1.17 2003/08/07 09:05:14 agc Exp $ */
          
          /*
           * Copyright (  c ) 1989,   1993
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Michael Fischbein.
           *
           * 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. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if 0
          #include <sys/cdefs.h>
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )cmp.c 8.1 (  Berkeley ) 5/31/93";
          #else
      45  __RCSID(  "$NetBSD: cmp.c,  v 1.17 2003/08/07 09:05:14 agc Exp $" );
          #endif
          #endif /* not lint */
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          
          #include <fts.h>
          #include <string.h>
          
          #include "extern-ls.h"
          
          #if defined(  __rtems__ ) || defined(  _POSIX_SOURCE ) || defined(  _POSIX_C_SOURCE ) || \
           defined(  _XOPEN_SOURCE ) || defined(  __NetBSD__ )
          #define ATIMENSEC_CMP(  x,   op,   y ) (  (  x )->st_atime op (  y )->st_atime )
          #define CTIMENSEC_CMP(  x,   op,   y ) (  (  x )->st_ctime op (  y )->st_ctime )
          #define MTIMENSEC_CMP(  x,   op,   y ) (  (  x )->st_mtime op (  y )->st_mtime )
          #else
          #define ATIMENSEC_CMP(  x,   op,   y ) \
           (  (  x )->st_atime.tv_nsec op (  y )->st_atime.tv_nsec )
          #define CTIMENSEC_CMP(  x,   op,   y ) \
           (  (  x )->st_ctime.tv_nsec op (  y )->st_ctime.tv_nsec )
          #define MTIMENSEC_CMP(  x,   op,   y ) \
      69   (  (  x )->st_mtime.tv_nsec op (  y )->st_mtime.tv_nsec )
          #endif
          
          int
          namecmp(  const FTSENT *a,   const FTSENT *b )
          {
          
      76   return (  strcmp(  a->fts_name,   b->fts_name ) );
          }
          
          int
          revnamecmp(  const FTSENT *a,   const FTSENT *b )
          {
          
      83   return (  strcmp(  b->fts_name,   a->fts_name ) );
          }
          
          int
          modcmp(  const FTSENT *a,   const FTSENT *b )
          {
          
           if (  b->fts_statp->st_mtime > a->fts_statp->st_mtime )
           return (  1 );
           else if (  b->fts_statp->st_mtime < a->fts_statp->st_mtime )
           return (  -1 );
           else if (  MTIMENSEC_CMP(  b->fts_statp,   >,   a->fts_statp ) )
           return (  1 );
           else if (  MTIMENSEC_CMP(  b->fts_statp,   <,   a->fts_statp ) )
           return (  -1 );
           else
      99   return (  namecmp(  a,   b ) );
          }
          
          int
          revmodcmp(  const FTSENT *a,   const FTSENT *b )
          {
          
           if (  b->fts_statp->st_mtime > a->fts_statp->st_mtime )
           return (  -1 );
           else if (  b->fts_statp->st_mtime < a->fts_statp->st_mtime )
           return (  1 );
           else if (  MTIMENSEC_CMP(  b->fts_statp,   >,   a->fts_statp ) )
           return (  -1 );
           else if (  MTIMENSEC_CMP(  b->fts_statp,   <,   a->fts_statp ) )
           return (  1 );
           else
     115   return (  revnamecmp(  a,   b ) );
          }
          
          int
          acccmp(  const FTSENT *a,   const FTSENT *b )
          {
          
           if (  b->fts_statp->st_atime > a->fts_statp->st_atime )
           return (  1 );
           else if (  b->fts_statp->st_atime < a->fts_statp->st_atime )
           return (  -1 );
           else if (  ATIMENSEC_CMP(  b->fts_statp,   >,   a->fts_statp ) )
           return (  1 );
           else if (  ATIMENSEC_CMP(  b->fts_statp,   <,   a->fts_statp ) )
           return (  -1 );
           else
     131   return (  namecmp(  a,   b ) );
          }
          
          int
          revacccmp(  const FTSENT *a,   const FTSENT *b )
          {
          
           if (  b->fts_statp->st_atime > a->fts_statp->st_atime )
           return (  -1 );
           else if (  b->fts_statp->st_atime < a->fts_statp->st_atime )
           return (  1 );
           else if (  ATIMENSEC_CMP(  b->fts_statp,   >,   a->fts_statp ) )
           return (  -1 );
           else if (  ATIMENSEC_CMP(  b->fts_statp,   <,   a->fts_statp ) )
           return (  1 );
           else
     147   return (  revnamecmp(  a,   b ) );
          }
          
          int
          statcmp(  const FTSENT *a,   const FTSENT *b )
          {
          
           if (  b->fts_statp->st_ctime > a->fts_statp->st_ctime )
           return (  1 );
           else if (  b->fts_statp->st_ctime < a->fts_statp->st_ctime )
           return (  -1 );
           else if (  CTIMENSEC_CMP(  b->fts_statp,   >,   a->fts_statp ) )
           return (  1 );
           else if (  CTIMENSEC_CMP(  b->fts_statp,   <,   a->fts_statp ) )
           return (  -1 );
           else
     163   return (  namecmp(  a,   b ) );
          }
          
          int
          revstatcmp(  const FTSENT *a,   const FTSENT *b )
          {
          
           if (  b->fts_statp->st_ctime > a->fts_statp->st_ctime )
           return (  -1 );
           else if (  b->fts_statp->st_ctime < a->fts_statp->st_ctime )
           return (  1 );
           else if (  CTIMENSEC_CMP(  b->fts_statp,   >,   a->fts_statp ) )
           return (  -1 );
           else if (  CTIMENSEC_CMP(  b->fts_statp,   <,   a->fts_statp ) )
           return (  1 );
           else
     179   return (  revnamecmp(  a,   b ) );
          }
          
          int
          sizecmp(  const FTSENT *a,   const FTSENT *b )
          {
          
           if (  b->fts_statp->st_size > a->fts_statp->st_size )
           return (  1 );
           if (  b->fts_statp->st_size < a->fts_statp->st_size )
           return (  -1 );
           else
     191   return (  namecmp(  a,   b ) );
          }
          
          int
          revsizecmp(  const FTSENT *a,   const FTSENT *b )
          {
          
           if (  b->fts_statp->st_size > a->fts_statp->st_size )
           return (  -1 );
           if (  b->fts_statp->st_size < a->fts_statp->st_size )
           return (  1 );
           else
           return (  revnamecmp(  a,   b ) );
          }

libmisc/shell/dd-args.c

       1  /*-
           * Copyright (  c ) 1991,   1993,   1994
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Keith Muller of the University of California,   San Diego and Lance
           * Visser of Convex Computer Corporation.
           *
           * 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )args.c 8.3 (  Berkeley ) 4/2/94";
          #endif
          #endif /* not lint */
          #include <sys/cdefs.h>
      44  __FBSDID(  "$FreeBSD: src/bin/dd/args.c,  v 1.40 2004/08/15 19:10:05 rwatson Exp $" );
          
          #include <sys/types.h>
          
          #include <err.h>
          #include <errno.h>
          #include <inttypes.h>
          #include <limits.h>
          #include <stdlib.h>
          #include <string.h>
          
          #include "dd.h"
          #include "extern-dd.h"
          
          #define strtouq strtoul
          #define strtoq strtol
          
      61  static int c_arg(  const void *,   const void * );
      62  static int c_conv(  const void *,   const void * );
      63  static void f_bs(  rtems_shell_dd_globals* globals,   char * );
      64  static void f_cbs(  rtems_shell_dd_globals* globals,   char * );
      65  static void f_conv(  rtems_shell_dd_globals* globals,   char * );
      66  static void f_count(  rtems_shell_dd_globals* globals,   char * );
      67  static void f_files(  rtems_shell_dd_globals* globals,   char * );
      68  static void f_fillchar(  rtems_shell_dd_globals* globals,   char * );
      69  static void f_ibs(  rtems_shell_dd_globals* globals,   char * );
      70  static void f_if(  rtems_shell_dd_globals* globals,   char * );
      71  static void f_obs(  rtems_shell_dd_globals* globals,   char * );
      72  static void f_of(  rtems_shell_dd_globals* globals,   char * );
      73  static void f_seek(  rtems_shell_dd_globals* globals,   char * );
      74  static void f_skip(  rtems_shell_dd_globals* globals,   char * );
      75  static uintmax_t get_num(  rtems_shell_dd_globals* globals,   const char * );
      76  static off_t get_off_t(  rtems_shell_dd_globals* globals,   const char * );
          
      78  static const struct arg {
           const char *name;
           void (  *f )(  rtems_shell_dd_globals* globals,   char * );
           uint_least32_t set,   noset;
      82  } args[] = {
           { "bs",   f_bs,   C_BS,   C_BS|C_IBS|C_OBS|C_OSYNC },  
           { "cbs",   f_cbs,   C_CBS,   C_CBS },  
           { "conv",   f_conv,   0,   0 },  
           { "count",   f_count,   C_COUNT,   C_COUNT },  
           { "files",   f_files,   C_FILES,   C_FILES },  
           { "fillchar",   f_fillchar,   C_FILL,   C_FILL },  
           { "ibs",   f_ibs,   C_IBS,   C_BS|C_IBS },  
           { "if",   f_if,   C_IF,   C_IF },  
           { "iseek",   f_skip,   C_SKIP,   C_SKIP },  
           { "obs",   f_obs,   C_OBS,   C_BS|C_OBS },  
           { "of",   f_of,   C_OF,   C_OF },  
           { "oseek",   f_seek,   C_SEEK,   C_SEEK },  
           { "seek",   f_seek,   C_SEEK,   C_SEEK },  
           { "skip",   f_skip,   C_SKIP,   C_SKIP },  
          };
          
          static char *oper;
          
          /*
           * args -- parse JCL syntax of dd.
           */
          void
     105  jcl(  rtems_shell_dd_globals* globals,   char **argv )
          {
           struct arg *ap,   tmp;
           char *arg;
          
           oper = NULL;
          
           in.dbsz = out.dbsz = 512;
          
           while (  (  oper = *++argv ) != NULL ) {
          // if (  (  oper = strdup(  oper ) ) == NULL )
          // errx(  exit_jump,   1,   "unable to allocate space for the argument \"%s\"",   *argv );
           if (  (  arg = strchr(  oper,   '=' ) ) == NULL )
           errx(  exit_jump,   1,   "unknown operand %s",   oper );
           *arg++ = '\0';
           if (  !*arg )
           errx(  exit_jump,   1,   "no value specified for %s",   oper );
           tmp.name = oper;
           if (  !(  ap = (  struct arg * )bsearch(  &tmp,   args,  
           sizeof(  args )/sizeof(  struct arg ),   sizeof(  struct arg ),  
           c_arg ) ) )
           errx(  exit_jump,   1,   "unknown operand %s",   tmp.name );
           if (  ddflags & ap->noset )
           errx(  exit_jump,   1,   "%s: illegal argument combination or already set",  
           tmp.name );
           ddflags |= ap->set;
           ap->f(  globals,   arg );
           }
          
           /* Final sanity checks. */
          
           if (  ddflags & C_BS ) {
           /*
           * Bs is turned off by any conversion -- we assume the user
           * just wanted to set both the input and output block sizes
           * and didn't want the bs semantics,   so we don't warn.
           */
           if (  ddflags & (  C_BLOCK | C_LCASE | C_SWAB | C_UCASE |
           C_UNBLOCK ) )
           ddflags &= ~C_BS;
          
           /* Bs supersedes ibs and obs. */
           if (  ddflags & C_BS && ddflags & (  C_IBS | C_OBS ) )
           warnx(  "bs supersedes ibs and obs" );
           }
          
           /*
           * Ascii/ebcdic and cbs implies block/unblock.
           * Block/unblock requires cbs and vice-versa.
           */
           if (  ddflags & (  C_BLOCK | C_UNBLOCK ) ) {
           if (  !(  ddflags & C_CBS ) )
           errx(  exit_jump,   1,   "record operations require cbs" );
           if (  cbsz == 0 )
           errx(  exit_jump,   1,   "cbs cannot be zero" );
           cfunc = ddflags & C_BLOCK ? block : unblock;
           } else if (  ddflags & C_CBS ) {
           if (  ddflags & (  C_ASCII | C_EBCDIC ) ) {
           if (  ddflags & C_ASCII ) {
           ddflags |= C_UNBLOCK;
           cfunc = unblock;
           } else {
           ddflags |= C_BLOCK;
           cfunc = block;
           }
           } else
           errx(  exit_jump,   1,   "cbs meaningless if not doing record operations" );
           } else
           cfunc = def;
          
           /*
           * Bail out if the calculation of a file offset would overflow.
           */
           if (  in.offset > OFF_MAX / (  ssize_t )in.dbsz ||
           out.offset > OFF_MAX / (  ssize_t )out.dbsz )
           errx(  exit_jump,   1,   "seek offsets cannot be larger than %jd",  
           (  intmax_t )OFF_MAX );
          }
          
          static int
     185  c_arg(  const void *a,   const void *b )
          {
          
           return (  strcmp(  (  (  const struct arg * )a )->name,  
           (  (  const struct arg * )b )->name ) );
          }
          
          static void
     193  f_bs(  rtems_shell_dd_globals* globals,   char *arg )
          {
           uintmax_t res;
          
           res = get_num(  globals,   arg );
           if (  res < 1 || res > SSIZE_MAX )
           errx(  exit_jump,   1,   "bs must be between 1 and %jd",   (  intmax_t )SSIZE_MAX );
           in.dbsz = out.dbsz = (  size_t )res;
          }
          
          static void
     204  f_cbs(  rtems_shell_dd_globals* globals,   char *arg )
          {
           uintmax_t res;
          
           res = get_num(  globals,   arg );
           if (  res < 1 || res > SSIZE_MAX )
           errx(  exit_jump,   1,   "cbs must be between 1 and %jd",   (  intmax_t )SSIZE_MAX );
           cbsz = (  size_t )res;
          }
          
          static void
     215  f_count(  rtems_shell_dd_globals* globals,   char *arg )
          {
           intmax_t res;
          
           res = (  intmax_t )get_num(  globals,   arg );
           if (  res < 0 )
           errx(  exit_jump,   1,   "count cannot be negative" );
           if (  res == 0 )
           cpy_cnt = (  uintmax_t )-1;
           else
           cpy_cnt = (  uintmax_t )res;
          }
          
          static void
     229  f_files(  rtems_shell_dd_globals* globals,   char *arg )
          {
          
           files_cnt = get_num(  globals,   arg );
           if (  files_cnt < 1 )
           errx(  exit_jump,   1,   "files must be between 1 and %jd",   (  uintmax_t )-1 );
          }
          
          static void
     238  f_fillchar(  rtems_shell_dd_globals* globals,   char *arg )
          {
          
           if (  strlen(  arg ) != 1 )
           errx(  exit_jump,   1,   "need exactly one fill char" );
          
           fill_char = arg[0];
          }
          
          static void
     248  f_ibs(  rtems_shell_dd_globals* globals,   char *arg )
          {
           uintmax_t res;
          
           if (  !(  ddflags & C_BS ) ) {
           res = get_num(  globals,   arg );
           if (  res < 1 || res > SSIZE_MAX )
           errx(  exit_jump,   1,   "ibs must be between 1 and %jd",  
           (  intmax_t )SSIZE_MAX );
           in.dbsz = (  size_t )res;
           }
          }
          
          static void
     262  f_if(  rtems_shell_dd_globals* globals,   char *arg )
          {
          
           in.name = strdup(  arg );
          }
          
          static void
     269  f_obs(  rtems_shell_dd_globals* globals,   char *arg )
          {
           uintmax_t res;
          
           if (  !(  ddflags & C_BS ) ) {
           res = get_num(  globals,   arg );
           if (  res < 1 || res > SSIZE_MAX )
           errx(  exit_jump,   1,   "obs must be between 1 and %jd",  
           (  intmax_t )SSIZE_MAX );
           out.dbsz = (  size_t )res;
           }
          }
          
          static void
     283  f_of(  rtems_shell_dd_globals* globals,   char *arg )
          {
          
           out.name = strdup(  arg );
          }
          
          static void
     290  f_seek(  rtems_shell_dd_globals* globals,   char *arg )
          {
          
           out.offset = get_off_t(  globals,   arg );
          }
          
          static void
     297  f_skip(  rtems_shell_dd_globals* globals,   char *arg )
          {
          
           in.offset = get_off_t(  globals,   arg );
          }
          
     303  static const struct conv {
           const char *name;
           uint_least32_t set,   noset;
           const u_char *ctab_;
     307  } clist[] = {
           { "ascii",   C_ASCII,   C_EBCDIC,   e2a_POSIX },  
           { "block",   C_BLOCK,   C_UNBLOCK,   NULL },  
           { "ebcdic",   C_EBCDIC,   C_ASCII,   a2e_POSIX },  
           { "ibm",   C_EBCDIC,   C_ASCII,   a2ibm_POSIX },  
           { "lcase",   C_LCASE,   C_UCASE,   NULL },  
           { "noerror",   C_NOERROR,   0,   NULL },  
           { "notrunc",   C_NOTRUNC,   0,   NULL },  
           { "oldascii",   C_ASCII,   C_EBCDIC,   e2a_32V },  
           { "oldebcdic",   C_EBCDIC,   C_ASCII,   a2e_32V },  
           { "oldibm",   C_EBCDIC,   C_ASCII,   a2ibm_32V },  
           { "osync",   C_OSYNC,   C_BS,   NULL },  
           { "pareven",   C_PAREVEN,   C_PARODD|C_PARSET|C_PARNONE,   NULL},  
           { "parnone",   C_PARNONE,   C_PARODD|C_PARSET|C_PAREVEN,   NULL},  
           { "parodd",   C_PARODD,   C_PAREVEN|C_PARSET|C_PARNONE,   NULL},  
           { "parset",   C_PARSET,   C_PARODD|C_PAREVEN|C_PARNONE,   NULL},  
           { "sparse",   C_SPARSE,   0,   NULL },  
           { "swab",   C_SWAB,   0,   NULL },  
           { "sync",   C_SYNC,   0,   NULL },  
           { "ucase",   C_UCASE,   C_LCASE,   NULL },  
           { "unblock",   C_UNBLOCK,   C_BLOCK,   NULL },  
          };
          
          static void
     331  f_conv(  rtems_shell_dd_globals* globals,   char *arg )
          {
           struct conv *cp,   tmp;
          
           while (  arg != NULL ) {
           tmp.name = strsep(  &arg,   ",  " );
           cp = bsearch(  &tmp,   clist,   sizeof(  clist ) / sizeof(  struct conv ),  
           sizeof(  struct conv ),   c_conv );
           if (  cp == NULL )
           errx(  exit_jump,   1,   "unknown conversion %s",   tmp.name );
           if (  ddflags & cp->noset )
           errx(  exit_jump,   1,   "%s: illegal conversion combination",   tmp.name );
           ddflags |= cp->set;
           if (  cp->ctab_ )
           ctab = cp->ctab_;
           }
          }
          
          static int
     350  c_conv(  const void *a,   const void *b )
          {
          
           return (  strcmp(  (  (  const struct conv * )a )->name,  
           (  (  const struct conv * )b )->name ) );
          }
          
          /*
           * Convert an expression of the following forms to a uintmax_t.
           * 1 ) A positive decimal number.
           * 2 ) A positive decimal number followed by a 'b' or 'B' (  mult by 512 ).
           * 3 ) A positive decimal number followed by a 'k' or 'K' (  mult by 1 << 10 ).
           * 4 ) A positive decimal number followed by a 'm' or 'M' (  mult by 1 << 20 ).
           * 5 ) A positive decimal number followed by a 'g' or 'G' (  mult by 1 << 30 ).
           * 5 ) A positive decimal number followed by a 'w' or 'W' (  mult by sizeof int ).
           * 6 ) Two or more positive decimal numbers (  with/without [BbKkMmGgWw] )
           * separated by 'x' or 'X' (  also '*' for backwards compatibility ),  
           * specifying the product of the indicated values.
           */
          static uintmax_t
     370  get_num(  rtems_shell_dd_globals* globals,   const char *val )
          {
           uintmax_t num,   mult,   prevnum;
           char *expr;
          
           errno = 0;
           num = strtouq(  val,   &expr,   0 );
           if (  errno != 0 ) /* Overflow or underflow. */
           err(  exit_jump,   1,   "%s",   oper );
          
           if (  expr == val ) /* No valid digits. */
           errx(  exit_jump,   1,   "%s: illegal numeric value",   oper );
          
           mult = 0;
           switch (  *expr ) {
           case 'B':
           case 'b':
           mult = UINT32_C(  512 );
           break;
           case 'K':
           case 'k':
           mult = UINT32_C(  1 ) << 10;
           break;
           case 'M':
           case 'm':
           mult = UINT32_C(  1 ) << 20;
           break;
           case 'G':
           case 'g':
           mult = UINT32_C(  1 ) << 30;
           break;
           case 'W':
           case 'w':
           mult = sizeof(  int );
           break;
           default:
           ;
           }
          
           if (  mult != 0 ) {
           prevnum = num;
           num *= mult;
           /* Check for overflow. */
           if (  num / mult != prevnum )
           goto erange;
           expr++;
           }
          
           switch (  *expr ) {
           case '\0':
           break;
           case '*': /* Backward compatible. */
           case 'X':
           case 'x':
           mult = get_num(  globals,   expr + 1 );
           prevnum = num;
           num *= mult;
           if (  num / mult == prevnum )
           break;
          erange:
           errx(  exit_jump,   1,   "%s: %s",   oper,   strerror(  ERANGE ) );
           default:
           errx(  exit_jump,   1,   "%s: illegal numeric value",   oper );
           }
           return (  num );
          }
          
          /*
           * Convert an expression of the following forms to an off_t. This is the
           * same as get_num(   ),   but it uses signed numbers.
           *
           * The major problem here is that an off_t may not necessarily be a intmax_t.
           */
          static off_t
     444  get_off_t(  rtems_shell_dd_globals* globals,   const char *val )
          {
           intmax_t num,   mult,   prevnum;
           char *expr;
          
           errno = 0;
           num = strtoq(  val,   &expr,   0 );
           if (  errno != 0 ) /* Overflow or underflow. */
           err(  exit_jump,   1,   "%s",   oper );
          
           if (  expr == val ) /* No valid digits. */
           errx(  exit_jump,   1,   "%s: illegal numeric value",   oper );
          
           mult = 0;
           switch (  *expr ) {
           case 'B':
           case 'b':
           mult = UINT32_C(  512 );
           break;
           case 'K':
           case 'k':
           mult = UINT32_C(  1 ) << 10;
           break;
           case 'M':
           case 'm':
           mult = UINT32_C(  1 ) << 20;
           break;
           case 'G':
           case 'g':
           mult = UINT32_C(  1 ) << 30;
           break;
           case 'W':
           case 'w':
           mult = sizeof(  int );
           break;
           }
          
           if (  mult != 0 ) {
           prevnum = num;
           num *= mult;
           /* Check for overflow. */
           if (  (  prevnum > 0 ) != (  num > 0 ) || num / mult != prevnum )
           goto erange;
           expr++;
           }
          
           switch (  *expr ) {
           case '\0':
           break;
           case '*': /* Backward compatible. */
           case 'X':
           case 'x':
           mult = (  intmax_t )get_off_t(  globals,   expr + 1 );
           prevnum = num;
           num *= mult;
           if (  (  prevnum > 0 ) == (  num > 0 ) && num / mult == prevnum )
           break;
          erange:
           errx(  exit_jump,   1,   "%s: %s",   oper,   strerror(  ERANGE ) );
           default:
           errx(  exit_jump,   1,   "%s: illegal numeric value",   oper );
           }
           return (  num );
          }

libmisc/shell/dd-conv.c

       1  /*-
           * Copyright (  c ) 1991,   1993,   1994
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Keith Muller of the University of California,   San Diego and Lance
           * Visser of Convex Computer Corporation.
           *
           * 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )conv.c 8.3 (  Berkeley ) 4/2/94";
          #endif
          #endif /* not lint */
          #include <sys/cdefs.h>
      44  __FBSDID(  "$FreeBSD: src/bin/dd/conv.c,  v 1.19 2004/04/06 20:06:45 markm Exp $" );
          
          #include <sys/param.h>
          
          #include <err.h>
          #include <inttypes.h>
          #include <string.h>
          
          #include "dd.h"
          #include "extern-dd.h"
          
          /*
           * def --
           * Copy input to output. Input is buffered until reaches obs,   and then
           * output until less than obs remains. Only a single buffer is used.
           * Worst case buffer calculation is (  ibs + obs - 1 ).
           */
          void
      62  def(  rtems_shell_dd_globals* globals )
          {
           u_char *inp;
           const u_char *t;
           size_t cnt;
          
           if (  (  t = ctab ) != NULL )
           for (  inp = in.dbp - (  cnt = in.dbrcnt ); cnt--; ++inp )
           *inp = t[*inp];
          
           /* Make the output buffer look right. */
           out.dbp = in.dbp;
           out.dbcnt = in.dbcnt;
          
           if (  in.dbcnt >= out.dbsz ) {
           /* If the output buffer is full,   write it. */
           dd_out(  globals,   0 );
          
           /*
           * Ddout copies the leftover output to the beginning of
           * the buffer and resets the output buffer. Reset the
           * input buffer to match it.
           */
           in.dbp = out.dbp;
           in.dbcnt = out.dbcnt;
           }
          }
          
          void
      91  def_close(  rtems_shell_dd_globals* globals )
          {
           /* Just update the count,   everything is already in the buffer. */
           if (  in.dbcnt )
           out.dbcnt = in.dbcnt;
          }
          
          /*
           * Copy variable length newline terminated records with a max size cbsz
           * bytes to output. Records less than cbs are padded with spaces.
           *
           * max in buffer: MAX(  ibs,   cbsz )
           * max out buffer: obs + cbsz
           */
          void
     106  block(  rtems_shell_dd_globals* globals )
          {
           u_char *inp,   *outp;
           const u_char *t;
           size_t cnt,   maxlen;
           static int intrunc;
           int ch;
          
           /*
           * Record truncation can cross block boundaries. If currently in a
           * truncation state,   keep tossing characters until reach a newline.
           * Start at the beginning of the buffer,   as the input buffer is always
           * left empty.
           */
           if (  intrunc ) {
           for (  inp = in.db,   cnt = in.dbrcnt; cnt && *inp++ != '\n'; --cnt )
           ;
           if (  !cnt ) {
           in.dbcnt = 0;
           in.dbp = in.db;
           return;
           }
           intrunc = 0;
           /* Adjust the input buffer numbers. */
           in.dbcnt = cnt - 1;
           in.dbp = inp + cnt - 1;
           }
          
           /*
           * Copy records (  max cbsz size chunks ) into the output buffer. The
           * translation is done as we copy into the output buffer.
           */
           ch = 0;
           for (  inp = in.dbp - in.dbcnt,   outp = out.dbp; in.dbcnt; ) {
           maxlen = MIN(  cbsz,   in.dbcnt );
           if (  (  t = ctab ) != NULL )
           for (  cnt = 0; cnt < maxlen && (  ch = *inp++ ) != '\n';
           ++cnt )
           *outp++ = t[ch];
           else
           for (  cnt = 0; cnt < maxlen && (  ch = *inp++ ) != '\n';
           ++cnt )
           *outp++ = ch;
           /*
           * Check for short record without a newline. Reassemble the
           * input block.
           */
           if (  ch != '\n' && in.dbcnt < cbsz ) {
           (  void )memmove(  in.db,   in.dbp - in.dbcnt,   in.dbcnt );
           break;
           }
          
           /* Adjust the input buffer numbers. */
           in.dbcnt -= cnt;
           if (  ch == '\n' )
           --in.dbcnt;
          
           /* Pad short records with spaces. */
           if (  cnt < cbsz )
           (  void )memset(  outp,   ctab ? ctab[' '] : ' ',   cbsz - cnt );
           else {
           /*
           * If the next character wouldn't have ended the
           * block,   it's a truncation.
           */
           if (  !in.dbcnt || *inp != '\n' )
           ++st.trunc;
          
           /* Toss characters to a newline. */
           for (  ; in.dbcnt && *inp++ != '\n'; --in.dbcnt )
           ;
           if (  !in.dbcnt )
           intrunc = 1;
           else
           --in.dbcnt;
           }
          
           /* Adjust output buffer numbers. */
           out.dbp += cbsz;
           if (  (  out.dbcnt += cbsz ) >= out.dbsz )
           dd_out(  globals,   0 );
           outp = out.dbp;
           }
           in.dbp = in.db + in.dbcnt;
          }
          
          void
     193  block_close(  rtems_shell_dd_globals* globals )
          {
           /*
           * Copy any remaining data into the output buffer and pad to a record.
           * Don't worry about truncation or translation,   the input buffer is
           * always empty when truncating,   and no characters have been added for
           * translation. The bottom line is that anything left in the input
           * buffer is a truncated record. Anything left in the output buffer
           * just wasn't big enough.
           */
           if (  in.dbcnt ) {
           ++st.trunc;
           (  void )memmove(  out.dbp,   in.dbp - in.dbcnt,   in.dbcnt );
           (  void )memset(  out.dbp + in.dbcnt,   ctab ? ctab[' '] : ' ',  
           cbsz - in.dbcnt );
           out.dbcnt += cbsz;
           }
          }
          
          /*
           * Convert fixed length (  cbsz ) records to variable length. Deletes any
           * trailing blanks and appends a newline.
           *
           * max in buffer: MAX(  ibs,   cbsz ) + cbsz
           * max out buffer: obs + cbsz
           */
          void
     220  unblock(  rtems_shell_dd_globals* globals )
          {
           u_char *inp;
           const u_char *t;
           size_t cnt;
          
           /* Translation and case conversion. */
           if (  (  t = ctab ) != NULL )
           for (  inp = in.dbp - (  cnt = in.dbrcnt ); cnt--; ++inp )
           *inp = t[*inp];
           /*
           * Copy records (  max cbsz size chunks ) into the output buffer. The
           * translation has to already be done or we might not recognize the
           * spaces.
           */
           for (  inp = in.db; in.dbcnt >= cbsz; inp += cbsz,   in.dbcnt -= cbsz ) {
           for (  t = inp + cbsz - 1; t >= inp && *t == ' '; --t )
           ;
           if (  t >= inp ) {
           cnt = t - inp + 1;
           (  void )memmove(  out.dbp,   inp,   cnt );
           out.dbp += cnt;
           out.dbcnt += cnt;
           }
           *out.dbp++ = '\n';
           if (  ++out.dbcnt >= out.dbsz )
           dd_out(  globals,   0 );
           }
           if (  in.dbcnt )
           (  void )memmove(  in.db,   in.dbp - in.dbcnt,   in.dbcnt );
           in.dbp = in.db + in.dbcnt;
          }
          
          void
     254  unblock_close(  rtems_shell_dd_globals* globals )
          {
           u_char *t;
           size_t cnt;
          
           if (  in.dbcnt ) {
           warnx(  "%s: short input record",   in.name );
           for (  t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t )
           ;
           if (  t >= in.db ) {
           cnt = t - in.db + 1;
           (  void )memmove(  out.dbp,   in.db,   cnt );
           out.dbp += cnt;
           out.dbcnt += cnt;
           }
           ++out.dbcnt;
           *out.dbp++ = '\n';
           }
          }

libmisc/shell/dd-conv_tab.c

       1  /*-
           * Copyright (  c ) 1991,   1993
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Keith Muller of the University of California,   San Diego and Lance
           * Visser of Convex Computer Corporation.
           *
           * 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )conv_tab.c 8.1 (  Berkeley ) 5/31/93";
          #endif
          #endif /* not lint */
          #include <sys/cdefs.h>
      44  __FBSDID(  "$FreeBSD: src/bin/dd/conv_tab.c,  v 1.12 2004/04/06 20:06:45 markm Exp $" );
          
          #include <sys/types.h>
          
          /*
           * There are currently six tables:
           *
           * ebcdic -> ascii 32V conv=oldascii
           * ascii -> ebcdic 32V conv=oldebcdic
           * ascii -> ibm ebcdic 32V conv=oldibm
           *
           * ebcdic -> ascii POSIX/S5 conv=ascii
           * ascii -> ebcdic POSIX/S5 conv=ebcdic
           * ascii -> ibm ebcdic POSIX/S5 conv=ibm
           *
           * Other tables are built from these if multiple conversions are being
           * done.
           *
           * Tables used for conversions to/from IBM and EBCDIC to support an extension
           * to POSIX P1003.2/D11. The tables referencing POSIX contain data extracted
           * from tables 4-3 and 4-4 in P1003.2/Draft 11. The historic tables were
           * constructed by running against a file with all possible byte values.
           *
           * More information can be obtained in "Correspondences of 8-Bit and Hollerith
           * Codes for Computer Environments-A USASI Tutorial",   Communications of the
           * ACM,   Volume 11,   Number 11,   November 1968,   pp. 783-789.
           */
          
          u_char casetab[256];
          
          /* EBCDIC to ASCII -- 32V compatible. */
          const u_char e2a_32V[] = {
           0000,   0001,   0002,   0003,   0234,   0011,   0206,   0177,   /* 0000 */
           0227,   0215,   0216,   0013,   0014,   0015,   0016,   0017,   /* 0010 */
           0020,   0021,   0022,   0023,   0235,   0205,   0010,   0207,   /* 0020 */
           0030,   0031,   0222,   0217,   0034,   0035,   0036,   0037,   /* 0030 */
           0200,   0201,   0202,   0203,   0204,   0012,   0027,   0033,   /* 0040 */
           0210,   0211,   0212,   0213,   0214,   0005,   0006,   0007,   /* 0050 */
           0220,   0221,   0026,   0223,   0224,   0225,   0226,   0004,   /* 0060 */
           0230,   0231,   0232,   0233,   0024,   0025,   0236,   0032,   /* 0070 */
           0040,   0240,   0241,   0242,   0243,   0244,   0245,   0246,   /* 0100 */
           0247,   0250,   0133,   0056,   0074,   0050,   0053,   0041,   /* 0110 */
           0046,   0251,   0252,   0253,   0254,   0255,   0256,   0257,   /* 0120 */
           0260,   0261,   0135,   0044,   0052,   0051,   0073,   0136,   /* 0130 */
           0055,   0057,   0262,   0263,   0264,   0265,   0266,   0267,   /* 0140 */
           0270,   0271,   0174,   0054,   0045,   0137,   0076,   0077,   /* 0150 */
           0272,   0273,   0274,   0275,   0276,   0277,   0300,   0301,   /* 0160 */
           0302,   0140,   0072,   0043,   0100,   0047,   0075,   0042,   /* 0170 */
           0303,   0141,   0142,   0143,   0144,   0145,   0146,   0147,   /* 0200 */
           0150,   0151,   0304,   0305,   0306,   0307,   0310,   0311,   /* 0210 */
           0312,   0152,   0153,   0154,   0155,   0156,   0157,   0160,   /* 0220 */
           0161,   0162,   0313,   0314,   0315,   0316,   0317,   0320,   /* 0230 */
           0321,   0176,   0163,   0164,   0165,   0166,   0167,   0170,   /* 0240 */
           0171,   0172,   0322,   0323,   0324,   0325,   0326,   0327,   /* 0250 */
           0330,   0331,   0332,   0333,   0334,   0335,   0336,   0337,   /* 0260 */
           0340,   0341,   0342,   0343,   0344,   0345,   0346,   0347,   /* 0270 */
           0173,   0101,   0102,   0103,   0104,   0105,   0106,   0107,   /* 0300 */
           0110,   0111,   0350,   0351,   0352,   0353,   0354,   0355,   /* 0310 */
           0175,   0112,   0113,   0114,   0115,   0116,   0117,   0120,   /* 0320 */
           0121,   0122,   0356,   0357,   0360,   0361,   0362,   0363,   /* 0330 */
           0134,   0237,   0123,   0124,   0125,   0126,   0127,   0130,   /* 0340 */
           0131,   0132,   0364,   0365,   0366,   0367,   0370,   0371,   /* 0350 */
           0060,   0061,   0062,   0063,   0064,   0065,   0066,   0067,   /* 0360 */
           0070,   0071,   0372,   0373,   0374,   0375,   0376,   0377,   /* 0370 */
          };
          
          /* ASCII to EBCDIC -- 32V compatible. */
          const u_char a2e_32V[] = {
           0000,   0001,   0002,   0003,   0067,   0055,   0056,   0057,   /* 0000 */
           0026,   0005,   0045,   0013,   0014,   0015,   0016,   0017,   /* 0010 */
           0020,   0021,   0022,   0023,   0074,   0075,   0062,   0046,   /* 0020 */
           0030,   0031,   0077,   0047,   0034,   0035,   0036,   0037,   /* 0030 */
           0100,   0117,   0177,   0173,   0133,   0154,   0120,   0175,   /* 0040 */
           0115,   0135,   0134,   0116,   0153,   0140,   0113,   0141,   /* 0050 */
           0360,   0361,   0362,   0363,   0364,   0365,   0366,   0367,   /* 0060 */
           0370,   0371,   0172,   0136,   0114,   0176,   0156,   0157,   /* 0070 */
           0174,   0301,   0302,   0303,   0304,   0305,   0306,   0307,   /* 0100 */
           0310,   0311,   0321,   0322,   0323,   0324,   0325,   0326,   /* 0110 */
           0327,   0330,   0331,   0342,   0343,   0344,   0345,   0346,   /* 0120 */
           0347,   0350,   0351,   0112,   0340,   0132,   0137,   0155,   /* 0130 */
           0171,   0201,   0202,   0203,   0204,   0205,   0206,   0207,   /* 0140 */
           0210,   0211,   0221,   0222,   0223,   0224,   0225,   0226,   /* 0150 */
           0227,   0230,   0231,   0242,   0243,   0244,   0245,   0246,   /* 0160 */
           0247,   0250,   0251,   0300,   0152,   0320,   0241,   0007,   /* 0170 */
           0040,   0041,   0042,   0043,   0044,   0025,   0006,   0027,   /* 0200 */
           0050,   0051,   0052,   0053,   0054,   0011,   0012,   0033,   /* 0210 */
           0060,   0061,   0032,   0063,   0064,   0065,   0066,   0010,   /* 0220 */
           0070,   0071,   0072,   0073,   0004,   0024,   0076,   0341,   /* 0230 */
           0101,   0102,   0103,   0104,   0105,   0106,   0107,   0110,   /* 0240 */
           0111,   0121,   0122,   0123,   0124,   0125,   0126,   0127,   /* 0250 */
           0130,   0131,   0142,   0143,   0144,   0145,   0146,   0147,   /* 0260 */
           0150,   0151,   0160,   0161,   0162,   0163,   0164,   0165,   /* 0270 */
           0166,   0167,   0170,   0200,   0212,   0213,   0214,   0215,   /* 0300 */
           0216,   0217,   0220,   0232,   0233,   0234,   0235,   0236,   /* 0310 */
           0237,   0240,   0252,   0253,   0254,   0255,   0256,   0257,   /* 0320 */
           0260,   0261,   0262,   0263,   0264,   0265,   0266,   0267,   /* 0330 */
           0270,   0271,   0272,   0273,   0274,   0275,   0276,   0277,   /* 0340 */
           0312,   0313,   0314,   0315,   0316,   0317,   0332,   0333,   /* 0350 */
           0334,   0335,   0336,   0337,   0352,   0353,   0354,   0355,   /* 0360 */
           0356,   0357,   0372,   0373,   0374,   0375,   0376,   0377,   /* 0370 */
          };
          
          /* ASCII to IBM EBCDIC -- 32V compatible. */
          const u_char a2ibm_32V[] = {
           0000,   0001,   0002,   0003,   0067,   0055,   0056,   0057,   /* 0000 */
           0026,   0005,   0045,   0013,   0014,   0015,   0016,   0017,   /* 0010 */
           0020,   0021,   0022,   0023,   0074,   0075,   0062,   0046,   /* 0020 */
           0030,   0031,   0077,   0047,   0034,   0035,   0036,   0037,   /* 0030 */
           0100,   0132,   0177,   0173,   0133,   0154,   0120,   0175,   /* 0040 */
           0115,   0135,   0134,   0116,   0153,   0140,   0113,   0141,   /* 0050 */
           0360,   0361,   0362,   0363,   0364,   0365,   0366,   0367,   /* 0060 */
           0370,   0371,   0172,   0136,   0114,   0176,   0156,   0157,   /* 0070 */
           0174,   0301,   0302,   0303,   0304,   0305,   0306,   0307,   /* 0100 */
           0310,   0311,   0321,   0322,   0323,   0324,   0325,   0326,   /* 0110 */
           0327,   0330,   0331,   0342,   0343,   0344,   0345,   0346,   /* 0120 */
           0347,   0350,   0351,   0255,   0340,   0275,   0137,   0155,   /* 0130 */
           0171,   0201,   0202,   0203,   0204,   0205,   0206,   0207,   /* 0140 */
           0210,   0211,   0221,   0222,   0223,   0224,   0225,   0226,   /* 0150 */
           0227,   0230,   0231,   0242,   0243,   0244,   0245,   0246,   /* 0160 */
           0247,   0250,   0251,   0300,   0117,   0320,   0241,   0007,   /* 0170 */
           0040,   0041,   0042,   0043,   0044,   0025,   0006,   0027,   /* 0200 */
           0050,   0051,   0052,   0053,   0054,   0011,   0012,   0033,   /* 0210 */
           0060,   0061,   0032,   0063,   0064,   0065,   0066,   0010,   /* 0220 */
           0070,   0071,   0072,   0073,   0004,   0024,   0076,   0341,   /* 0230 */
           0101,   0102,   0103,   0104,   0105,   0106,   0107,   0110,   /* 0240 */
           0111,   0121,   0122,   0123,   0124,   0125,   0126,   0127,   /* 0250 */
           0130,   0131,   0142,   0143,   0144,   0145,   0146,   0147,   /* 0260 */
           0150,   0151,   0160,   0161,   0162,   0163,   0164,   0165,   /* 0270 */
           0166,   0167,   0170,   0200,   0212,   0213,   0214,   0215,   /* 0300 */
           0216,   0217,   0220,   0232,   0233,   0234,   0235,   0236,   /* 0310 */
           0237,   0240,   0252,   0253,   0254,   0255,   0256,   0257,   /* 0320 */
           0260,   0261,   0262,   0263,   0264,   0265,   0266,   0267,   /* 0330 */
           0270,   0271,   0272,   0273,   0274,   0275,   0276,   0277,   /* 0340 */
           0312,   0313,   0314,   0315,   0316,   0317,   0332,   0333,   /* 0350 */
           0334,   0335,   0336,   0337,   0352,   0353,   0354,   0355,   /* 0360 */
           0356,   0357,   0372,   0373,   0374,   0375,   0376,   0377,   /* 0370 */
          };
          
          /* EBCDIC to ASCII -- POSIX and System V compatible. */
          const u_char e2a_POSIX[] = {
           0000,   0001,   0002,   0003,   0234,   0011,   0206,   0177,   /* 0000 */
           0227,   0215,   0216,   0013,   0014,   0015,   0016,   0017,   /* 0010 */
           0020,   0021,   0022,   0023,   0235,   0205,   0010,   0207,   /* 0020 */
           0030,   0031,   0222,   0217,   0034,   0035,   0036,   0037,   /* 0030 */
           0200,   0201,   0202,   0203,   0204,   0012,   0027,   0033,   /* 0040 */
           0210,   0211,   0212,   0213,   0214,   0005,   0006,   0007,   /* 0050 */
           0220,   0221,   0026,   0223,   0224,   0225,   0226,   0004,   /* 0060 */
           0230,   0231,   0232,   0233,   0024,   0025,   0236,   0032,   /* 0070 */
           0040,   0240,   0241,   0242,   0243,   0244,   0245,   0246,   /* 0100 */
           0247,   0250,   0325,   0056,   0074,   0050,   0053,   0174,   /* 0110 */
           0046,   0251,   0252,   0253,   0254,   0255,   0256,   0257,   /* 0120 */
           0260,   0261,   0041,   0044,   0052,   0051,   0073,   0176,   /* 0130 */
           0055,   0057,   0262,   0263,   0264,   0265,   0266,   0267,   /* 0140 */
           0270,   0271,   0313,   0054,   0045,   0137,   0076,   0077,   /* 0150 */
           0272,   0273,   0274,   0275,   0276,   0277,   0300,   0301,   /* 0160 */
           0302,   0140,   0072,   0043,   0100,   0047,   0075,   0042,   /* 0170 */
           0303,   0141,   0142,   0143,   0144,   0145,   0146,   0147,   /* 0200 */
           0150,   0151,   0304,   0305,   0306,   0307,   0310,   0311,   /* 0210 */
           0312,   0152,   0153,   0154,   0155,   0156,   0157,   0160,   /* 0220 */
           0161,   0162,   0136,   0314,   0315,   0316,   0317,   0320,   /* 0230 */
           0321,   0345,   0163,   0164,   0165,   0166,   0167,   0170,   /* 0240 */
           0171,   0172,   0322,   0323,   0324,   0133,   0326,   0327,   /* 0250 */
           0330,   0331,   0332,   0333,   0334,   0335,   0336,   0337,   /* 0260 */
           0340,   0341,   0342,   0343,   0344,   0135,   0346,   0347,   /* 0270 */
           0173,   0101,   0102,   0103,   0104,   0105,   0106,   0107,   /* 0300 */
           0110,   0111,   0350,   0351,   0352,   0353,   0354,   0355,   /* 0310 */
           0175,   0112,   0113,   0114,   0115,   0116,   0117,   0120,   /* 0320 */
           0121,   0122,   0356,   0357,   0360,   0361,   0362,   0363,   /* 0330 */
           0134,   0237,   0123,   0124,   0125,   0126,   0127,   0130,   /* 0340 */
           0131,   0132,   0364,   0365,   0366,   0367,   0370,   0371,   /* 0350 */
           0060,   0061,   0062,   0063,   0064,   0065,   0066,   0067,   /* 0360 */
           0070,   0071,   0372,   0373,   0374,   0375,   0376,   0377,   /* 0370 */
          };
          
          /* ASCII to EBCDIC -- POSIX and System V compatible. */
          const u_char a2e_POSIX[] = {
           0000,   0001,   0002,   0003,   0067,   0055,   0056,   0057,   /* 0000 */
           0026,   0005,   0045,   0013,   0014,   0015,   0016,   0017,   /* 0010 */
           0020,   0021,   0022,   0023,   0074,   0075,   0062,   0046,   /* 0020 */
           0030,   0031,   0077,   0047,   0034,   0035,   0036,   0037,   /* 0030 */
           0100,   0132,   0177,   0173,   0133,   0154,   0120,   0175,   /* 0040 */
           0115,   0135,   0134,   0116,   0153,   0140,   0113,   0141,   /* 0050 */
           0360,   0361,   0362,   0363,   0364,   0365,   0366,   0367,   /* 0060 */
           0370,   0371,   0172,   0136,   0114,   0176,   0156,   0157,   /* 0070 */
           0174,   0301,   0302,   0303,   0304,   0305,   0306,   0307,   /* 0100 */
           0310,   0311,   0321,   0322,   0323,   0324,   0325,   0326,   /* 0110 */
           0327,   0330,   0331,   0342,   0343,   0344,   0345,   0346,   /* 0120 */
           0347,   0350,   0351,   0255,   0340,   0275,   0232,   0155,   /* 0130 */
           0171,   0201,   0202,   0203,   0204,   0205,   0206,   0207,   /* 0140 */
           0210,   0211,   0221,   0222,   0223,   0224,   0225,   0226,   /* 0150 */
           0227,   0230,   0231,   0242,   0243,   0244,   0245,   0246,   /* 0160 */
           0247,   0250,   0251,   0300,   0117,   0320,   0137,   0007,   /* 0170 */
           0040,   0041,   0042,   0043,   0044,   0025,   0006,   0027,   /* 0200 */
           0050,   0051,   0052,   0053,   0054,   0011,   0012,   0033,   /* 0210 */
           0060,   0061,   0032,   0063,   0064,   0065,   0066,   0010,   /* 0220 */
           0070,   0071,   0072,   0073,   0004,   0024,   0076,   0341,   /* 0230 */
           0101,   0102,   0103,   0104,   0105,   0106,   0107,   0110,   /* 0240 */
           0111,   0121,   0122,   0123,   0124,   0125,   0126,   0127,   /* 0250 */
           0130,   0131,   0142,   0143,   0144,   0145,   0146,   0147,   /* 0260 */
           0150,   0151,   0160,   0161,   0162,   0163,   0164,   0165,   /* 0270 */
           0166,   0167,   0170,   0200,   0212,   0213,   0214,   0215,   /* 0300 */
           0216,   0217,   0220,   0152,   0233,   0234,   0235,   0236,   /* 0310 */
           0237,   0240,   0252,   0253,   0254,   0112,   0256,   0257,   /* 0320 */
           0260,   0261,   0262,   0263,   0264,   0265,   0266,   0267,   /* 0330 */
           0270,   0271,   0272,   0273,   0274,   0241,   0276,   0277,   /* 0340 */
           0312,   0313,   0314,   0315,   0316,   0317,   0332,   0333,   /* 0350 */
           0334,   0335,   0336,   0337,   0352,   0353,   0354,   0355,   /* 0360 */
           0356,   0357,   0372,   0373,   0374,   0375,   0376,   0377,   /* 0370 */
          };
          
          /* ASCII to IBM EBCDIC -- POSIX and System V compatible. */
          const u_char a2ibm_POSIX[] = {
           0000,   0001,   0002,   0003,   0067,   0055,   0056,   0057,   /* 0000 */
           0026,   0005,   0045,   0013,   0014,   0015,   0016,   0017,   /* 0010 */
           0020,   0021,   0022,   0023,   0074,   0075,   0062,   0046,   /* 0020 */
           0030,   0031,   0077,   0047,   0034,   0035,   0036,   0037,   /* 0030 */
           0100,   0132,   0177,   0173,   0133,   0154,   0120,   0175,   /* 0040 */
           0115,   0135,   0134,   0116,   0153,   0140,   0113,   0141,   /* 0050 */
           0360,   0361,   0362,   0363,   0364,   0365,   0366,   0367,   /* 0060 */
           0370,   0371,   0172,   0136,   0114,   0176,   0156,   0157,   /* 0070 */
           0174,   0301,   0302,   0303,   0304,   0305,   0306,   0307,   /* 0100 */
           0310,   0311,   0321,   0322,   0323,   0324,   0325,   0326,   /* 0110 */
           0327,   0330,   0331,   0342,   0343,   0344,   0345,   0346,   /* 0120 */
           0347,   0350,   0351,   0255,   0340,   0275,   0137,   0155,   /* 0130 */
           0171,   0201,   0202,   0203,   0204,   0205,   0206,   0207,   /* 0140 */
           0210,   0211,   0221,   0222,   0223,   0224,   0225,   0226,   /* 0150 */
           0227,   0230,   0231,   0242,   0243,   0244,   0245,   0246,   /* 0160 */
           0247,   0250,   0251,   0300,   0117,   0320,   0241,   0007,   /* 0170 */
           0040,   0041,   0042,   0043,   0044,   0025,   0006,   0027,   /* 0200 */
           0050,   0051,   0052,   0053,   0054,   0011,   0012,   0033,   /* 0210 */
           0060,   0061,   0032,   0063,   0064,   0065,   0066,   0010,   /* 0220 */
           0070,   0071,   0072,   0073,   0004,   0024,   0076,   0341,   /* 0230 */
           0101,   0102,   0103,   0104,   0105,   0106,   0107,   0110,   /* 0240 */
           0111,   0121,   0122,   0123,   0124,   0125,   0126,   0127,   /* 0250 */
           0130,   0131,   0142,   0143,   0144,   0145,   0146,   0147,   /* 0260 */
           0150,   0151,   0160,   0161,   0162,   0163,   0164,   0165,   /* 0270 */
           0166,   0167,   0170,   0200,   0212,   0213,   0214,   0215,   /* 0300 */
           0216,   0217,   0220,   0232,   0233,   0234,   0235,   0236,   /* 0310 */
           0237,   0240,   0252,   0253,   0254,   0255,   0256,   0257,   /* 0320 */
           0260,   0261,   0262,   0263,   0264,   0265,   0266,   0267,   /* 0330 */
           0270,   0271,   0272,   0273,   0274,   0275,   0276,   0277,   /* 0340 */
           0312,   0313,   0314,   0315,   0316,   0317,   0332,   0333,   /* 0350 */
           0334,   0335,   0336,   0337,   0352,   0353,   0354,   0355,   /* 0360 */
           0356,   0357,   0372,   0373,   0374,   0375,   0376,   0377,   /* 0370 */
          };

libmisc/shell/dd-misc.c

       1  /*-
           * Copyright (  c ) 1991,   1993,   1994
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Keith Muller of the University of California,   San Diego and Lance
           * Visser of Convex Computer Corporation.
           *
           * 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )misc.c 8.3 (  Berkeley ) 4/2/94";
          #endif
          #endif /* not lint */
          #if 0
          #include <sys/cdefs.h>
      45  __FBSDID(  "$FreeBSD: src/bin/dd/misc.c,  v 1.27 2004/04/06 20:06:46 markm Exp $" );
          #endif
          
          #include <sys/types.h>
          #include <sys/time.h>
          
          #include <errno.h>
          #include <inttypes.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          
          #include "dd.h"
          #include "extern-dd.h"
          
          void
      62  summary(  rtems_shell_dd_globals* globals )
          {
           struct timeval tv;
           double secs;
           char buf[100];
          
           (  void )gettimeofday(  &tv,   (  struct timezone * )NULL );
           secs = tv.tv_sec + tv.tv_usec * 1e-6 - st.start;
           if (  secs < 1e-6 )
           secs = 1e-6;
           /* Use snprintf(  3 ) so that we don't reenter stdio(  3 ). */
           (  void )snprintf(  buf,   sizeof(  buf ),  
           "%ju+%ju records in\n%ju+%ju records out\n",  
           st.in_full,   st.in_part,   st.out_full,   st.out_part );
           (  void )write(  STDERR_FILENO,   buf,   strlen(  buf ) );
           if (  st.swab ) {
           (  void )snprintf(  buf,   sizeof(  buf ),   "%ju odd length swab %s\n",  
           st.swab,   (  st.swab == 1 ) ? "block" : "blocks" );
           (  void )write(  STDERR_FILENO,   buf,   strlen(  buf ) );
           }
           if (  st.trunc ) {
           (  void )snprintf(  buf,   sizeof(  buf ),   "%ju truncated %s\n",  
           st.trunc,   (  st.trunc == 1 ) ? "block" : "blocks" );
           (  void )write(  STDERR_FILENO,   buf,   strlen(  buf ) );
           }
           (  void )snprintf(  buf,   sizeof(  buf ),  
           "%ju bytes transferred in %.6f secs (  %.0f bytes/sec )\n",  
           st.bytes,   secs,   st.bytes / secs );
           (  void )write(  STDERR_FILENO,   buf,   strlen(  buf ) );
          }
          
          /* ARGSUSED */
          void
      95  summaryx(  rtems_shell_dd_globals* globals,   int __unused )
          {
           int save_errno = errno;
          
           summary(  globals );
           errno = save_errno;
          }
          
          #if RTEMS_REMOVED
          /* ARGSUSED */
          void
     106  terminate(  int sig )
          {
          
           summary(   );
           _exit(  sig == 0 ? 0 : 1 );
          }
          #endif

libmisc/shell/dd-position.c

       1  /*-
           * Copyright (  c ) 1991,   1993,   1994
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Keith Muller of the University of California,   San Diego and Lance
           * Visser of Convex Computer Corporation.
           *
           * 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )position.c 8.3 (  Berkeley ) 4/2/94";
          #include <sys/cdefs.h>
      42  __FBSDID(  "$FreeBSD: src/bin/dd/position.c,  v 1.23 2004/04/06 20:06:46 markm Exp $" );
          #endif
          #endif /* not lint */
          
          #include <sys/types.h>
          #if RTEMS_REMOVED
          #include <sys/mtio.h>
          #endif
          
          #include <err.h>
          #include <errno.h>
          #include <inttypes.h>
          #include <unistd.h>
          
          #include "dd.h"
          #include "extern-dd.h"
          
          /*
           * Position input/output data streams before starting the copy. Device type
           * dependent. Seekable devices use lseek,   and the rest position by reading.
           * Seeking past the end of file can cause null blocks to be written to the
           * output.
           */
          void
      66  pos_in(  rtems_shell_dd_globals* globals )
          {
           off_t cnt;
           int warned;
           ssize_t nr;
           size_t bcnt;
          
           /* If known to be seekable,   try to seek on it. */
           if (  in.flags & ISSEEK ) {
           errno = 0;
           if (  lseek(  in.fd,   in.offset * in.dbsz,   SEEK_CUR ) == -1 &&
           errno != 0 )
           err(  exit_jump,   1,   "%s",   in.name );
           return;
           }
          
           /* Don't try to read a really weird amount (  like negative ). */
           if (  in.offset < 0 )
           errx(  exit_jump,   1,   "%s: illegal offset",   "iseek/skip" );
          
           /*
           * Read the data. If a pipe,   read until satisfy the number of bytes
           * being skipped. No differentiation for reading complete and partial
           * blocks for other devices.
           */
           for (  bcnt = in.dbsz,   cnt = in.offset,   warned = 0; cnt; ) {
           if (  (  nr = read(  in.fd,   in.db,   bcnt ) ) > 0 ) {
           if (  in.flags & ISPIPE ) {
           if (  !(  bcnt -= nr ) ) {
           bcnt = in.dbsz;
           --cnt;
           }
           } else
           --cnt;
           continue;
           }
          
           if (  nr == 0 ) {
           if (  files_cnt > 1 ) {
           --files_cnt;
           continue;
           }
           errx(  exit_jump,   1,   "skip reached end of input" );
           }
          
           /*
           * Input error -- either EOF with no more files,   or I/O error.
           * If noerror not set die. POSIX requires that the warning
           * message be followed by an I/O display.
           */
           if (  ddflags & C_NOERROR ) {
           if (  !warned ) {
           warn(  "%s",   in.name );
           warned = 1;
           summary(  globals );
           }
           continue;
           }
           err(  exit_jump,   1,   "%s",   in.name );
           }
          }
          
          void
     129  pos_out(  rtems_shell_dd_globals* globals )
          {
          #if RTEMS_REMOVED
           struct mtop t_op;
           off_t cnt;
           ssize_t n;
          #endif
          
           /*
           * If not a tape,   try seeking on the file. Seeking on a pipe is
           * going to fail,   but don't protect the user -- they shouldn't
           * have specified the seek operand.
           */
           if (  out.flags & (  ISSEEK | ISPIPE ) ) {
           errno = 0;
           if (  lseek(  out.fd,   out.offset * out.dbsz,   SEEK_CUR ) == -1 &&
           errno != 0 )
           err(  exit_jump,   1,   "%s",   out.name );
           return;
           }
          
           /* Don't try to read a really weird amount (  like negative ). */
           if (  out.offset < 0 )
           errx(  exit_jump,   1,   "%s: illegal offset",   "oseek/seek" );
          
          #if RTEMS_REMOVED
           /* If no read access,   try using mtio. */
           if (  out.flags & NOREAD ) {
           t_op.mt_op = MTFSR;
           t_op.mt_count = out.offset;
          
           if (  ioctl(  out.fd,   MTIOCTOP,   &t_op ) == -1 )
           err(  1,   "%s",   out.name );
           return;
           }
          
           /* Read it. */
           for (  cnt = 0; cnt < out.offset; ++cnt ) {
           if (  (  n = read(  out.fd,   out.db,   out.dbsz ) ) > 0 )
           continue;
          
           if (  n == -1 )
           err(  1,   "%s",   out.name );
          
           /*
           * If reach EOF,   fill with NUL characters; first,   back up over
           * the EOF mark. Note,   cnt has not yet been incremented,   so
           * the EOF read does not count as a seek'd block.
           */
           t_op.mt_op = MTBSR;
           t_op.mt_count = 1;
           if (  ioctl(  out.fd,   MTIOCTOP,   &t_op ) == -1 )
           err(  1,   "%s",   out.name );
          
           while (  cnt++ < out.offset ) {
           n = write(  out.fd,   out.db,   out.dbsz );
           if (  n == -1 )
           err(  1,   "%s",   out.name );
           if (  (  size_t )n != out.dbsz )
           errx(  1,   "%s: write failure",   out.name );
           }
           break;
           }
          #endif
          }

libmisc/shell/err.c

       1  /* $NetBSD: err.c,  v 1.25 2005/09/13 13:51:50 christos Exp $ */
          
          /*-
           * Copyright (  c ) 1993
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_NBTOOL_CONFIG_H
          #include "nbtool_config.h"
          #endif
          
          #include <sys/cdefs.h>
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          #if 0
          static char sccsid[] = "@(  # )err.c 8.1 (  Berkeley ) 6/4/93";
          #else
      45  __RCSID(  "$NetBSD: err.c,  v 1.25 2005/09/13 13:51:50 christos Exp $" );
          #endif
          #endif /* LIBC_SCCS and not lint */
          
          #include <err.h>
          #include <stdarg.h>
          
          #ifdef __weak_alias
      53  __weak_alias(  err,   _err )
          #endif
          
          __dead void
          err(  jmp_buf* exit_jmp,   int eval,   const char *fmt,   ... )
          {
           va_list ap;
          
           va_start(  ap,   fmt );
           verr(  exit_jmp,   eval,   fmt,   ap );
           va_end(  ap );
          }

libmisc/shell/errx.c

       1  /* $NetBSD: errx.c,  v 1.13 2005/09/13 13:51:50 christos Exp $ */
          
          /*-
           * Copyright (  c ) 1993
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_NBTOOL_CONFIG_H
          #include "nbtool_config.h"
          #endif
          
          #include <sys/cdefs.h>
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          #if 0
          static char sccsid[] = "@(  # )err.c 8.1 (  Berkeley ) 6/4/93";
          #else
      45  __RCSID(  "$NetBSD: errx.c,  v 1.13 2005/09/13 13:51:50 christos Exp $" );
          #endif
          #endif /* LIBC_SCCS and not lint */
          
          #include <err.h>
          #include <stdarg.h>
          
          #ifdef __weak_alias
      53  __weak_alias(  errx,   _errx )
          #endif
          
          __dead void
          errx(  jmp_buf* exit_jmp,   int eval,   const char *fmt,   ... )
          {
           va_list ap;
          
           va_start(  ap,   fmt );
           verrx(  exit_jmp,   eval,   fmt,   ap );
           va_end(  ap );
          }

libmisc/shell/fdisk.c

       1  /**
           * @file
           *
           * Block device partition management.
           */
          
          /*
           * Copyright (  c ) 2009
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * D-82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          
          #include <rtems/bdpart.h>
          #include <rtems/error.h>
          #include <rtems/shell.h>
          
          #define RTEMS_BDPART_SHELL_ERROR(   fmt,   ... ) \
           do { \
           printf(   "error: " fmt "\n",   ##__VA_ARGS__ ); \
           return -1; \
           } while (  0 )
          
          #define RTEMS_BDPART_SHELL_ERROR_SC(   sc,   fmt,   ... ) \
           if (  (  sc ) != RTEMS_SUCCESSFUL ) { \
           printf(   "error: " fmt ": %s\n",   ##__VA_ARGS__,   rtems_status_text(   sc ) ); \
           return -1; \
           }
          
          typedef enum {
           RTEMS_BDPART_SHELL_FS,  
           RTEMS_BDPART_SHELL_N,  
           RTEMS_BDPART_SHELL_MBR,  
           RTEMS_BDPART_SHELL_GPT
          } rtems_bdpart_shell_state;
          
          static const char rtems_bdpart_shell_usage [] =
           "disk format and utility functions\n"
           "\n"
           "fdisk DISK_NAME\n"
           "\tprints the partition table\n"
           "\n"
           "fdisk DISK_NAME [FS N1 [N2 ... ]] ... [write] [FORMAT]\n"
           "\tcreates a new partition table\n"
           "\n"
           "fdisk DISK_NAME register\n"
           "\tcreates a logical disk for each partition of the disk\n"
           "\n"
           "fdisk DISK_NAME unregister\n"
           "\tdeletes the logical disks associated with the partitions of the disk\n"
           "\n"
           "fdisk DISK_NAME mount\n"
           "\tmounts the file system of each partition of the disk\n"
           "\n"
           "fdisk DISK_NAME unmount\n"
           "\tunmounts the file system of each partition of the disk\n"
      71   "\n"
           "option values:\n"
           "\tDISK_NAME: absolute path to disk device like '/dev/hda'\n"
           "\tN*: weights of positive integers\n"
           "\tFS: 0x00 ... 0xff,   fat12,   fat16,   fat32,   data\n"
           "\twrite: write the new partition table to the disk\n"
           "\tFORMAT: mbr [[no]dos],   gpt";
          
          static int rtems_bdpart_shell_main(   int argc,   char **argv )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           rtems_bdpart_format format;
           rtems_bdpart_partition pt [RTEMS_BDPART_PARTITION_NUMBER_HINT];
           unsigned dist [RTEMS_BDPART_PARTITION_NUMBER_HINT];
           size_t count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
           const char *disk_name = NULL;
           const char *mount_base = "/mnt";
           bool do_create = false;
           bool do_read = false;
           bool do_write = false;
           bool do_register = false;
           bool do_unregister = false;
           bool do_mount = false;
           bool do_unmount = false;
           bool do_dump = false;
          
           if (  argc < 2 ) {
           puts(   rtems_bdpart_shell_usage );
           return -1;
           }
          
           disk_name = argv [1];
          
           if (  argc == 2 ) {
           do_read = true;
           do_dump = true;
           } else if (  argc == 3 ) {
           /* Check option */
           if (  strcmp(   argv [2],   "register" ) == 0 ) {
           do_read = true;
           do_register = true;
           } else if (  strcmp(   argv [2],   "unregister" ) == 0 ) {
           do_read = true;
           do_unregister = true;
           } else if (  strcmp(   argv [2],   "mount" ) == 0 ) {
           do_read = true;
           do_mount = true;
           } else if (  strcmp(   argv [2],   "unmount" ) == 0 ) {
           do_read = true;
           do_unmount = true;
           } else {
           RTEMS_BDPART_SHELL_ERROR(   "unexpected option: %s",   argv [2] );
           }
           } else {
           rtems_bdpart_shell_state state = RTEMS_BDPART_SHELL_FS;
           uint8_t current_type = RTEMS_BDPART_MBR_FAT_32;
           size_t i = 0;
           int ai = 0;
          
           /* Clear partition table */
           memset(   pt,   0,   sizeof(   pt ) );
          
           /* Default format */
           format.type = RTEMS_BDPART_FORMAT_MBR;
           format.mbr.disk_id = 0;
           format.mbr.dos_compatibility = true;
          
           for (  ai = 2; ai < argc; ++ai ) {
           char *s = argv [ai];
           unsigned long v = 0;
           char *end = NULL;
          
           if (  strlen(   s ) == 0 ) {
           continue;
           } else if (  strcmp(   s,   "write" ) == 0 ) {
           do_write = true;
           continue;
           } else if (  strcmp(   s,   "mbr" ) == 0 ) {
           state = RTEMS_BDPART_SHELL_MBR;
           format.type = RTEMS_BDPART_FORMAT_MBR;
           continue;
           } else if (  strcmp(   s,   "gpt" ) == 0 ) {
           state = RTEMS_BDPART_SHELL_GPT;
           format.type = RTEMS_BDPART_FORMAT_GPT;
           continue;
           }
          
           switch (  state ) {
           case RTEMS_BDPART_SHELL_FS:
           v = strtoul(   s,   &end,   16 );
           if (  *end == '\0' ) {
           if (  v <= 0xffU ) {
           current_type = (  uint8_t ) v;
           } else {
           RTEMS_BDPART_SHELL_ERROR(   "type value out of range: %s",   argv [ai] );
           }
           } else if (  strcmp(   s,   "fat32" ) == 0 ) {
           current_type = RTEMS_BDPART_MBR_FAT_32;
           } else if (  strcmp(   s,   "data" ) == 0 ) {
           current_type = RTEMS_BDPART_MBR_DATA;
           } else if (  strcmp(   s,   "fat16" ) == 0 ) {
           current_type = RTEMS_BDPART_MBR_FAT_16;
           } else if (  strcmp(   s,   "fat12" ) == 0 ) {
           current_type = RTEMS_BDPART_MBR_FAT_12;
           } else {
           RTEMS_BDPART_SHELL_ERROR(   "unexpected option: %s",   argv [ai] );
           }
           state = RTEMS_BDPART_SHELL_N;
           break;
           case RTEMS_BDPART_SHELL_N:
           v = strtoul(   s,   &end,   10 );
           if (  *end == '\0' ) {
           rtems_bdpart_to_partition_type(   current_type,   pt [i].type );
           dist [i] = v;
           if (  i < count ) {
           ++i;
           } else {
           RTEMS_BDPART_SHELL_ERROR(   "too many partitions" );
           }
           } else {
           --ai;
           state = RTEMS_BDPART_SHELL_FS;
           }
           break;
           case RTEMS_BDPART_SHELL_MBR:
           if (  strcmp(   s,   "dos" ) == 0 ) {
           format.mbr.dos_compatibility = true;
           } else if (  strcmp(   s,   "nodos" ) == 0 ) {
           format.mbr.dos_compatibility = false;
           } else {
           RTEMS_BDPART_SHELL_ERROR(   "unexpected option: %s",   argv [ai] );
           }
           break;
           case RTEMS_BDPART_SHELL_GPT:
           RTEMS_BDPART_SHELL_ERROR(   "unexpected option: %s",   argv [ai] );
           default:
           RTEMS_BDPART_SHELL_ERROR(   "fdisk interal error" );
           }
           }
          
           /* Partition number */
           count = i;
          
           /* Actions */
           do_create = true;
           do_dump = true;
           if (  do_write ) {
           do_read = true;
           }
           }
          
           if (  do_create ) {
           /* Create partitions */
           sc = rtems_bdpart_create(   disk_name,   &format,   pt,   dist,   count );
           RTEMS_BDPART_SHELL_ERROR_SC(   sc,   "cannot create partitions for '%s'",   disk_name );
           }
          
           if (  do_write ) {
           /* Write partitions */
           sc = rtems_bdpart_write(   disk_name,   &format,   pt,   count );
           RTEMS_BDPART_SHELL_ERROR_SC(   sc,   "cannot write partitions to '%s'",   disk_name );
           }
          
           if (  do_read ) {
           /* Read partitions */
           count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
           sc = rtems_bdpart_read(   disk_name,   &format,   pt,   &count );
           RTEMS_BDPART_SHELL_ERROR_SC(   sc,   "cannot read partitions from '%s'",   disk_name );
           }
          
           if (  do_register ) {
           /* Register partitions */
           sc = rtems_bdpart_register(   disk_name,   pt,   count );
           RTEMS_BDPART_SHELL_ERROR_SC(   sc,   "cannot register partitions of '%s'",   disk_name );
           }
          
           if (  do_unregister ) {
           /* Unregister partitions */
           sc = rtems_bdpart_unregister(   disk_name,   pt,   count );
           RTEMS_BDPART_SHELL_ERROR_SC(   sc,   "cannot unregister partitions of '%s'",   disk_name );
           }
          
           if (  do_mount ) {
           /* Mount partitions */
           sc = rtems_bdpart_mount(   disk_name,   pt,   count,   mount_base );
           RTEMS_BDPART_SHELL_ERROR_SC(   sc,   "cannot mount partitions of '%s' to '%s'",   disk_name,   mount_base );
           }
          
           if (  do_unmount ) {
           /* Unmount partitions */
           sc = rtems_bdpart_unmount(   disk_name,   pt,   count,   mount_base );
           RTEMS_BDPART_SHELL_ERROR_SC(   sc,   "cannot unmount partitions of '%s'",   disk_name );
           }
          
           if (  do_dump ) {
           /* Dump partitions */
           rtems_bdpart_dump(   pt,   count );
           }
          
           return 0;
          }
          
          struct rtems_shell_cmd_tt rtems_shell_FDISK_Command = {
           .name = "fdisk",  
           .usage = rtems_bdpart_shell_usage,  
           .topic = "files",  
           .command = rtems_bdpart_shell_main,  
           .alias = NULL,  
           .next = NULL
          };

libmisc/shell/filemode.c

       1  /*-
           * Copyright (  c ) 1990,   1993
           * The Regents of the University of California. 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          static char sccsid[] = "@(  # )strmode.c 8.3 (  Berkeley ) 8/15/94";
          #endif /* LIBC_SCCS and not lint */
          #include <sys/cdefs.h>
      38  __FBSDID(  "$FreeBSD: src/lib/libc/string/strmode.c,  v 1.5 2007/01/09 00:28:12 imp Exp $" );
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <string.h>
          
          void
      45  strmode(  
           mode_t mode,  
           char *p )
          {
           /* print type */
           switch (  mode & S_IFMT ) {
           case S_IFDIR: /* directory */
           *p++ = 'd';
           break;
           case S_IFCHR: /* character special */
           *p++ = 'c';
           break;
           case S_IFBLK: /* block special */
           *p++ = 'b';
           break;
           case S_IFREG: /* regular */
           *p++ = '-';
           break;
           case S_IFLNK: /* symbolic link */
           *p++ = 'l';
           break;
           case S_IFSOCK: /* socket */
           *p++ = 's';
           break;
          #ifdef S_IFIFO
           case S_IFIFO: /* fifo */
           *p++ = 'p';
           break;
          #endif
          #ifdef S_IFWHT
           case S_IFWHT: /* whiteout */
           *p++ = 'w';
           break;
          #endif
           default: /* unknown */
           *p++ = '?';
           break;
           }
           /* usr */
           if (  mode & S_IRUSR )
           *p++ = 'r';
           else
           *p++ = '-';
           if (  mode & S_IWUSR )
           *p++ = 'w';
           else
           *p++ = '-';
           switch (  mode & (  S_IXUSR | S_ISUID ) ) {
           case 0:
           *p++ = '-';
           break;
           case S_IXUSR:
           *p++ = 'x';
           break;
           case S_ISUID:
           *p++ = 'S';
           break;
           case S_IXUSR | S_ISUID:
           *p++ = 's';
           break;
           }
           /* group */
           if (  mode & S_IRGRP )
           *p++ = 'r';
           else
           *p++ = '-';
           if (  mode & S_IWGRP )
           *p++ = 'w';
           else
           *p++ = '-';
           switch (  mode & (  S_IXGRP | S_ISGID ) ) {
           case 0:
           *p++ = '-';
           break;
           case S_IXGRP:
           *p++ = 'x';
           break;
           case S_ISGID:
           *p++ = 'S';
           break;
           case S_IXGRP | S_ISGID:
           *p++ = 's';
           break;
           }
           /* other */
           if (  mode & S_IROTH )
           *p++ = 'r';
           else
           *p++ = '-';
           if (  mode & S_IWOTH )
           *p++ = 'w';
           else
           *p++ = '-';
           switch (  mode & (  S_IXOTH | S_ISVTX ) ) {
           case 0:
           *p++ = '-';
           break;
           case S_IXOTH:
           *p++ = 'x';
           break;
           case S_ISVTX:
           *p++ = 'T';
           break;
           case S_IXOTH | S_ISVTX:
           *p++ = 't';
           break;
           }
           *p++ = ' '; /* will be a '+' if ACL's implemented */
           *p = '\0';
          }

libmisc/shell/fts.c

       1  /* $NetBSD: fts.c,  v 1.40 2009/11/02 17:17:34 stacktic Exp $ */
          
          /*-
           * Copyright (  c ) 1990,   1993,   1994
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_NBTOOL_CONFIG_H
          #include "nbtool_config.h"
          #endif
          
          #include <sys/cdefs.h>
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          #if 0
          static char sccsid[] = "@(  # )fts.c 8.6 (  Berkeley ) 8/14/94";
          #else
      45  __RCSID(  "$NetBSD: fts.c,  v 1.40 2009/11/02 17:17:34 stacktic Exp $" );
          #endif
          #endif /* LIBC_SCCS and not lint */
          
          #ifndef __rtems__
          #include "namespace.h"
          #endif
          #include <limits.h>
          #include <sys/param.h>
          #include <sys/stat.h>
          
          #include <assert.h>
          #include <dirent.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <fts.h>
          #include <stdlib.h>
          #include <stdint.h>
          #include <string.h>
          #include <unistd.h>
          
          #define _DIAGASSERT(  a )
          #undef FTS_WHITEOUT
          #define dirfd(  dp ) __dirfd(  dp )
          
          #if ! HAVE_NBTOOL_CONFIG_H
          #define HAVE_STRUCT_DIRENT_D_NAMLEN
          #endif
          
      74  static FTSENT *fts_alloc(  FTS *,   const char *,   size_t );
      75  static FTSENT *fts_build(  FTS *,   int );
      76  static void fts_free(  FTSENT * );
      77  static void fts_lfree(  FTSENT * );
      78  static void fts_load(  FTS *,   FTSENT * );
      79  static size_t fts_maxarglen(  char * const * );
      80  static size_t fts_pow2(  size_t );
      81  static int fts_palloc(  FTS *,   size_t );
      82  static void fts_padjust(  FTS *,   FTSENT * );
      83  static FTSENT *fts_sort(  FTS *,   FTSENT *,   size_t );
      84  static unsigned short fts_stat(  FTS *,   FTSENT *,   int );
      85  static int fts_safe_changedir(  const FTS *,   const FTSENT *,   int,  
           const char * );
          
          #if defined(  ALIGNBYTES ) && defined(  ALIGN )
          #define FTS_ALLOC_ALIGNED 1
          /* FIXME: Redefine because some versions of
           * RTEMS newlib and the BSDs ship a broken ALIGN */
          #undef ALIGN
          #define ALIGN(  p ) (  (  (  uintptr_t )(  p ) + ALIGNBYTES ) & ~ALIGNBYTES )
          #else
          #undef FTS_ALLOC_ALIGNED
          #endif
          
          #define ISDOT(  a ) (  a[0] == '.' && (  !a[1] || (  a[1] == '.' && !a[2] ) ) )
          
          #define CLR(  opt ) (  sp->fts_options &= ~(  opt ) )
          #define ISSET(  opt ) (  sp->fts_options & (  opt ) )
          #define SET(  opt ) (  sp->fts_options |= (  opt ) )
          
          #define CHDIR(  sp,   path ) (  !ISSET(  FTS_NOCHDIR ) && chdir(  path ) )
          #define FCHDIR(  sp,   fd ) (  !ISSET(  FTS_NOCHDIR ) && fchdir(  fd ) )
          
          /* fts_build flags */
          #define BCHILD 1 /* fts_children */
          #define BNAMES 2 /* fts_children,   names only */
          #define BREAD 3 /* fts_read */
          
          #ifndef DTF_HIDEW
          #undef FTS_WHITEOUT
          #endif
          
          FTS *
     117  fts_open(  char * const *argv,   int options,  
           int (  *compar )(  const FTSENT **,   const FTSENT ** ) )
          {
           FTS *sp;
           FTSENT *p,   *root;
           size_t nitems;
           FTSENT *parent,   *tmp = NULL; /* pacify gcc */
           size_t len;
          
           _DIAGASSERT(  argv != NULL );
          
           /* Options check. */
           if (  options & ~FTS_OPTIONMASK ) {
           errno = EINVAL;
           return (  NULL );
           }
          
           /* Allocate/initialize the stream */
           if (  (  sp = malloc(  (  unsigned int )sizeof(  FTS ) ) ) == NULL )
           return (  NULL );
           memset(  sp,   0,   sizeof(  FTS ) );
           sp->fts_compar = compar;
           sp->fts_options = options;
          
           /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
           if (  ISSET(  FTS_LOGICAL ) )
           SET(  FTS_NOCHDIR );
          
           /*
           * Start out with 1K of path space,   and enough,   in any case,  
           * to hold the user's paths.
           */
           if (  fts_palloc(  sp,   MAX(  fts_maxarglen(  argv ),   MAXPATHLEN ) ) )
           goto mem1;
          
           /* Allocate/initialize root's parent. */
           if (  (  parent = fts_alloc(  sp,   "",   0 ) ) == NULL )
           goto mem2;
           parent->fts_level = FTS_ROOTPARENTLEVEL;
          
           /* Allocate/initialize root(  s ). */
           for (  root = NULL,   nitems = 0; *argv; ++argv,   ++nitems ) {
           /* Don't allow zero-length paths. */
           if (  (  len = strlen(  *argv ) ) == 0 ) {
           errno = ENOENT;
           goto mem3;
           }
          
           if (  (  p = fts_alloc(  sp,   *argv,   len ) ) == NULL )
           goto mem3;
           p->fts_level = FTS_ROOTLEVEL;
           p->fts_parent = parent;
           p->fts_accpath = p->fts_name;
           p->fts_info = fts_stat(  sp,   p,   ISSET(  FTS_COMFOLLOW ) );
          
           /* Command-line "." and ".." are real directories. */
           if (  p->fts_info == FTS_DOT )
           p->fts_info = FTS_D;
          
           /*
           * If comparison routine supplied,   traverse in sorted
           * order; otherwise traverse in the order specified.
           */
           if (  compar ) {
           p->fts_link = root;
           root = p;
           } else {
           p->fts_link = NULL;
           if (  root == NULL )
           tmp = root = p;
           else {
           tmp->fts_link = p;
           tmp = p;
           }
           }
           }
           if (  compar && nitems > 1 )
           root = fts_sort(  sp,   root,   nitems );
          
           /*
           * Allocate a dummy pointer and make fts_read think that we've just
           * finished the node before the root(  s ); set p->fts_info to FTS_INIT
           * so that everything about the "current" node is ignored.
           */
           if (  (  sp->fts_cur = fts_alloc(  sp,   "",   0 ) ) == NULL )
           goto mem3;
           sp->fts_cur->fts_link = root;
           sp->fts_cur->fts_info = FTS_INIT;
          
           /*
           * If using chdir(  2 ),   grab a file descriptor pointing to dot to insure
           * that we can get back here; this could be avoided for some paths,  
           * but almost certainly not worth the effort. Slashes,   symbolic links,  
           * and ".." are all fairly nasty problems. Note,   if we can't get the
           * descriptor we run anyway,   just more slowly.
           */
           if (  !ISSET(  FTS_NOCHDIR ) ) {
           if (  (  sp->fts_rfd = open(  ".",   O_RDONLY,   0 ) ) == -1 )
           SET(  FTS_NOCHDIR );
           else if (  fcntl(  sp->fts_rfd,   F_SETFD,   FD_CLOEXEC ) == -1 ) {
           close(  sp->fts_rfd );
           SET(  FTS_NOCHDIR );
           }
           }
          
           if (  nitems == 0 )
           fts_free(  parent );
          
           return (  sp );
          
          mem3: fts_lfree(  root );
           fts_free(  parent );
          mem2: free(  sp->fts_path );
          mem1: free(  sp );
           return (  NULL );
          }
          
          static void
     235  fts_load(  FTS *sp,   FTSENT *p )
          {
           size_t len;
           char *cp;
          
           _DIAGASSERT(  sp != NULL );
           _DIAGASSERT(  p != NULL );
          
           /*
           * Load the stream structure for the next traversal. Since we don't
           * actually enter the directory until after the preorder visit,   set
           * the fts_accpath field specially so the chdir gets done to the right
           * place and the user can access the first node. From fts_open it's
           * known that the path will fit.
           */
           len = p->fts_pathlen = p->fts_namelen;
           memmove(  sp->fts_path,   p->fts_name,   len + 1 );
           if (  (  cp = strrchr(  p->fts_name,   '/' ) ) && (  cp != p->fts_name || cp[1] ) ) {
           len = strlen(  ++cp );
           memmove(  p->fts_name,   cp,   len + 1 );
           p->fts_namelen = len;
           }
           p->fts_accpath = p->fts_path = sp->fts_path;
           sp->fts_dev = p->fts_dev;
          }
          
          int
     262  fts_close(  FTS *sp )
          {
           FTSENT *freep,   *p;
           int saved_errno = 0;
          
           _DIAGASSERT(  sp != NULL );
          
           /*
           * This still works if we haven't read anything -- the dummy structure
           * points to the root list,   so we step through to the end of the root
           * list which has a valid parent pointer.
           */
           if (  sp->fts_cur ) {
           if (  sp->fts_cur->fts_flags & FTS_SYMFOLLOW )
           (  void )close(  sp->fts_cur->fts_symfd );
           for (  p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL; ) {
           freep = p;
           p = p->fts_link ? p->fts_link : p->fts_parent;
           fts_free(  freep );
           }
           fts_free(  p );
           }
          
           /* Free up child linked list,   sort array,   path buffer. */
           if (  sp->fts_child )
           fts_lfree(  sp->fts_child );
           if (  sp->fts_array )
           free(  sp->fts_array );
           free(  sp->fts_path );
          
           /* Return to original directory,   save errno if necessary. */
           if (  !ISSET(  FTS_NOCHDIR ) ) {
           if (  fchdir(  sp->fts_rfd ) == -1 )
           saved_errno = errno;
           (  void )close(  sp->fts_rfd );
           }
          
           /* Free up the stream pointer. */
           free(  sp );
           if (  saved_errno ) {
           errno = saved_errno;
           return -1;
           }
          
           return 0;
          }
          
          #if !defined(  __FTS_COMPAT_TAILINGSLASH )
          
          /*
           * Special case of "/" at the end of the path so that slashes aren't
           * appended which would cause paths to be written as "....//foo".
           */
          #define NAPPEND(  p ) \
           (  p->fts_path[p->fts_pathlen - 1] == '/' \
           ? p->fts_pathlen - 1 : p->fts_pathlen )
          
          #else /* !defined(  __FTS_COMPAT_TAILINGSLASH ) */
          
          /*
           * compatibility with the old behaviour.
           *
           * Special case a root of "/" so that slashes aren't appended which would
           * cause paths to be written as "//foo".
           */
          
          #define NAPPEND(  p ) \
           (  p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \
           p->fts_path[0] == '/' ? 0 : p->fts_pathlen )
     331  
          #endif /* !defined(  __FTS_COMPAT_TAILINGSLASH ) */
          
          FTSENT *
          fts_read(  FTS *sp )
          {
           FTSENT *p,   *tmp;
           int instr;
           char *t;
           int saved_errno;
          
           _DIAGASSERT(  sp != NULL );
          
           /* If finished or unrecoverable error,   return NULL. */
           if (  sp->fts_cur == NULL || ISSET(  FTS_STOP ) )
           return (  NULL );
          
           /* Set current node pointer. */
           p = sp->fts_cur;
          
           /* Save and zero out user instructions. */
           instr = p->fts_instr;
           p->fts_instr = FTS_NOINSTR;
          
           /* Any type of file may be re-visited; re-stat and re-turn. */
           if (  instr == FTS_AGAIN ) {
           p->fts_info = fts_stat(  sp,   p,   0 );
           return (  p );
           }
          
           /*
           * Following a symlink -- SLNONE test allows application to see
           * SLNONE and recover. If indirecting through a symlink,   have
           * keep a pointer to current location. If unable to get that
           * pointer,   follow fails.
           */
           if (  instr == FTS_FOLLOW &&
           (  p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE ) ) {
           p->fts_info = fts_stat(  sp,   p,   1 );
           if (  p->fts_info == FTS_D && !ISSET(  FTS_NOCHDIR ) ) {
           if (  (  p->fts_symfd = open(  ".",   O_RDONLY,   0 ) ) == -1 ) {
           p->fts_errno = errno;
           p->fts_info = FTS_ERR;
           } else if (  fcntl(  p->fts_symfd,   F_SETFD,   FD_CLOEXEC ) == -1 ) {
           p->fts_errno = errno;
           p->fts_info = FTS_ERR;
           close(  p->fts_symfd );
           } else
           p->fts_flags |= FTS_SYMFOLLOW;
           }
           return (  p );
           }
          
           /* Directory in pre-order. */
           if (  p->fts_info == FTS_D ) {
           /* If skipped or crossed mount point,   do post-order visit. */
           if (  instr == FTS_SKIP ||
           (  ISSET(  FTS_XDEV ) && p->fts_dev != sp->fts_dev ) ) {
           if (  p->fts_flags & FTS_SYMFOLLOW )
           (  void )close(  p->fts_symfd );
           if (  sp->fts_child ) {
           fts_lfree(  sp->fts_child );
           sp->fts_child = NULL;
           }
           p->fts_info = FTS_DP;
           return (  p );
           }
          
           /* Rebuild if only read the names and now traversing. */
           if (  sp->fts_child && ISSET(  FTS_NAMEONLY ) ) {
           CLR(  FTS_NAMEONLY );
           fts_lfree(  sp->fts_child );
           sp->fts_child = NULL;
           }
          
           /*
           * Cd to the subdirectory.
           *
           * If have already read and now fail to chdir,   whack the list
           * to make the names come out right,   and set the parent errno
           * so the application will eventually get an error condition.
           * Set the FTS_DONTCHDIR flag so that when we logically change
           * directories back to the parent we don't do a chdir.
           *
           * If haven't read do so. If the read fails,   fts_build sets
           * FTS_STOP or the fts_info field of the node.
           */
           if (  sp->fts_child ) {
           if (  fts_safe_changedir(  sp,   p,   -1,   p->fts_accpath ) ) {
           p->fts_errno = errno;
           p->fts_flags |= FTS_DONTCHDIR;
           for (  p = sp->fts_child; p; p = p->fts_link )
           p->fts_accpath =
           p->fts_parent->fts_accpath;
           }
           } else if (  (  sp->fts_child = fts_build(  sp,   BREAD ) ) == NULL ) {
           if (  ISSET(  FTS_STOP ) )
           return (  NULL );
           return (  p );
           }
           p = sp->fts_child;
           sp->fts_child = NULL;
           goto name;
           }
          
           /* Move to the next node on this level. */
          next: tmp = p;
           if (  (  p = p->fts_link ) != NULL ) {
           fts_free(  tmp );
          
           /*
           * If reached the top,   return to the original directory,   and
           * load the paths for the next root.
           */
           if (  p->fts_level == FTS_ROOTLEVEL ) {
           if (  FCHDIR(  sp,   sp->fts_rfd ) ) {
           SET(  FTS_STOP );
           return (  NULL );
           }
           fts_load(  sp,   p );
           return (  sp->fts_cur = p );
           }
          
           /*
           * User may have called fts_set on the node. If skipped,  
           * ignore. If followed,   get a file descriptor so we can
           * get back if necessary.
           */
           if (  p->fts_instr == FTS_SKIP )
           goto next;
           if (  p->fts_instr == FTS_FOLLOW ) {
           p->fts_info = fts_stat(  sp,   p,   1 );
           if (  p->fts_info == FTS_D && !ISSET(  FTS_NOCHDIR ) ) {
           if (  (  p->fts_symfd =
           open(  ".",   O_RDONLY,   0 ) ) == -1 ) {
           p->fts_errno = errno;
           p->fts_info = FTS_ERR;
           } else if (  fcntl(  p->fts_symfd,   F_SETFD,   FD_CLOEXEC ) == -1 ) {
           p->fts_errno = errno;
           p->fts_info = FTS_ERR;
           close(  p->fts_symfd );
           } else
           p->fts_flags |= FTS_SYMFOLLOW;
           }
           p->fts_instr = FTS_NOINSTR;
           }
          
          name: t = sp->fts_path + NAPPEND(  p->fts_parent );
           *t++ = '/';
           memmove(  t,   p->fts_name,   (  size_t )(  p->fts_namelen + 1 ) );
           return (  sp->fts_cur = p );
           }
          
           /* Move up to the parent node. */
           p = tmp->fts_parent;
           fts_free(  tmp );
          
           if (  p->fts_level == FTS_ROOTPARENTLEVEL ) {
           /*
           * Done; free everything up and set errno to 0 so the user
           * can distinguish between error and EOF.
           */
           fts_free(  p );
           errno = 0;
           return (  sp->fts_cur = NULL );
           }
          
           /* Nul terminate the pathname. */
           sp->fts_path[p->fts_pathlen] = '\0';
          
           /*
           * Return to the parent directory. If at a root node or came through
           * a symlink,   go back through the file descriptor. Otherwise,   cd up
           * one directory.
           */
           if (  p->fts_level == FTS_ROOTLEVEL ) {
           if (  FCHDIR(  sp,   sp->fts_rfd ) ) {
           SET(  FTS_STOP );
           return (  NULL );
           }
           } else if (  p->fts_flags & FTS_SYMFOLLOW ) {
           if (  FCHDIR(  sp,   p->fts_symfd ) ) {
           saved_errno = errno;
           (  void )close(  p->fts_symfd );
           errno = saved_errno;
           SET(  FTS_STOP );
           return (  NULL );
           }
           (  void )close(  p->fts_symfd );
           } else if (  !(  p->fts_flags & FTS_DONTCHDIR ) &&
           fts_safe_changedir(  sp,   p->fts_parent,   -1,   ".." ) ) {
           SET(  FTS_STOP );
           return (  NULL );
           }
           p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
           return (  sp->fts_cur = p );
          }
          
          /*
           * Fts_set takes the stream as an argument although it's not used in this
           * implementation; it would be necessary if anyone wanted to add global
           * semantics to fts using fts_set. An error return is allowed for similar
     533   * reasons.
           */
          /* ARGSUSED */
          int
          fts_set(  FTS *sp,   FTSENT *p,   int instr )
          {
          
           _DIAGASSERT(  sp != NULL );
           _DIAGASSERT(  p != NULL );
          
           if (  instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
           instr != FTS_NOINSTR && instr != FTS_SKIP ) {
           errno = EINVAL;
           return (  1 );
           }
           p->fts_instr = instr;
     549   return (  0 );
          }
          
          FTSENT *
          fts_children(  FTS *sp,   int instr )
          {
           FTSENT *p;
           int fd;
          
           _DIAGASSERT(  sp != NULL );
          
           if (  instr && instr != FTS_NAMEONLY ) {
           errno = EINVAL;
           return (  NULL );
           }
          
           /* Set current node pointer. */
           p = sp->fts_cur;
          
           /*
           * Errno set to 0 so user can distinguish empty directory from
           * an error.
           */
           errno = 0;
          
           /* Fatal errors stop here. */
           if (  ISSET(  FTS_STOP ) )
           return (  NULL );
          
           /* Return logical hierarchy of user's arguments. */
           if (  p->fts_info == FTS_INIT )
           return (  p->fts_link );
          
           /*
           * If not a directory being visited in pre-order,   stop here. Could
           * allow FTS_DNR,   assuming the user has fixed the problem,   but the
           * same effect is available with FTS_AGAIN.
           */
           if (  p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */ )
           return (  NULL );
          
           /* Free up any previous child list. */
           if (  sp->fts_child )
           fts_lfree(  sp->fts_child );
          
           if (  instr == FTS_NAMEONLY ) {
           SET(  FTS_NAMEONLY );
           instr = BNAMES;
           } else
           instr = BCHILD;
          
           /*
           * If using chdir on a relative path and called BEFORE fts_read does
           * its chdir to the root of a traversal,   we can lose -- we need to
           * chdir into the subdirectory,   and we don't know where the current
           * directory is,   so we can't get back so that the upcoming chdir by
           * fts_read will work.
           */
           if (  p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
           ISSET(  FTS_NOCHDIR ) )
           return (  sp->fts_child = fts_build(  sp,   instr ) );
          
           if (  (  fd = open(  ".",   O_RDONLY,   0 ) ) == -1 )
           return (  sp->fts_child = NULL );
           sp->fts_child = fts_build(  sp,   instr );
           if (  fchdir(  fd ) ) {
           (  void )close(  fd );
           return (  NULL );
           }
           (  void )close(  fd );
           return (  sp->fts_child );
          }
          
          /*
           * This is the tricky part -- do not casually change *anything* in here. The
           * idea is to build the linked list of entries that are used by fts_children
           * and fts_read. There are lots of special cases.
           *
           * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is
           * set and it's a physical walk (  so that symbolic links can't be directories ),  
           * we can do things quickly. First,   if it's a 4.4BSD file system,   the type
           * of the file is in the directory entry. Otherwise,   we assume that the number
           * of subdirectories in a node is equal to the number of links to the parent.
           * The former skips all stat calls. The latter skips stat calls in any leaf
     633   * directories and for any files after the subdirectories in the directory have
           * been found,   cutting the stat calls by about 2/3.
           */
          static FTSENT *
          fts_build(  FTS *sp,   int type )
          {
           struct dirent *dp;
           FTSENT *p,   *head;
           size_t nitems;
           FTSENT *cur,   *tail;
           DIR *dirp;
           void *oldaddr;
           size_t dnamlen;
           int cderrno,   descend,   level,   nlinks,   saved_errno,   nostat,   doadjust;
           size_t len,   maxlen;
          #ifdef FTS_WHITEOUT
           int oflag;
          #endif
           char *cp = NULL; /* pacify gcc */
          
           _DIAGASSERT(  sp != NULL );
          
           /* Set current node pointer. */
           cur = sp->fts_cur;
          
           /*
           * Open the directory for reading. If this fails,   we're done.
           * If being called from fts_read,   set the fts_info field.
           */
          #ifdef FTS_WHITEOUT
           if (  ISSET(  FTS_WHITEOUT ) )
           oflag = DTF_NODUP|DTF_REWIND;
           else
           oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
          #else
          #define __opendir2(  path,   flag ) opendir(  path )
          #endif
           if (  (  dirp = __opendir2(  cur->fts_accpath,   oflag ) ) == NULL ) {
           if (  type == BREAD ) {
           cur->fts_info = FTS_DNR;
           cur->fts_errno = errno;
           }
           return (  NULL );
           }
          
           /*
           * Nlinks is the number of possible entries of type directory in the
           * directory if we're cheating on stat calls,   0 if we're not doing
           * any stat calls at all,   -1 if we're doing stats on everything.
           */
           if (  type == BNAMES ) {
           nlinks = 0;
           nostat = 1;
           } else if (  ISSET(  FTS_NOSTAT ) && ISSET(  FTS_PHYSICAL ) ) {
           nlinks = cur->fts_nlink - (  ISSET(  FTS_SEEDOT ) ? 0 : 2 );
           nostat = 1;
           } else {
           nlinks = -1;
           nostat = 0;
           }
          
          #ifdef notdef
           (  void )printf(  "nlinks == %d (  cur: %d )\n",   nlinks,   cur->fts_nlink );
           (  void )printf(  "NOSTAT %d PHYSICAL %d SEEDOT %d\n",  
           ISSET(  FTS_NOSTAT ),   ISSET(  FTS_PHYSICAL ),   ISSET(  FTS_SEEDOT ) );
          #endif
           /*
           * If we're going to need to stat anything or we want to descend
           * and stay in the directory,   chdir. If this fails we keep going,  
           * but set a flag so we don't chdir after the post-order visit.
           * We won't be able to stat anything,   but we can still return the
           * names themselves. Note,   that since fts_read won't be able to
           * chdir into the directory,   it will have to return different path
           * names than before,   i.e. "a/b" instead of "b". Since the node
           * has already been visited in pre-order,   have to wait until the
           * post-order visit to return the error. There is a special case
           * here,   if there was nothing to stat then it's not an error to
           * not be able to stat. This is all fairly nasty. If a program
           * needed sorted entries or stat information,   they had better be
           * checking FTS_NS on the returned nodes.
           */
           cderrno = 0;
           if (  nlinks || type == BREAD ) {
           if (  fts_safe_changedir(  sp,   cur,   dirfd(  dirp ),   NULL ) ) {
           if (  nlinks && type == BREAD )
           cur->fts_errno = errno;
           cur->fts_flags |= FTS_DONTCHDIR;
           descend = 0;
           cderrno = errno;
           } else
           descend = 1;
           } else
           descend = 0;
          
           /*
           * Figure out the max file name length that can be stored in the
           * current path -- the inner loop allocates more path as necessary.
           * We really wouldn't have to do the maxlen calculations here,   we
           * could do them in fts_read before returning the path,   but it's a
           * lot easier here since the length is part of the dirent structure.
           *
           * If not changing directories set a pointer so that can just append
           * each new name into the path.
           */
           len = NAPPEND(  cur );
           if (  ISSET(  FTS_NOCHDIR ) ) {
           cp = sp->fts_path + len;
           *cp++ = '/';
           }
           len++;
           maxlen = sp->fts_pathlen - len;
          
          #if defined(  __FTS_COMPAT_LEVEL )
           if (  cur->fts_level == SHRT_MAX ) {
           (  void )closedir(  dirp );
           cur->fts_info = FTS_ERR;
           SET(  FTS_STOP );
           errno = ENAMETOOLONG;
           return (  NULL );
           }
          #endif
          
           level = cur->fts_level + 1;
          
           /* Read the directory,   attaching each entry to the `link' pointer. */
           doadjust = 0;
           for (  head = tail = NULL,   nitems = 0; (  dp = readdir(  dirp ) ) != NULL; ) {
          
           if (  !ISSET(  FTS_SEEDOT ) && ISDOT(  dp->d_name ) )
           continue;
          
          #if defined(  HAVE_STRUCT_DIRENT_D_NAMLEN )
           dnamlen = dp->d_namlen;
          #else
           dnamlen = strlen(  dp->d_name );
          #endif
           if (  (  p = fts_alloc(  sp,   dp->d_name,   dnamlen ) ) == NULL )
           goto mem1;
           if (  dnamlen >= maxlen ) { /* include space for NUL */
           oldaddr = sp->fts_path;
           if (  fts_palloc(  sp,   dnamlen + len + 1 ) ) {
           /*
           * No more memory for path or structures. Save
           * errno,   free up the current structure and the
           * structures already allocated.
           */
          mem1: saved_errno = errno;
           if (  p )
           fts_free(  p );
           fts_lfree(  head );
           (  void )closedir(  dirp );
           errno = saved_errno;
           cur->fts_info = FTS_ERR;
           SET(  FTS_STOP );
           return (  NULL );
           }
           /* Did realloc(   ) change the pointer? */
           if (  oldaddr != sp->fts_path ) {
           doadjust = 1;
           if (  ISSET(  FTS_NOCHDIR ) )
           cp = sp->fts_path + len;
           }
           maxlen = sp->fts_pathlen - len;
           }
          
          #if defined(  __FTS_COMPAT_LENGTH )
           if (  len + dnamlen >= USHRT_MAX ) {
           /*
           * In an FTSENT,   fts_pathlen is an unsigned short
           * so it is possible to wraparound here.
           * If we do,   free up the current structure and the
           * structures already allocated,   then error out
           * with ENAMETOOLONG.
           */
           fts_free(  p );
           fts_lfree(  head );
           (  void )closedir(  dirp );
           cur->fts_info = FTS_ERR;
           SET(  FTS_STOP );
           errno = ENAMETOOLONG;
           return (  NULL );
           }
          #endif
           p->fts_level = level;
           p->fts_pathlen = len + dnamlen;
           p->fts_parent = sp->fts_cur;
          
          #ifdef FTS_WHITEOUT
           if (  dp->d_type == DT_WHT )
           p->fts_flags |= FTS_ISW;
          #endif
          
           if (  cderrno ) {
           if (  nlinks ) {
           p->fts_info = FTS_NS;
           p->fts_errno = cderrno;
           } /* else
           p->fts_info = FTS_NSOK;
           */
           /* Coverity Scan Id 1 says above is dead code */
           p->fts_accpath = cur->fts_accpath;
           } else if (  nlinks == 0
          #ifdef DT_DIR
           || (  nostat &&
           dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN )
          #endif
            ) {
           p->fts_accpath =
           ISSET(  FTS_NOCHDIR ) ? p->fts_path : p->fts_name;
           p->fts_info = FTS_NSOK;
           } else {
           /* Build a file name for fts_stat to stat. */
           if (  ISSET(  FTS_NOCHDIR ) ) {
           p->fts_accpath = p->fts_path;
           memmove(  cp,   p->fts_name,  
           (  size_t )(  p->fts_namelen + 1 ) );
           } else
           p->fts_accpath = p->fts_name;
           /* Stat it. */
           p->fts_info = fts_stat(  sp,   p,   0 );
          
           /* Decrement link count if applicable. */
           if (  nlinks > 0 && (  p->fts_info == FTS_D ||
           p->fts_info == FTS_DC || p->fts_info == FTS_DOT ) )
           --nlinks;
           }
          
           /* We walk in directory order so "ls -f" doesn't get upset. */
           p->fts_link = NULL;
           if (  head == NULL )
           head = tail = p;
           else {
           tail->fts_link = p;
           tail = p;
           }
           ++nitems;
           }
           (  void )closedir(  dirp );
          
           /*
           * If had to realloc the path,   adjust the addresses for the rest
           * of the tree.
           */
           if (  doadjust )
           fts_padjust(  sp,   head );
          
           /*
           * If not changing directories,   reset the path back to original
           * state.
           */
           if (  ISSET(  FTS_NOCHDIR ) ) {
           if (  len == sp->fts_pathlen || nitems == 0 )
           --cp;
           *cp = '\0';
           }
          
           /*
           * If descended after called from fts_children or after called from
           * fts_read and nothing found,   get back. At the root level we use
           * the saved fd; if one of fts_open(   )'s arguments is a relative path
           * to an empty directory,   we wind up here with no other way back. If
           * can't get back,   we're done.
           */
           if (  descend && (  type == BCHILD || !nitems ) &&
           (  cur->fts_level == FTS_ROOTLEVEL ?
           FCHDIR(  sp,   sp->fts_rfd ) :
           fts_safe_changedir(  sp,   cur->fts_parent,   -1,   ".." ) ) ) {
           cur->fts_info = FTS_ERR;
           SET(  FTS_STOP );
           return (  NULL );
           }
          
           /* If didn't find anything,   return NULL. */
           if (  !nitems ) {
           if (  type == BREAD )
           cur->fts_info = FTS_DP;
           return (  NULL );
           }
          
           /* Sort the entries. */
           if (  sp->fts_compar && nitems > 1 )
           head = fts_sort(  sp,   head,   nitems );
     915   return (  head );
          }
          
          static unsigned short
          fts_stat(  FTS *sp,   FTSENT *p,   int follow )
          {
           FTSENT *t;
           dev_t dev;
           __fts_ino_t ino;
           __fts_stat_t *sbp,   sb;
           int saved_errno;
          
           _DIAGASSERT(  sp != NULL );
           _DIAGASSERT(  p != NULL );
          
           /* If user needs stat info,   stat buffer already allocated. */
           sbp = ISSET(  FTS_NOSTAT ) ? &sb : p->fts_statp;
          
          #ifdef FTS_WHITEOUT
           /* check for whiteout */
           if (  p->fts_flags & FTS_ISW ) {
           if (  sbp != &sb ) {
           memset(  sbp,   '\0',   sizeof (  *sbp ) );
           sbp->st_mode = S_IFWHT;
           }
           return (  FTS_W );
           }
          #endif
          
           /*
           * If doing a logical walk,   or application requested FTS_FOLLOW,   do
           * a stat(  2 ). If that fails,   check for a non-existent symlink. If
           * fail,   set the errno from the stat call.
           */
           if (  ISSET(  FTS_LOGICAL ) || follow ) {
           if (  stat(  p->fts_accpath,   sbp ) ) {
           saved_errno = errno;
           if (  !lstat(  p->fts_accpath,   sbp ) ) {
           errno = 0;
           return (  FTS_SLNONE );
           }
           p->fts_errno = saved_errno;
           goto err;
           }
           } else if (  lstat(  p->fts_accpath,   sbp ) ) {
           p->fts_errno = errno;
          err: memset(  sbp,   0,   sizeof(  *sbp ) );
           return (  FTS_NS );
           }
          
           if (  S_ISDIR(  sbp->st_mode ) ) {
           /*
           * Set the device/inode. Used to find cycles and check for
           * crossing mount points. Also remember the link count,   used
           * in fts_build to limit the number of stat calls. It is
           * understood that these fields are only referenced if fts_info
           * is set to FTS_D.
           */
           dev = p->fts_dev = sbp->st_dev;
           ino = p->fts_ino = sbp->st_ino;
           p->fts_nlink = sbp->st_nlink;
          
           if (  ISDOT(  p->fts_name ) )
           return (  FTS_DOT );
          
           /*
           * Cycle detection is done by brute force when the directory
           * is first encountered. If the tree gets deep enough or the
           * number of symbolic links to directories is high enough,  
           * something faster might be worthwhile.
           */
           for (  t = p->fts_parent;
           t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent )
           if (  ino == t->fts_ino && dev == t->fts_dev ) {
           p->fts_cycle = t;
           return (  FTS_DC );
           }
           return (  FTS_D );
           }
           if (  S_ISLNK(  sbp->st_mode ) )
           return (  FTS_SL );
           if (  S_ISREG(  sbp->st_mode ) )
           return (  FTS_F );
     998   return (  FTS_DEFAULT );
          }
          
          static FTSENT *
          fts_sort(  FTS *sp,   FTSENT *head,   size_t nitems )
          {
           FTSENT **ap,   *p;
          
           _DIAGASSERT(  sp != NULL );
           _DIAGASSERT(  head != NULL );
          
           /*
           * Construct an array of pointers to the structures and call qsort(  3 ).
           * Reassemble the array in the order returned by qsort. If unable to
           * sort for memory reasons,   return the directory entries in their
           * current order. Allocate enough space for the current needs plus
           * 40 so don't realloc one entry at a time.
           */
           if (  nitems > sp->fts_nitems ) {
           FTSENT **new;
          
           new = realloc(  sp->fts_array,   sizeof(  FTSENT * ) * (  nitems + 40 ) );
           if (  new == 0 )
           return (  head );
           sp->fts_array = new;
           sp->fts_nitems = nitems + 40;
           }
           for (  ap = sp->fts_array,   p = head; p; p = p->fts_link )
           *ap++ = p;
           qsort(  (  void * )sp->fts_array,   nitems,   sizeof(  FTSENT * ),  
           (  int (  * )(  const void *,   const void * ) )sp->fts_compar );
           for (  head = *(  ap = sp->fts_array ); --nitems; ++ap )
           ap[0]->fts_link = ap[1];
           ap[0]->fts_link = NULL;
    1032   return (  head );
          }
          
          static FTSENT *
          fts_alloc(  FTS *sp,   const char *name,   size_t namelen )
          {
           FTSENT *p;
          #if defined(  FTS_ALLOC_ALIGNED )
           size_t len;
          #endif
          
           _DIAGASSERT(  sp != NULL );
           _DIAGASSERT(  name != NULL );
          
          #if defined(  FTS_ALLOC_ALIGNED )
           /*
           * The file name is a variable length array and no stat structure is
           * necessary if the user has set the nostat bit. Allocate the FTSENT
           * structure,   the file name and the stat structure in one chunk,   but
           * be careful that the stat structure is reasonably aligned. Since the
           * fts_name field is declared to be of size 1,   the fts_name pointer is
           * namelen + 2 before the first possible address of the stat structure.
           */
           len = sizeof(  FTSENT ) + namelen;
           if (  !ISSET(  FTS_NOSTAT ) )
           len += sizeof(  *(  p->fts_statp ) ) + ALIGNBYTES;
           if (  (  p = malloc(  len ) ) == NULL )
           return (  NULL );
          
           if (  !ISSET(  FTS_NOSTAT ) )
           p->fts_statp = (  __fts_stat_t * )ALIGN(  p->fts_name + namelen + 2 );
          #else
           if (  (  p = malloc(  sizeof(  FTSENT ) + namelen ) ) == NULL )
           return (  NULL );
          
           if (  !ISSET(  FTS_NOSTAT ) )
           if (  (  p->fts_statp = malloc(  sizeof(  *(  p->fts_statp ) ) ) ) == NULL ) {
           free(  p );
           return (  NULL );
           }
          #endif
          
           if (  ISSET(  FTS_NOSTAT ) )
           p->fts_statp = NULL;
          
           /* Copy the name plus the trailing NULL. */
           memmove(  p->fts_name,   name,   namelen + 1 );
          
           p->fts_namelen = namelen;
           p->fts_path = sp->fts_path;
           p->fts_errno = 0;
           p->fts_flags = 0;
           p->fts_instr = FTS_NOINSTR;
           p->fts_number = 0;
           p->fts_pointer = NULL;
    1087   return (  p );
          }
          
          static void
          fts_free(  FTSENT *p )
          {
          #if !defined(  FTS_ALLOC_ALIGNED )
           if (  p->fts_statp )
           free(  p->fts_statp );
          #endif
    1097   free(  p );
          }
          
          static void
          fts_lfree(  FTSENT *head )
          {
           FTSENT *p;
          
           /* XXX: head may be NULL ? */
          
           /* Free a linked list of structures. */
           while (  (  p = head ) != NULL ) {
           head = head->fts_link;
           fts_free(  p );
    1111   }
          }
          
          static size_t
          fts_pow2(  size_t x )
          {
          
           x--;
           x |= x>>1;
           x |= x>>2;
           x |= x>>4;
           x |= x>>8;
          #if (  SIZEOF_SIZE_T * CHAR_BIT ) > 16
           x |= x>>16;
          #endif
          #if (  SIZEOF_SIZE_T * CHAR_BIT ) > 32
           x |= x>>32;
          #endif
          #if (  SIZEOF_SIZE_T * CHAR_BIT ) > 64
           x |= x>>64;
          #endif
           x++;
           return (  x );
          }
          
          /*
           * Allow essentially unlimited paths; find,   rm,   ls should all work on any tree.
           * Most systems will allow creation of paths much longer than MAXPATHLEN,   even
    1139   * though the kernel won't resolve them. Round up the new size to a power of 2,  
           * so we don't realloc the path 2 bytes at a time.
           */
          static int
          fts_palloc(  FTS *sp,   size_t size )
          {
           char *new;
          
           _DIAGASSERT(  sp != NULL );
          
          #ifdef __FTS_COMPAT_LENGTH
           /* Protect against fts_pathlen overflow. */
           if (  size > USHRT_MAX + 1 ) {
           errno = ENAMETOOLONG;
           return (  1 );
           }
          #endif
           size = fts_pow2(  size );
           new = realloc(  sp->fts_path,   size );
           if (  new == 0 )
           return (  1 );
           sp->fts_path = new;
           sp->fts_pathlen = size;
           return (  0 );
          }
          
          /*
    1166   * When the path is realloc'd,   have to fix all of the pointers in structures
           * already returned.
           */
          static void
          fts_padjust(  FTS *sp,   FTSENT *head )
          {
           FTSENT *p;
           char *addr;
          
           _DIAGASSERT(  sp != NULL );
          
          #define ADJUST(  p ) do { \
           if (  (  p )->fts_accpath != (  p )->fts_name ) \
           (  p )->fts_accpath = \
           addr + (  (  p )->fts_accpath - (  p )->fts_path ); \
           (  p )->fts_path = addr; \
          } while (  /*CONSTCOND*/0 )
          
           addr = sp->fts_path;
          
           /* Adjust the current set of children. */
           for (  p = sp->fts_child; p; p = p->fts_link )
           ADJUST(  p );
    1189  
           /* Adjust the rest of the tree,   including the current level. */
           for (  p = head; p->fts_level >= FTS_ROOTLEVEL; ) {
           ADJUST(  p );
           p = p->fts_link ? p->fts_link : p->fts_parent;
           }
          }
          
          static size_t
          fts_maxarglen(  char * const *argv )
          {
           size_t len,   max;
          
           _DIAGASSERT(  argv != NULL );
          
           for (  max = 0; *argv; ++argv )
           if (  (  len = strlen(  *argv ) ) > max )
           max = len;
    1207   return (  max + 1 );
          }
          
          /*
           * Change to dir specified by fd or p->fts_accpath without getting
           * tricked by someone changing the world out from underneath us.
           * Assumes p->fts_dev and p->fts_ino are filled in.
           */
          static int
          fts_safe_changedir(  const FTS *sp,   const FTSENT *p,   int fd,   const char *path )
          {
           int oldfd = fd,   ret = -1;
           __fts_stat_t sb;
          
           if (  ISSET(  FTS_NOCHDIR ) )
           return 0;
          
           if (  oldfd < 0 && (  fd = open(  path,   O_RDONLY ) ) == -1 )
           return -1;
          
           if (  fstat(  fd,   &sb ) == -1 )
           goto bail;
          
           if (  sb.st_ino != p->fts_ino || sb.st_dev != p->fts_dev ) {
           errno = ENOENT;
           goto bail;
           }
          
           ret = fchdir(  fd );
          
          bail:
           if (  oldfd < 0 ) {
           int save_errno = errno;
           (  void )close(  fd );
           errno = save_errno;
           }
           return ret;
          }

libmisc/shell/hexdump-conv.c

       1  /*
           * Copyright (  c ) 1989,   1993
           * The Regents of the University of California. 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef lint
          static const char sccsid[] = "@(  # )conv.c 8.1 (  Berkeley ) 6/6/93";
          #endif /* not lint */
          #include <sys/cdefs.h>
      42  __FBSDID(  "$FreeBSD: src/usr.bin/hexdump/conv.c,  v 1.9 2006/07/31 14:17:04 jkoshy Exp $" );
          
          #include <sys/types.h>
          
          #include <assert.h>
          #include <ctype.h>
          #include <limits.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <wchar.h>
          #include <wctype.h>
          #include "hexdump.h"
          
          void
      57  conv_c(  rtems_shell_hexdump_globals* globals,   PR *pr,   u_char *p,   size_t bufsize )
          {
           char buf[10];
           char const *str;
           wchar_t wc;
           size_t clen,   oclen;
           int converr,   pad,   width;
           char peekbuf[MB_LEN_MAX];
          
           printf(  "MB_LEN_MAX=%i\n",   MB_LEN_MAX );
           return;
           if (  pr->mbleft > 0 ) {
           str = "**";
           pr->mbleft--;
           goto strpr;
           }
          
           switch(  *p ) {
           case '\0':
           str = "\\0";
           goto strpr;
           /* case '\a': */
           case '\007':
           str = "\\a";
           goto strpr;
           case '\b':
           str = "\\b";
           goto strpr;
           case '\f':
           str = "\\f";
           goto strpr;
           case '\n':
           str = "\\n";
           goto strpr;
           case '\r':
           str = "\\r";
           goto strpr;
           case '\t':
           str = "\\t";
           goto strpr;
           case '\v':
           str = "\\v";
           goto strpr;
           default:
           break;
           }
           /*
           * Multibyte characters are disabled for hexdump(  1 ) for backwards
           * compatibility and consistency (  none of its other output formats
           * recognize them correctly ).
           */
           converr = 0;
           if (  odmode && MB_CUR_MAX > 1 ) {
           oclen = 0;
          retry:
           clen = mbrtowc(  &wc,   (  char* )p,   bufsize,   &pr->mbstate );
           if (  clen == 0 )
           clen = 1;
           else if (  clen == (  size_t )-1 || (  clen == (  size_t )-2 &&
           buf == peekbuf ) ) {
           memset(  &pr->mbstate,   0,   sizeof(  pr->mbstate ) );
           wc = *p;
           clen = 1;
           converr = 1;
           } else if (  clen == (  size_t )-2 ) {
           /*
           * Incomplete character; peek ahead and see if we
           * can complete it.
           */
           oclen = bufsize;
           bufsize = peek(  globals,   p = (  u_char* )peekbuf,   MB_CUR_MAX );
           goto retry;
           }
           clen += oclen;
           } else {
           wc = *p;
           clen = 1;
           }
           if (  !converr && iswprint(  wc ) ) {
           if (  !odmode ) {
           *pr->cchar = 'c';
           (  void )printf(  pr->fmt,   (  int )wc );
           } else {
           *pr->cchar = 'C';
           assert(  strcmp(  pr->fmt,   "%3C" ) == 0 );
           width = wcwidth(  wc );
           assert(  width >= 0 );
           pad = 3 - width;
           if (  pad < 0 )
           pad = 0;
           (  void )printf(  "%*s%lc",   pad,   "",   wc );
           pr->mbleft = clen - 1;
           }
           } else {
           (  void )sprintf(  buf,   "%03o",   (  int )*p );
           str = buf;
          strpr: *pr->cchar = 's';
           (  void )printf(  pr->fmt,   str );
           }
          }
          
          void
     159  conv_u(  rtems_shell_hexdump_globals* globals,   PR *pr,   u_char *p )
          {
           static char const * list[] = {
           "nul",   "soh",   "stx",   "etx",   "eot",   "enq",   "ack",   "bel",  
           "bs",   "ht",   "lf",   "vt",   "ff",   "cr",   "so",   "si",  
           "dle",   "dcl",   "dc2",   "dc3",   "dc4",   "nak",   "syn",   "etb",  
           "can",   "em",   "sub",   "esc",   "fs",   "gs",   "rs",   "us",  
           };
          
           /* od used nl,   not lf */
           if (  *p <= 0x1f ) {
           *pr->cchar = 's';
           if (  odmode && *p == 0x0a )
           (  void )printf(  pr->fmt,   "nl" );
           else
           (  void )printf(  pr->fmt,   list[*p] );
           } else if (  *p == 0x7f ) {
           *pr->cchar = 's';
           (  void )printf(  pr->fmt,   "del" );
           } else if (  odmode && *p == 0x20 ) { /* od replaced space with sp */
           *pr->cchar = 's';
           (  void )printf(  pr->fmt,   " sp" );
           } else if (  isprint(  *p ) ) {
           *pr->cchar = 'c';
           (  void )printf(  pr->fmt,   *p );
           } else {
           *pr->cchar = 'x';
           (  void )printf(  pr->fmt,   (  int )*p );
           }
          }

libmisc/shell/hexdump-display.c

          /*
           * Copyright (  c ) 1989,   1993
           * The Regents of the University of California. 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )display.c 8.1 (  Berkeley ) 6/6/93";
          #endif
          #endif /* not lint */
          #if 0
          #include <sys/cdefs.h>
      45  __FBSDID(  "$FreeBSD: src/usr.bin/hexdump/display.c,  v 1.22 2004/08/04 02:47:32 tjr Exp $" );
          #endif
          
          #include <sys/param.h>
          #include <sys/stat.h>
          
          #include <stdint.h>
          
          #include <ctype.h>
          #include <err.h>
          #include <errno.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #ifdef HAVE_STRINGS_H
          #include <strings.h>
          #endif
          #include <unistd.h>
          #include "hexdump.h"
          
          #if RTEMS_REMOVED
          enum _vflag vflag = FIRST;
          
          static off_t address; /* address/offset in stream */
          static off_t eaddress; /* end address */
          #endif
          
          static void print(  rtems_shell_hexdump_globals*,   PR *,   u_char * );
          
          void
          display(  rtems_shell_hexdump_globals* globals )
          {
           FS *fs;
           FU *fu;
           PR *pr;
           int cnt;
           u_char *bp;
           off_t saveaddress;
           u_char savech,   *savebp;
          
           savech = 0;
           while (  (  bp = get(  globals ) ) )
           for (  fs = fshead,   savebp = bp,   saveaddress = address; fs;
           fs = fs->nextfs,   bp = savebp,   address = saveaddress )
           for (  fu = fs->nextfu; fu; fu = fu->nextfu ) {
           if (  fu->flags&F_IGNORE )
           break;
           for (  cnt = fu->reps; cnt; --cnt )
           for (  pr = fu->nextpr; pr; address += pr->bcnt,  
           bp += pr->bcnt,   pr = pr->nextpr ) {
           if (  eaddress && address >= eaddress &&
           !(  pr->flags & (  F_TEXT|F_BPAD ) ) )
           bpad(  pr );
           if (  cnt == 1 && pr->nospace ) {
           savech = *pr->nospace;
           *pr->nospace = '\0';
           }
           print(  globals,   pr,   bp );
           if (  cnt == 1 && pr->nospace )
           *pr->nospace = savech;
           }
           }
           if (  endfu ) {
           /*
           * If eaddress not set,   error or file size was multiple of
           * blocksize,   and no partial block ever found.
           */
           if (  !eaddress ) {
           if (  !address )
           return;
           eaddress = address;
           }
           for (  pr = endfu->nextpr; pr; pr = pr->nextpr )
           switch(  pr->flags ) {
           case F_ADDRESS:
           (  void )printf(  pr->fmt,   (  quad_t )eaddress );
           break;
           case F_TEXT:
           (  void )printf(  "%s",   pr->fmt );
           break;
           }
           }
          }
          
          static void
          print(  rtems_shell_hexdump_globals* globals,   PR *pr,   u_char *bp )
          {
           long double ldbl;
           double f8;
           float f4;
           int16_t s2;
           int8_t s8;
           int32_t s4;
           u_int16_t u2;
           u_int32_t u4;
           u_int64_t u8;
          
           switch(  pr->flags ) {
           case F_ADDRESS:
           (  void )printf(  pr->fmt,   (  quad_t )address );
           break;
           case F_BPAD:
           (  void )printf(  pr->fmt,   "" );
           break;
           case F_C:
           conv_c(  globals,   pr,   bp,   eaddress ? eaddress - address :
           blocksize - address % blocksize );
           break;
           case F_CHAR:
           (  void )printf(  pr->fmt,   *bp );
           break;
           case F_DBL:
           switch(  pr->bcnt ) {
           case 4:
           bcopy(  bp,   &f4,   sizeof(  f4 ) );
           (  void )printf(  pr->fmt,   f4 );
           break;
           case 8:
           bcopy(  bp,   &f8,   sizeof(  f8 ) );
           (  void )printf(  pr->fmt,   f8 );
           break;
           default:
           if (  pr->bcnt == sizeof(  long double ) ) {
           bcopy(  bp,   &ldbl,   sizeof(  ldbl ) );
           (  void )printf(  pr->fmt,   ldbl );
           }
           break;
           }
           break;
           case F_INT:
           switch(  pr->bcnt ) {
           case 1:
           (  void )printf(  pr->fmt,   (  quad_t )(  signed char )*bp );
           break;
           case 2:
           bcopy(  bp,   &s2,   sizeof(  s2 ) );
           (  void )printf(  pr->fmt,   (  quad_t )s2 );
           break;
           case 4:
           bcopy(  bp,   &s4,   sizeof(  s4 ) );
           (  void )printf(  pr->fmt,   (  quad_t )s4 );
           break;
           case 8:
           bcopy(  bp,   &s8,   sizeof(  s8 ) );
           (  void )printf(  pr->fmt,   s8 );
           break;
           }
           break;
           case F_P:
           (  void )printf(  pr->fmt,   isprint(  *bp ) ? *bp : '.' );
           break;
           case F_STR:
           (  void )printf(  pr->fmt,   (  char * )bp );
           break;
           case F_TEXT:
           (  void )printf(  "%s",   pr->fmt );
           break;
           case F_U:
           conv_u(  globals,   pr,   bp );
           break;
           case F_UINT:
           switch(  pr->bcnt ) {
           case 1:
           (  void )printf(  pr->fmt,   (  u_quad_t )*bp );
           break;
           case 2:
           bcopy(  bp,   &u2,   sizeof(  u2 ) );
           (  void )printf(  pr->fmt,   (  u_quad_t )u2 );
           break;
           case 4:
           bcopy(  bp,   &u4,   sizeof(  u4 ) );
           (  void )printf(  pr->fmt,   (  u_quad_t )u4 );
           break;
           case 8:
           bcopy(  bp,   &u8,   sizeof(  u8 ) );
           (  void )printf(  pr->fmt,   u8 );
           break;
           }
           break;
           }
          }
          
          void
          bpad(  PR *pr )
          {
           static char const *spec = " -0+#";
           char *p1,   *p2;
          
           /*
           * Remove all conversion flags; '-' is the only one valid
           * with %s,   and it's not useful here.
           */
           pr->flags = F_BPAD;
           pr->cchar[0] = 's';
           pr->cchar[1] = '\0';
           for (  p1 = pr->fmt; *p1 != '%'; ++p1 );
           for (  p2 = ++p1; *p1 && index(  spec,   *p1 ); ++p1 );
           while (  (  *p2++ = *p1++ ) );
          }
          
          static char **_argv;
          
          u_char *
          get(  rtems_shell_hexdump_globals* globals )
          {
          #if RTEMS_REMOVED
           static int ateof = 1;
           static u_char *curp,   *savp;
          #endif
           int n;
           int need,   nread;
           int valid_save = 0;
           u_char *tmpp;
          
           if (  !curp ) {
           if (  (  curp = calloc(  1,   blocksize ) ) == NULL )
           err(  exit_jump,   1,   NULL );
           if (  (  savp = calloc(  1,   blocksize ) ) == NULL )
           err(  exit_jump,   1,   NULL );
           } else {
           tmpp = curp;
           curp = savp;
           savp = tmpp;
           address += blocksize;
           valid_save = 1;
           }
           for (  need = blocksize,   nread = 0;; ) {
           /*
           * if read the right number of bytes,   or at EOF for one file,  
           * and no other files are available,   zero-pad the rest of the
           * block and set the end flag.
           */
           if (  !length || (  ateof && !next(  globals,   (  char ** )NULL ) ) ) {
           if (  odmode && address < skip )
           errx(  exit_jump,   1,   "cannot skip past end of input" );
           if (  need == blocksize )
           return(  (  u_char * )NULL );
           /*
           * XXX bcmp(   ) is not quite right in the presence
           * of multibyte characters.
           */
           if (  vflag != ALL &&
           valid_save &&
           bcmp(  curp,   savp,   nread ) == 0 ) {
           if (  vflag != DUP )
           (  void )printf(  "*\n" );
           return(  (  u_char * )NULL );
           }
           bzero(  (  char * )curp + nread,   need );
           eaddress = address + nread;
           return(  curp );
           }
           n = fread(  (  char * )curp + nread,   sizeof(  u_char ),  
           length == -1 ? need : MIN(  length,   need ),   hdstdin );
           if (  !n ) {
           if (  ferror(  hdstdin ) )
           warn(  "%s",   _argv[-1] );
           ateof = 1;
           continue;
           }
           ateof = 0;
           if (  length != -1 )
           length -= n;
           if (  !(  need -= n ) ) {
           /*
           * XXX bcmp(   ) is not quite right in the presence
           * of multibyte characters.
           */
           if (  vflag == ALL || vflag == FIRST ||
           valid_save == 0 ||
           bcmp(  curp,   savp,   blocksize ) != 0 ) {
           if (  vflag == DUP || vflag == FIRST )
           vflag = WAIT;
           return(  curp );
           }
           if (  vflag == WAIT )
           (  void )printf(  "*\n" );
           vflag = DUP;
           address += blocksize;
           need = blocksize;
           nread = 0;
           }
           else
           nread += n;
           }
          }
          
          size_t
          peek(  rtems_shell_hexdump_globals* globals,   u_char *buf,   size_t nbytes )
          {
           size_t n,   nread;
           int c;
          
           if (  length != -1 && nbytes > (  unsigned int )length )
           nbytes = length;
           nread = 0;
           while (  nread < nbytes && (  c = getchar(   ) ) != EOF ) {
           *buf++ = c;
           nread++;
           }
           n = nread;
           while (  n-- > 0 ) {
           c = *--buf;
           ungetc(  c,   hdstdin );
           }
           return (  nread );
          }
          
          int
          next(  rtems_shell_hexdump_globals* globals,   char **argv )
          {
          #if RTEMS_REMOVED
           static int done;
          #endif
           int statok;
          
           if (  argv ) {
           _argv = argv;
           return(  1 );
           }
           for (  ;; ) {
           if (  *_argv ) {
           done = 1;
           if (  !hdstdin ) {
           hdstdin = malloc(  sizeof(  FILE ) );
           if (  !hdstdin )
           {
           errno = ENOMEM;
           err(  exit_jump,   1,   "file name allocation" );
           }
           memset (  hdstdin,   0,   sizeof(  FILE ) );
           }
           if (  !(  hdstdin = freopen(  *_argv,   "r",   hdstdin ) ) ) {
           warn(  "%s",   *_argv );
           exitval = 1;
           ++_argv;
           continue;
           }
           statok = 1;
           } else {
           errno = ECANCELED;
           err(  exit_jump,   1,   "no file (  stdin no supported )" );
           if (  done++ )
           return(  0 );
           statok = 0;
           }
           if (  skip )
           doskip(  globals,   statok ? *_argv : "stdin",   statok );
           if (  *_argv )
           ++_argv;
           if (  !skip )
           return(  1 );
           }
           /* NOTREACHED */
          }
          
          void
          doskip(  rtems_shell_hexdump_globals* globals,   const char *fname,   int statok )
          {
           int cnt;
           struct stat sb;
          
           if (  statok ) {
           if (  fstat(  fileno(  hdstdin ),   &sb ) )
           err(  exit_jump,   1,   "%s",   fname );
           /* can seek block devices on RTEMS */
           if (  0 && S_ISREG(  sb.st_mode ) && skip >= sb.st_size ) {
           address += sb.st_size;
           skip -= sb.st_size;
           return;
           }
           if (  1 || S_ISREG(  sb.st_mode ) ) {
           if (  fseeko(  hdstdin,   skip,   SEEK_SET ) )
           err(  exit_jump,   1,   "%s",   fname );
           address += skip;
           skip = 0;
           } else {
           for (  cnt = 0; cnt < skip; ++cnt )
           if (  getchar(   ) == EOF )
           break;
           address += cnt;
           skip -= cnt;
           }
           }
          }

libmisc/shell/hexdump-odsyntax.c

       1  /*-
           * Copyright (  c ) 1990,   1993
           * The Regents of the University of California. 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )odsyntax.c 8.2 (  Berkeley ) 5/4/95";
          #endif /* not lint */
          #include <sys/cdefs.h>
      43  __FBSDID(  "$FreeBSD: src/usr.bin/hexdump/odsyntax.c,  v 1.17 2004/07/22 13:14:42 johan Exp $" );
          #endif
          
          #include <sys/types.h>
          
          #include <ctype.h>
          #include <err.h>
          #include <errno.h>
          #include <float.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          
          #include "hexdump.h"
          
          #define __need_getopt_newlib
          #include <getopt.h>
          
          #define PADDING " "
          
          #if RTEMS_REMOVED
          int odmode;
          #endif
          
      68  static void odadd(  rtems_shell_hexdump_globals*,   const char * );
      69  static void odformat(  rtems_shell_hexdump_globals*,   const char * );
      70  static const char *odformatfp(  rtems_shell_hexdump_globals*,   char,   const char * );
      71  static const char *odformatint(  rtems_shell_hexdump_globals*,   char,   const char * );
      72  static void odoffset(  rtems_shell_hexdump_globals*,   int,   char *** );
      73  static void odusage(  rtems_shell_hexdump_globals* );
          
          void
      76  oldsyntax(  rtems_shell_hexdump_globals* globals,   int argc,   char ***argvp )
          {
           static char empty[] = "",   padding[] = PADDING;
           int ch;
           char **argv,   *end;
          
           struct getopt_data getopt_reent;
           memset(  &getopt_reent,   0,   sizeof(  getopt_data ) );
          
           /* Add initial (  default ) address format. -A may change it later. */
          #define TYPE_OFFSET 7
           add(  globals,   "\"%07.7_Ao\n\"" );
           add(  globals,   "\"%07.7_ao \"" );
          
           odmode = 1;
           argv = *argvp;
           while (  (  ch = getopt_r(  argc,   argv,   "A:aBbcDdeFfHhIij:LlN:Oost:vXx",   &getopt_reent ) ) != -1 )
           switch (  ch ) {
           case 'A':
           switch (  *optarg ) {
           case 'd': case 'o': case 'x':
           fshead->nextfu->fmt[TYPE_OFFSET] = *optarg;
           fshead->nextfs->nextfu->fmt[TYPE_OFFSET] =
           *optarg;
           break;
           case 'n':
           fshead->nextfu->fmt = empty;
           fshead->nextfs->nextfu->fmt = padding;
           break;
           default:
           errx(  exit_jump,   1,   "%s: invalid address base",   optarg );
           }
           break;
           case 'a':
           odformat(  globals,   "a" );
           break;
           case 'B':
           case 'o':
           odformat(  globals,   "o2" );
           break;
           case 'b':
           odformat(  globals,   "o1" );
           break;
           case 'c':
           odformat(  globals,   "c" );
           break;
           case 'd':
           odformat(  globals,   "u2" );
           break;
           case 'D':
           odformat(  globals,   "u4" );
           break;
           case 'e': /* undocumented in od */
           case 'F':
           odformat(  globals,   "fD" );
           break;
           case 'f':
           odformat(  globals,   "fF" );
           break;
           case 'H':
           case 'X':
           odformat(  globals,   "x4" );
           break;
           case 'h':
           case 'x':
           odformat(  globals,   "x2" );
           break;
           case 'I':
           case 'L':
           case 'l':
           odformat(  globals,   "dL" );
           break;
           case 'i':
           odformat(  globals,   "dI" );
           break;
           case 'j':
           errno = 0;
           skip = strtoll(  optarg,   &end,   0 );
           if (  *end == 'b' )
           skip *= 512;
           else if (  *end == 'k' )
           skip *= 1024;
           else if (  *end == 'm' )
           skip *= 1048576L;
           if (  errno != 0 || skip < 0 || strlen(  end ) > 1 )
           errx(  exit_jump,   1,   "%s: invalid skip amount",   optarg );
           break;
           case 'N':
           if (  (  length = atoi(  optarg ) ) <= 0 )
           errx(  exit_jump,   1,   "%s: invalid length",   optarg );
           break;
           case 'O':
           odformat(  globals,   "o4" );
           break;
           case 's':
           odformat(  globals,   "d2" );
           break;
           case 't':
           odformat(  globals,   optarg );
           break;
           case 'v':
           vflag = ALL;
           break;
           case '?':
           default:
           odusage(  globals );
           }
          
           if (  fshead->nextfs->nextfs == NULL )
           odformat(  globals,   "oS" );
          
           argc -= getopt_reent.optind;
           *argvp += getopt_reent.optind;
          
           if (  argc )
           odoffset(  globals,   argc,   argvp );
          }
          
          static void
     195  odusage(  rtems_shell_hexdump_globals* globals )
          {
          
           fprintf(  stderr,  
          "usage: od [-aBbcDdeFfHhIiLlOosvXx] [-A base] [-j skip] [-N length] [-t type]\n" );
           fprintf(  stderr,  
          " [[+]offset[.][Bb]] [file ...]\n" );
           exit(  1 );
          }
          
          static void
     206  odoffset(  rtems_shell_hexdump_globals* globals,   int argc,   char ***argvp )
          {
           char *p,   *num,   *end;
           int base;
          
           /*
           * The offset syntax of od(  1 ) was genuinely bizarre. First,   if
           * it started with a plus it had to be an offset. Otherwise,   if
           * there were at least two arguments,   a number or lower-case 'x'
           * followed by a number makes it an offset. By default it was
           * octal; if it started with 'x' or '0x' it was hex. If it ended
           * in a '.',   it was decimal. If a 'b' or 'B' was appended,   it
           * multiplied the number by 512 or 1024 byte units. There was
           * no way to assign a block count to a hex offset.
           *
           * We assume it's a file if the offset is bad.
           */
           p = argc == 1 ? (  *argvp )[0] : (  *argvp )[1];
          
           if (  *p != '+' && (  argc < 2 ||
           (  !isdigit(  (  unsigned char )p[0] ) && (  p[0] != 'x' || !isxdigit(  (  unsigned char )p[1] ) ) ) ) )
           return;
          
           base = 0;
           /*
           * skip over leading '+',   'x[0-9a-fA-f]' or '0x',   and
           * set base.
           */
           if (  p[0] == '+' )
           ++p;
           if (  p[0] == 'x' && isxdigit(  (  unsigned char )p[1] ) ) {
           ++p;
           base = 16;
           } else if (  p[0] == '0' && p[1] == 'x' ) {
           p += 2;
           base = 16;
           }
          
           /* skip over the number */
           if (  base == 16 )
           for (  num = p; isxdigit(  (  unsigned char )*p ); ++p );
           else
           for (  num = p; isdigit(  (  unsigned char )*p ); ++p );
          
           /* check for no number */
           if (  num == p )
           return;
          
           /* if terminates with a '.',   base is decimal */
           if (  *p == '.' ) {
           if (  base )
           return;
           base = 10;
           }
          
           skip = strtoll(  num,   &end,   base ? base : 8 );
          
           /* if end isn't the same as p,   we got a non-octal digit */
           if (  end != p ) {
           skip = 0;
           return;
           }
          
           if (  *p ) {
           if (  *p == 'B' ) {
           skip *= 1024;
           ++p;
           } else if (  *p == 'b' ) {
           skip *= 512;
           ++p;
           }
           }
          
           if (  *p ) {
           skip = 0;
           return;
           }
          
           /*
           * If the offset uses a non-octal base,   the base of the offset
           * is changed as well. This isn't pretty,   but it's easy.
           */
           if (  base == 16 ) {
           fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
           fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
           } else if (  base == 10 ) {
           fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
           fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
           }
          
           /* Terminate file list. */
           (  *argvp )[1] = NULL;
          }
          
          static void
     301  odformat(  rtems_shell_hexdump_globals* globals,   const char *fmt )
          {
           char fchar;
          
           while (  *fmt != '\0' ) {
           switch (  (  fchar = *fmt++ ) ) {
           case 'a':
           odadd(  globals,   "16/1 \"%3_u \" \"\\n\"" );
           break;
           case 'c':
           odadd(  globals,   "16/1 \"%3_c \" \"\\n\"" );
           break;
           case 'o': case 'u': case 'd': case 'x':
           fmt = odformatint(  globals,   fchar,   fmt );
           break;
           case 'f':
           fmt = odformatfp(  globals,   fchar,   fmt );
           break;
           default:
           errx(  exit_jump,   1,   "%c: unrecognised format character",   fchar );
           }
           }
          }
          #define __unused
          
          static const char *
     327  odformatfp(  rtems_shell_hexdump_globals* globals,   char fchar __unused,   const char *fmt )
          {
           size_t isize;
           int digits;
           char *end,   *hdfmt;
          
           isize = sizeof(  double );
           switch (  *fmt ) {
           case 'F':
           isize = sizeof(  float );
           fmt++;
           break;
           case 'D':
           isize = sizeof(  double );
           fmt++;
           break;
           case 'L':
           isize = sizeof(  long double );
           fmt++;
           break;
           default:
           if (  isdigit(  (  unsigned char )*fmt ) ) {
           errno = 0;
           isize = (  size_t )strtoul(  fmt,   &end,   10 );
           if (  errno != 0 || isize == 0 )
           errx(  exit_jump,   1,   "%s: invalid size",   fmt );
           fmt = (  const char * )end;
           }
           }
           if (  isize == sizeof(  float )  ) {
           digits = FLT_DIG;
           } else if (  isize == sizeof(  double ) ) {
           digits = DBL_DIG;
           } else if (  isize == sizeof(  long double ) ) {
           digits = LDBL_DIG;
           } else {
           errx(  exit_jump,   1,   "unsupported floating point size %zu",  
           isize );
           }
          
           asprintf(  &hdfmt,   "%lu/%lu \" %%%d.%de \" \"\\n\"",  
           16UL / (  u_long )isize,   (  u_long )isize,   digits + 8,   digits );
           if (  hdfmt == NULL )
           err(  exit_jump,   1,   NULL );
           odadd(  globals,   hdfmt );
           free(  hdfmt );
          
           return (  fmt );
          }
          
          static const char *
     378  odformatint(  rtems_shell_hexdump_globals* globals,   char fchar,   const char *fmt )
          {
           unsigned long long n;
           size_t isize;
           int digits;
           char *end,   *hdfmt;
          
           isize = sizeof(  int );
           switch (  *fmt ) {
           case 'C':
           isize = sizeof(  char );
           fmt++;
           break;
           case 'I':
           isize = sizeof(  int );
           fmt++;
           break;
           case 'L':
           isize = sizeof(  long );
           fmt++;
           break;
           case 'S':
           isize = sizeof(  short );
           fmt++;
           break;
           default:
           if (  isdigit(  (  unsigned char )*fmt ) ) {
           errno = 0;
           isize = (  size_t )strtoul(  fmt,   &end,   10 );
           if (  errno != 0 || isize == 0 )
           errx(  exit_jump,   1,   "%s: invalid size",   fmt );
           if (  isize != sizeof(  char ) && isize != sizeof(  short ) &&
           isize != sizeof(  int ) && isize != sizeof(  long ) )
           errx(  exit_jump,   1,   "unsupported int size %lu",  
           (  u_long )isize );
           fmt = (  const char * )end;
           }
           }
          
           /*
           * Calculate the maximum number of digits we need to
           * fit the number. Overestimate for decimal with log
           * base 8. We need one extra space for signed numbers
           * to store the sign.
           */
           n = (  1ULL << (  8 * isize ) ) - 1;
           digits = 0;
           while (  n != 0 ) {
           digits++;
           n >>= (  fchar == 'x' ) ? 4 : 3;
           }
           if (  fchar == 'd' )
           digits++;
           asprintf(  &hdfmt,   "%lu/%lu \"%*s%%%s%d%c\" \"\\n\"",  
           16UL / (  u_long )isize,   (  u_long )isize,   (  int )(  4 * isize - digits ),  
           "",   (  fchar == 'd' || fchar == 'u' ) ? "" : "0",   digits,   fchar );
           if (  hdfmt == NULL )
           err(  exit_jump,   1,   NULL );
           odadd(  globals,   hdfmt );
           free(  hdfmt );
          
           return (  fmt );
          }
          
          static void
     443  odadd(  rtems_shell_hexdump_globals* globals,   const char *fmt )
          {
           static int needpad;
          
           if (  needpad )
           add(  globals,   "\""PADDING"\"" );
           add(  globals,   fmt );
           needpad = 1;
          }

libmisc/shell/hexdump-parse.c

       1  /*
           * Copyright (  c ) 1989,   1993
           * The Regents of the University of California. 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )parse.c 8.1 (  Berkeley ) 6/6/93";
          #include <sys/cdefs.h>
      42  __FBSDID(  "$FreeBSD: src/usr.bin/hexdump/parse.c,  v 1.14 2006/08/09 19:12:10 maxim Exp $" );
          #endif
          #endif /* not lint */
          
          #include <sys/types.h>
          
          #include <err.h>
          #include <fcntl.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <ctype.h>
          #include <string.h>
          #ifdef HAVE_STRINGS_H
          #include <strings.h>
          #endif
          
          #include "hexdump.h"
          
          #if RTEMS_REMOVED
          FU *endfu; /* format at end-of-data */
          #endif
          
          void
      65  addfile(  rtems_shell_hexdump_globals* globals,   char *name )
          {
           unsigned char *p;
           FILE *fp;
           int ch;
           char buf[2048 + 1];
          
           if (  (  fp = fopen(  name,   "r" ) ) == NULL )
           err(  exit_jump,   1,   "%s",   name );
           while (  fgets(  buf,   sizeof(  buf ),   fp ) ) {
           if (  !(  p = (  unsigned char* )index(  buf,   '\n' ) ) ) {
           warnx(  "line too long" );
           while (  (  ch = getchar(   ) ) != '\n' && ch != EOF );
           continue;
           }
           *p = '\0';
           for (  p = (  unsigned char* ) buf; *p && isspace(  *p ); ++p );
           if (  !*p || *p == '#' )
           continue;
           add(  globals,   (  char* )p );
           }
           (  void )fclose(  fp );
          }
          
          void
      90  add(  rtems_shell_hexdump_globals* globals,   const char *fmt )
          {
           unsigned const char *p,   *savep;
           static FS **nextfs;
           FS *tfs;
           FU *tfu,   **nextfu;
          
           /* start new linked list of format units */
           if (  (  tfs = calloc(  1,   sizeof(  FS ) ) ) == NULL )
           err(  exit_jump,   1,   NULL );
           if (  !fshead )
           fshead = tfs;
           else
           *nextfs = tfs;
           nextfs = &tfs->nextfs;
           nextfu = &tfs->nextfu;
          
           /* take the format string and break it up into format units */
           for (  p = (  unsigned const char* )fmt;; ) {
           /* skip leading white space */
           for (  ; isspace(  *p ); ++p );
           if (  !*p )
           break;
          
           /* allocate a new format unit and link it in */
           if (  (  tfu = calloc(  1,   sizeof(  FU ) ) ) == NULL )
           err(  exit_jump,   1,   NULL );
           *nextfu = tfu;
           nextfu = &tfu->nextfu;
           tfu->reps = 1;
          
           /* if leading digit,   repetition count */
           if (  isdigit(  *p ) ) {
           for (  savep = p; isdigit(  *p ); ++p );
           if (  !isspace(  *p ) && *p != '/' )
           badfmt(  globals,   fmt );
           /* may overwrite either white space or slash */
           tfu->reps = atoi(  (  char* )savep );
           tfu->flags = F_SETREP;
           /* skip trailing white space */
           for (  ++p; isspace(  *p ); ++p );
           }
          
           /* skip slash and trailing white space */
           if (  *p == '/' )
           while (  isspace(  *++p ) );
          
           /* byte count */
           if (  isdigit(  *p ) ) {
           for (  savep = p; isdigit(  *p ); ++p );
           if (  !isspace(  *p ) )
           badfmt(  globals,   fmt );
           tfu->bcnt = atoi(  (  char* )savep );
           /* skip trailing white space */
           for (  ++p; isspace(  *p ); ++p );
           }
          
           /* format */
           if (  *p != '"' )
           badfmt(  globals,   fmt );
           for (  savep = ++p; *p != '"'; )
           if (  *p++ == 0 )
           badfmt(  globals,   fmt );
           if (  !(  tfu->fmt = malloc(  p - savep + 1 ) ) )
           err(  exit_jump,   1,   NULL );
           (  void ) strncpy(  tfu->fmt,   (  char* )savep,   p - savep );
           tfu->fmt[p - savep] = '\0';
           escape(  tfu->fmt );
           p++;
           }
          }
          
          static const char *spec = ".#-+ 0123456789";
          
          int
     165  size(  rtems_shell_hexdump_globals* globals,   FS *fs )
          {
           FU *fu;
           int bcnt,   cursize;
           unsigned char *fmt;
           int prec;
          
           /* figure out the data block size needed for each format unit */
           for (  cursize = 0,   fu = fs->nextfu; fu; fu = fu->nextfu ) {
           if (  fu->bcnt ) {
           cursize += fu->bcnt * fu->reps;
           continue;
           }
           for (  bcnt = prec = 0,   fmt = (  unsigned char* ) fu->fmt; *fmt; ++fmt ) {
           if (  *fmt != '%' )
           continue;
           /*
           * skip any special chars -- save precision in
           * case it's a %s format.
           */
           while (  index(  spec + 1,   *++fmt ) );
           if (  *fmt == '.' && isdigit(  *++fmt ) ) {
           prec = atoi(  (  char* )fmt );
           while (  isdigit(  *++fmt ) );
           }
           switch(  *fmt ) {
           case 'c':
           bcnt += 1;
           break;
           case 'd': case 'i': case 'o': case 'u':
           case 'x': case 'X':
           bcnt += 4;
           break;
           case 'e': case 'E': case 'f': case 'g': case 'G':
           bcnt += 8;
           break;
           case 's':
           bcnt += prec;
           break;
           case '_':
           switch(  *++fmt ) {
           case 'c': case 'p': case 'u':
           bcnt += 1;
           break;
           }
           }
           }
           cursize += bcnt * fu->reps;
           }
           return (  cursize );
          }
          
          void
     218  rewrite(  rtems_shell_hexdump_globals* globals,   FS *fs )
          {
           enum { NOTOKAY,   USEBCNT,   USEPREC } sokay;
           PR *pr,   **nextpr;
           FU *fu;
           unsigned char *p1,   *p2,   *fmtp;
           char savech,   cs[3];
           int nconv,   prec;
           size_t len;
          
           pr = NULL;
           nextpr = NULL;
           prec = 0;
          
           for (  fu = fs->nextfu; fu; fu = fu->nextfu ) {
           /*
           * Break each format unit into print units; each conversion
           * character gets its own.
           */
           for (  nconv = 0,   fmtp = (  unsigned char* )fu->fmt; *fmtp; nextpr = &pr->nextpr ) {
           if (  (  pr = calloc(  1,   sizeof(  PR ) ) ) == NULL )
           err(  exit_jump,   1,   NULL );
           if (  !fu->nextpr )
           fu->nextpr = pr;
           else {
           if (  nextpr )
           *nextpr = pr;
           }
          
           /* Skip preceding text and up to the next % sign. */
           for (  p1 = fmtp; *p1 && *p1 != '%'; ++p1 );
          
           /* Only text in the string. */
           if (  !*p1 ) {
           pr->fmt = (  char* )fmtp;
           pr->flags = F_TEXT;
           break;
           }
          
           /*
           * Get precision for %s -- if have a byte count,   don't
           * need it.
           */
           if (  fu->bcnt ) {
           sokay = USEBCNT;
           /* Skip to conversion character. */
           for (  ++p1; index(  spec,   *p1 ); ++p1 );
           } else {
           /* Skip any special chars,   field width. */
           while (  index(  spec + 1,   *++p1 ) );
           if (  *p1 == '.' && isdigit(  *++p1 ) ) {
           sokay = USEPREC;
           prec = atoi(  (  char* )p1 );
           while (  isdigit(  *++p1 ) );
           } else
           sokay = NOTOKAY;
           }
          
           p2 = p1 + 1; /* Set end pointer. */
           cs[0] = *p1; /* Set conversion string. */
           cs[1] = '\0';
          
           /*
           * Figure out the byte count for each conversion;
           * rewrite the format as necessary,   set up blank-
           * padding for end of data.
           */
           switch(  cs[0] ) {
           case 'c':
           pr->flags = F_CHAR;
           switch(  fu->bcnt ) {
           case 0: case 1:
           pr->bcnt = 1;
           break;
           default:
           p1[1] = '\0';
           badcnt(  globals,   (  char* )p1 );
           }
           break;
           case 'd': case 'i':
           pr->flags = F_INT;
           goto isint;
           case 'o': case 'u': case 'x': case 'X':
           pr->flags = F_UINT;
          isint: cs[2] = '\0';
           cs[1] = cs[0];
           cs[0] = 'q';
           switch(  fu->bcnt ) {
           case 0: case 4:
           pr->bcnt = 4;
           break;
           case 1:
           pr->bcnt = 1;
           break;
           case 2:
           pr->bcnt = 2;
           break;
           default:
           p1[1] = '\0';
           badcnt(  globals,   (  char* )p1 );
           }
           break;
           case 'e': case 'E': case 'f': case 'g': case 'G':
           pr->flags = F_DBL;
           switch(  fu->bcnt ) {
           case 0: case 8:
           pr->bcnt = 8;
           break;
           case 4:
           pr->bcnt = 4;
           break;
           default:
           if (  fu->bcnt == sizeof(  long double ) ) {
           cs[2] = '\0';
           cs[1] = cs[0];
           cs[0] = 'L';
           pr->bcnt = sizeof(  long double );
           } else {
           p1[1] = '\0';
           badcnt(  globals,   (  char* )p1 );
           }
           }
           break;
           case 's':
           pr->flags = F_STR;
           switch(  sokay ) {
           case NOTOKAY:
           badsfmt(  globals );
           case USEBCNT:
           pr->bcnt = fu->bcnt;
           break;
           case USEPREC:
           pr->bcnt = prec;
           break;
           }
           break;
           case '_':
           ++p2;
           switch(  p1[1] ) {
           case 'A':
           endfu = fu;
           fu->flags |= F_IGNORE;
           /* FALLTHROUGH */
           case 'a':
           pr->flags = F_ADDRESS;
           ++p2;
           switch(  p1[2] ) {
           case 'd': case 'o': case'x':
           cs[0] = 'q';
           cs[1] = p1[2];
           cs[2] = '\0';
           break;
           default:
           p1[3] = '\0';
           badconv(  globals,   (  char* )p1 );
           }
           break;
           case 'c':
           pr->flags = F_C;
           /* cs[0] = 'c'; set in conv_c */
           goto isint2;
           case 'p':
           pr->flags = F_P;
           cs[0] = 'c';
           goto isint2;
           case 'u':
           pr->flags = F_U;
           /* cs[0] = 'c'; set in conv_u */
          isint2: switch(  fu->bcnt ) {
           case 0: case 1:
           pr->bcnt = 1;
           break;
           default:
           p1[2] = '\0';
           badcnt(  globals,   (  char* )p1 );
           }
           break;
           default:
           p1[2] = '\0';
           badconv(  globals,   (  char* )p1 );
           }
           break;
           default:
           p1[1] = '\0';
           badconv(  globals,   (  char* )p1 );
           }
          
           /*
           * Copy to PR format string,   set conversion character
           * pointer,   update original.
           */
           savech = *p2;
           p1[0] = '\0';
           len = strlen(  (  char* )fmtp ) + strlen(  cs ) + 1;
           if (  (  pr->fmt = calloc(  1,   len ) ) == NULL )
           err(  exit_jump,   1,   NULL );
           snprintf(  pr->fmt,   len,   "%s%s",   fmtp,   cs );
           *p2 = savech;
           pr->cchar = pr->fmt + (  p1 - fmtp );
           fmtp = p2;
          
           /* Only one conversion character if byte count. */
           if (  !(  pr->flags&F_ADDRESS ) && fu->bcnt && nconv++ )
           errx(  exit_jump,   1,   "byte count with multiple conversion characters" );
           }
           /*
           * If format unit byte count not specified,   figure it out
           * so can adjust rep count later.
           */
           if (  !fu->bcnt )
           for (  pr = fu->nextpr; pr; pr = pr->nextpr )
           fu->bcnt += pr->bcnt;
           }
           if (  pr ) {
           free(  pr );
           pr = NULL;
           }
           /*
           * If the format string interprets any data at all,   and it's
           * not the same as the blocksize,   and its last format unit
           * interprets any data at all,   and has no iteration count,  
           * repeat it as necessary.
           *
           * If,   rep count is greater than 1,   no trailing whitespace
           * gets output from the last iteration of the format unit.
           */
           for (  fu = fs->nextfu; fu; fu = fu->nextfu ) {
           if (  !fu->nextfu && fs->bcnt < blocksize &&
           !(  fu->flags&F_SETREP ) && fu->bcnt )
           fu->reps += (  blocksize - fs->bcnt ) / fu->bcnt;
           if (  fu->reps > 1 ) {
           for (  pr = fu->nextpr;; pr = pr->nextpr )
           if (  !pr->nextpr )
           break;
           for (  p1 = (  unsigned char* )pr->fmt,   p2 = NULL; *p1; ++p1 )
           p2 = isspace(  *p1 ) ? p1 : NULL;
           if (  p2 )
           pr->nospace = (  char* )p2;
           }
           }
          #ifdef DEBUG
           for (  fu = fs->nextfu; fu; fu = fu->nextfu ) {
           (  void )printf(  "fmt:" );
           for (  pr = fu->nextpr; pr; pr = pr->nextpr )
           (  void )printf(  " {%s}",   pr->fmt );
           (  void )printf(  "\n" );
           }
          #endif
          }
          
          void
     469  escape(  char *p1 )
          {
           char *p2;
          
           /* alphabetic escape sequences have to be done in place */
           for (  p2 = p1;; ++p1,   ++p2 ) {
           if (  !*p1 ) {
           *p2 = *p1;
           break;
           }
           if (  *p1 == '\\' )
           switch(  *++p1 ) {
           case 'a':
           /* *p2 = '\a'; */
           *p2 = '\007';
           break;
           case 'b':
           *p2 = '\b';
           break;
           case 'f':
           *p2 = '\f';
           break;
           case 'n':
           *p2 = '\n';
           break;
           case 'r':
           *p2 = '\r';
           break;
           case 't':
           *p2 = '\t';
           break;
           case 'v':
           *p2 = '\v';
           break;
           default:
           *p2 = *p1;
           break;
           }
           }
          }
          
          void
     511  badcnt(  rtems_shell_hexdump_globals* globals,   char *s )
          {
           errx(  exit_jump,   1,   "%s: bad byte count",   s );
          }
          
          void
     517  badsfmt(  rtems_shell_hexdump_globals* globals )
          {
           errx(  exit_jump,   1,   "%%s: requires a precision or a byte count" );
          }
          
          void
     523  badfmt(  rtems_shell_hexdump_globals* globals,   const char *fmt )
          {
           errx(  exit_jump,   1,   "\"%s\": bad format",   fmt );
          }
          
          void
     529  badconv(  rtems_shell_hexdump_globals* globals,   char *ch )
          {
           errx(  exit_jump,   1,   "%%%s: bad conversion character",   ch );
          }

libmisc/shell/hexsyntax.c

       1  /*-
           * Copyright (  c ) 1990,   1993
           * The Regents of the University of California. 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )hexsyntax.c 8.2 (  Berkeley ) 5/4/95";
          #include <sys/cdefs.h>
      42  __FBSDID(  "$FreeBSD: src/usr.bin/hexdump/hexsyntax.c,  v 1.12 2002/09/04 23:29:01 dwmalone Exp $" );
          #endif
          #endif /* not lint */
          
          #include <sys/types.h>
          
          #include <err.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #ifdef HAVE_STRINGS_H
          #include <strings.h>
          #endif
          #include <unistd.h>
          
          #include "hexdump.h"
          
          #define __need_getopt_newlib
          #include <getopt.h>
          
          #if RTEMS_REMOVED
          off_t skip; /* bytes to skip */
          #endif
          
          void
      67  newsyntax(  rtems_shell_hexdump_globals* globals,   int argc,   char ***argvp )
          {
           int ch;
           char *p,   **argv;
          
           struct getopt_data getopt_reent;
           memset(  &getopt_reent,   0,   sizeof(  getopt_data ) );
          
           argv = *argvp;
           if (  (  p = rindex(  argv[0],   'h' ) ) != NULL &&
           strcmp(  p,   "hd" ) == 0 ) {
           /* "Canonical" format,   implies -C. */
           add(  globals,   "\"%08.8_Ax\n\"" );
           add(  globals,   "\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" " );
           add(  globals,   "\" |\" 16/1 \"%_p\" \"|\\n\"" );
           }
           while (  (  ch = getopt_r(  argc,   argv,   "bcCde:f:n:os:vx",   &getopt_reent ) ) != -1 )
           switch (  ch ) {
           case 'b':
           add(  globals,   "\"%07.7_Ax\n\"" );
           add(  globals,   "\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"" );
           break;
           case 'c':
           add(  globals,   "\"%07.7_Ax\n\"" );
           add(  globals,   "\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"" );
           break;
           case 'C':
           add(  globals,   "\"%08.8_Ax\n\"" );
           add(  globals,   "\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" " );
           add(  globals,   "\" |\" 16/1 \"%_p\" \"|\\n\"" );
           break;
           case 'd':
           add(  globals,   "\"%07.7_Ax\n\"" );
           add(  globals,   "\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"" );
           break;
           case 'e':
           add(  globals,   getopt_reent.optarg );
           break;
           case 'f':
           addfile(  globals,   getopt_reent.optarg );
           break;
           case 'n':
           if (  (  length = atoi(  getopt_reent.optarg ) ) < 0 )
           errx(  exit_jump,   1,   "%s: bad length value",   getopt_reent.optarg );
           break;
           case 'o':
           add(  globals,   "\"%07.7_Ax\n\"" );
           add(  globals,   "\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"" );
           break;
           case 's':
           if (  (  skip = strtoll(  getopt_reent.optarg,   &p,   0 ) ) < 0 )
           errx(  exit_jump,   1,   "%s: bad skip value",   getopt_reent.optarg );
           switch(  *p ) {
           case 'b':
           skip *= 512;
           break;
           case 'k':
           skip *= 1024;
           break;
           case 'm':
           skip *= 1048576;
           break;
           }
           break;
           case 'v':
           vflag = ALL;
           break;
           case 'x':
           add(  globals,   "\"%07.7_Ax\n\"" );
           add(  globals,   "\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"" );
           break;
           case '?':
           usage(  globals );
           }
          
           if (  !fshead ) {
           add(  globals,   "\"%07.7_Ax\n\"" );
           add(  globals,   "\"%07.7_ax \" 8/2 \"%04x \" \"\\n\"" );
           }
          
           *argvp += getopt_reent.optind;
          }
          
          void
     151  usage(  rtems_shell_hexdump_globals* globals )
          {
           (  void )fprintf(  stderr,   "%s\n%s\n%s\n%s\n",  
          "usage: hexdump [-bcCdovx] [-e fmt] [-f fmt_file] [-n length]",  
          " [-s skip] [file ...]",  
          " hd [-bcdovx] [-e fmt] [-f fmt_file] [-n length]",  
          " [-s skip] [file ...]" );
           exit(  1 );
          }

libmisc/shell/login_check.c

       1  /**
           * @file
           *
           * @brief Shell login check function.
           */
          
          /*
           * Copyright (  c ) 2009 embedded brains GmbH and others.
           *
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * D-82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * Based on work from Chris Johns and Fernando Ruiz.
           *
           * Derived from file "cpukit/libmisc/shell/shell.c".
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <unistd.h>
          #include <pwd.h>
          
          #include <rtems/shell.h>
          #include <rtems/userenv.h>
          
      36  bool rtems_shell_login_check(  
           const char *user,  
           const char *passphrase
           )
          {
           struct passwd *pw = getpwnam(   user );
          
           /* Valid user? */
           if (  pw != NULL && strcmp(   pw->pw_passwd,   "!" ) != 0 ) {
           setuid(   pw->pw_uid );
           setgid(   pw->pw_gid );
           rtems_current_user_env->euid = 0;
           rtems_current_user_env->egid = 0;
           chown(   rtems_current_shell_env->devname,   pw->pw_uid,   0 );
           rtems_current_user_env->euid = pw->pw_uid;
           rtems_current_user_env->egid = pw->pw_gid;
           if (  strcmp(   pw->pw_passwd,   "*" ) == 0 ) {
           /* TODO: /etc/shadow */
           return true;
           } else {
           /* TODO: crypt(   ) */
           return true;
           }
           }
          
           return false;
          }

libmisc/shell/login_prompt.c

       1  /**
           * @file
           *
           * @brief Shell login prompt functions.
           */
          
          /*
           * Authorship
           * ----------
           * Parts of this software was created by
           * Till Straumann <strauman@slac.stanford.edu>,   2003-2007
           * Stanford Linear Accelerator Center,   Stanford University.
           *
           * Acknowledgement of sponsorship
           * ------------------------------
           * Parts of this software was produced by
           * the Stanford Linear Accelerator Center,   Stanford University,  
           * under Contract DE-AC03-76SFO0515 with the Department of Energy.
           *
           * Government disclaimer of liability
           * ----------------------------------
           * Neither the United States nor the United States Department of Energy,  
           * nor any of their employees,   makes any warranty,   express or implied,   or
           * assumes any legal liability or responsibility for the accuracy,  
           * completeness,   or usefulness of any data,   apparatus,   product,   or process
           * disclosed,   or represents that its use would not infringe privately owned
           * rights.
           *
           * Stanford disclaimer of liability
           * --------------------------------
           * Stanford University makes no representations or warranties,   express or
           * implied,   nor assumes any liability for the use of this software.
           *
           * Stanford disclaimer of copyright
           * --------------------------------
           * Stanford University,   owner of the copyright,   hereby disclaims its
           * copyright and all other rights in this software. Hence,   anyone may
           * freely use it for any purpose without restriction.
           *
           * Maintenance of notices
           * ----------------------
           * In the interest of clarity regarding the origin and status of this
           * SLAC software,   this and all the preceding Stanford University notices
           * are to remain affixed to any copy or derivative of this software made
           * or distributed by the recipient and are to be affixed to any copy of
           * software made or distributed by the recipient that contains a copy or
           * derivative of this software.
           *
           * ------------------ SLAC Software Notices,   Set 4 OTT.002a,   2004 FEB 03
           *
           * Copyright (  c ) 2009 embedded brains GmbH and others.
           *
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * D-82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * Based on work from Chris Johns,   Fernando Ruiz and Till Straumann.
           *
           * Derived from files "cpukit/libmisc/shell/shell.c" and
           * "cpukit/telnetd/check_passwd.c".
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <termios.h>
          #include <unistd.h>
          #include <ctype.h>
          #include <errno.h>
          
          #include <rtems/shell.h>
          
      81  static int rtems_shell_discard(   int c,   FILE *stream )
          {
           return c;
          }
          
      86  static bool rtems_shell_get_text(  
           FILE *in,  
           FILE *out,  
           char *line,  
           size_t size
           )
          {
           int fd_in = fileno(   in );
           int (  *put )(   int,   FILE * ) =
           out != NULL && isatty(   fd_in )
           ? fputc
           : rtems_shell_discard;
           size_t i = 0;
          
           if (  size < 1 ) {
           return false;
           }
          
           tcdrain(   fd_in );
           if (  out != NULL ){
           tcdrain(   fileno(  out )  );
           }
          
           while (  true ) {
           int c = fgetc(  in );
          
           switch (  c ) {
           case EOF:
           clearerr(   in  );
           return false;
           case '\n':
           case '\r':
           put(  '\n',   out );
           line [i] = '\0';
           return true;
           case 127:
           case '\b':
           if (  i > 0 ) {
           put(  '\b',   out );
           put(  ' ',   out );
           put(  '\b',   out );
           --i;
           } else {
           put(  '\a',   out );
           }
           break;
           default:
           if (  !iscntrl(   c ) ) {
           if (  i < size - 1 ) {
           line [i] = (  char ) c;
           ++i;
           put(   c,   out );
           } else {
           put(  '\a',   out );
           }
           } else {
           put(  '\a',   out );
           }
           break;
           }
           }
           return true;
          }
          
     150  bool rtems_shell_login_prompt(  
           FILE *in,  
           FILE *out,  
           const char *device,  
           rtems_shell_login_check_t check
           )
          {
           int fd_in = fileno(  in );
           struct termios termios_previous;
           bool restore_termios = false;
           int i = 0;
           bool result = false;
          
           if (  tcgetattr(   fd_in,   &termios_previous ) == 0 ) {
           struct termios termios_new = termios_previous;
          
           /*
           * Stay in canonical mode so we can tell EOF and dropped connections.
           * But read one character at a time and do not echo it.
           */
           termios_new.c_lflag &= (  unsigned char ) ~ECHO;
           termios_new.c_cc [VTIME] = 0;
           termios_new.c_cc [VMIN] = 1;
          
           restore_termios = tcsetattr(   fd_in,   TCSANOW,   &termios_new ) == 0;
           }
          
           for (  i = 0; i < 3; ++i ) {
           char user [32];
           char passphrase [128];
          
           fprintf(   out,   "%s login: ",   device  );
           fflush(   out  );
           result = rtems_shell_get_text(   in,   out,   user,   sizeof(  user )  );
           if (   !result  )
           break;
          
           fflush(   in );
           fprintf(   out,   "Password: " );
           fflush(   out );
           result = rtems_shell_get_text(   in,   NULL,   passphrase,   sizeof(  passphrase )  );
           if (   !result  )
           break;
           fputc(   '\n',   out );
          
           result = check(   user,   passphrase  );
           if (  result )
           break;
          
           fprintf(   out,   "Login incorrect\n\n" );
           sleep(   2 );
           }
          
           if (  restore_termios ) {
           /* What to do if restoring the flags fails? */
           tcsetattr(   fd_in,   TCSANOW,   &termios_previous );
           }
          
           return result;
          }

libmisc/shell/main_alias.c

       1  /*
           * ALIAS Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_alias.c,  v 1.4 2008/02/27 21:52:16 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      25  int rtems_shell_rtems_main_alias(  int argc,   char **argv )
          {
           if (  argc<3 ) {
           fprintf(  stderr,  "too few arguments\n" );
           return 1;
           }
          
           if (  !rtems_shell_alias_cmd(  argv[1],  argv[2] ) ) {
           fprintf(  stderr,  "unable to make an alias(  %s,  %s )\n",  argv[1],  argv[2] );
           }
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_ALIAS_Command = {
           "alias",   /* name */
           "alias old new",   /* usage */
           "misc",   /* topic */
           rtems_shell_rtems_main_alias,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_blksync.c

       1  /*
           * RM Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_blksync.c,  v 1.5 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          #include <fcntl.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/bdbuf.h>
          #include <rtems/blkdev.h>
          #include "internal.h"
          
      31  int rtems_shell_main_blksync(  
           int argc,  
           char *argv[]
           )
          {
           const char* driver = NULL;
           int arg;
           int fd;
          
           for (  arg = 1; arg < argc; arg++ ) {
           if (  argv[arg][0] == '-' ) {
           fprintf(   stderr,   "%s: invalid option: %s\n",   argv[0],   argv[arg] );
           return 1;
           } else {
           if (  !driver )
           driver = argv[arg];
           else {
           fprintf(   stderr,   "%s: only one driver name allowed: %s\n",  
           argv[0],   argv[arg] );
           return 1;
           }
           }
           }
          
           fd = open (  driver,   O_WRONLY,   0 );
           if (  fd < 0 ) {
           fprintf(   stderr,   "%s: driver open failed: %s\n",   argv[0],   strerror (  errno ) );
           return 1;
           }
          
           if (  ioctl (  fd,   RTEMS_BLKIO_SYNCDEV ) < 0 ) {
           fprintf(   stderr,   "%s: driver sync failed: %s\n",   argv[0],   strerror (  errno ) );
           return 1;
           }
          
           close (  fd );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_BLKSYNC_Command = {
           "blksync",   /* name */
           "blksync driver # sync the block driver",   /* usage */
           "files",   /* topic */
           rtems_shell_main_blksync,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_cat.c

       1  /*
           * CAT Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_cat.c,  v 1.4 2008/02/27 21:52:16 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <termios.h>
          #include <string.h>
          #include <stdlib.h>
          #include <ctype.h>
          #include <dirent.h>
          #include <time.h>
          #include <fcntl.h>
          #include <unistd.h>
          #include <pwd.h>
          #include <grp.h>
          #include <errno.h>
          #include <sys/types.h>
          #include <stddef.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      38  int rtems_shell_main_cat(  int argc,   char *argv[] )
          {
           int n;
           int sc;
          
           for (   n=1; n < argc ; n++ ) {
           sc = rtems_shell_cat_file(  stdout,   argv[n] );
           if (   sc == -1  ) {
           fprintf(  stderr,   "%s: %s: %s\n",   argv[0],   argv[n],   strerror(  errno ) );
           return -1;
           }
           }
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_CAT_Command = {
           "cat",   /* name */
           "cat n1 [n2 [n3...]] # show the ascii contents",   /* usage */
           "files",   /* topic */
           rtems_shell_main_cat ,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_cd.c

       1  /*
           * CD Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_cd.c,  v 1.3 2007/12/17 22:39:28 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
          rtems_shell_alias_t rtems_shell_CD_Alias = {
           "chdir",   /* command */
           "cd" /* alias */
          };

libmisc/shell/main_chdir.c

       1  /*
           * CHDIR Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_chdir.c,  v 1.4 2008/02/27 21:52:16 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      28  int rtems_shell_main_chdir(  
           int argc,  
           char *argv[]
           )
          {
           char *dir;
          
           dir = "/";
          
           if (  argc > 1 )
           dir = argv[1];
          
           if (  chdir(  dir ) ) {
           fprintf(  stderr,   "chdir to '%s' failed:%s\n",   dir,  strerror(  errno ) );
           return errno;
           }
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_CHDIR_Command = {
           "chdir",   /* name */
           "chdir [dir] # change the current directory",   /* usage */
           "files",   /* topic */
           rtems_shell_main_chdir,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_chmod.c

       1  /*
           * CHMOD Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_chmod.c,  v 1.7 2009/07/23 14:32:34 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          #include <sys/types.h>
          #include <sys/stat.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include "internal.h"
          
      31  int rtems_shell_main_chmod(  
           int argc,  
           char *argv[]
           )
          {
           int n;
           mode_t mode;
           unsigned long tmp;
          
           if (  argc < 2 ) {
           fprintf(  stderr,  "%s: too few arguments\n",   argv[0] );
           return -1;
           }
          
           /*
           * Convert arguments into numbers
           */
           if (   rtems_string_to_unsigned_long(  argv[1],   &tmp,   NULL,   0 )  ) {
           printf(   "Mode argument (  %s ) is not a number\n",   argv[1]  );
           return -1;
           }
           mode = (  mode_t ) (  tmp & 0777 );
          
           /*
           * Now change the files modes
           */
           for (  n=2 ; n < argc ; n++ )
           chmod(  argv[n++],   mode );
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_CHMOD_Command = {
           "chmod",   /* name */
           "chmod 0777 n1 n2... # change filemode",   /* usage */
           "files",   /* topic */
           rtems_shell_main_chmod,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_chroot.c

       1  /*
           * CHROOT Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_chroot.c,  v 1.4 2008/02/27 21:52:16 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      28  int rtems_shell_main_chroot(  
           int argc,  
           char * argv[]
           )
          {
           char *new_root = "/";
          
           if (  argc == 2 )
           new_root = argv[1];
          
           if (   chroot(  new_root ) < 0  ) {
           fprintf(  stderr,  "chroot %s (  %s )\n",   new_root,   strerror(  errno ) );
           return -1;
           }
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_CHROOT_Command = {
           "chroot",   /* name */
           "chroot [dir] # change the root directory",   /* usage */
           "files",   /* topic */
           rtems_shell_main_chroot,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_cp.c

       1  /* $NetBSD: cp.c,  v 1.39 2005/10/24 12:59:07 kleink Exp $ */
          
          /*
           * Copyright (  c ) 1988,   1993,   1994
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * David Hitz of Auspex Systems Inc.
           *
           * 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. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if 0
          #ifndef lint
      41  __COPYRIGHT(  
          "@(  # ) Copyright (  c ) 1988,   1993,   1994\n\
           The Regents of the University of California. All rights reserved.\n" );
          #endif /* not lint */
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )cp.c 8.5 (  Berkeley ) 4/29/95";
          #else
      50  __RCSID(  "$NetBSD: cp.c,  v 1.39 2005/10/24 12:59:07 kleink Exp $" );
          #endif
          #endif /* not lint */
          #endif
          /*
           * Cp copies source files to target files.
           *
           * The global PATH_T structure "to" always contains the path to the
           * current target file. Since fts(  3 ) does not change directories,  
           * this path can be either absolute or dot-relative.
           *
           * The basic algorithm is to initialize "to" and use fts(  3 ) to traverse
           * the file hierarchy rooted in the argument list. A trivial case is the
           * case of 'cp file1 file2'. The more interesting case is the case of
           * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the
           * path (  relative to the root of the traversal ) is appended to dir (  stored
           * in "to" ) to form the final target path.
           */
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          #define __need_getopt_newlib
          #include <getopt.h>
          
          #include <sys/param.h>
          #include <sys/stat.h>
          
          #include <err.h>
          #include <errno.h>
          #include <fts.h>
          #include <limits.h>
          #include <signal.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          
          #include "extern-cp.h"
          
          #define S_ISTXT 0
          
          #define STRIP_TRAILING_SLASH(  p ) { \
           while (  (  p ).p_end > (  p ).p_path + 1 && (  p ).p_end[-1] == '/' ) \
           *--(  p ).p_end = 0; \
          }
          
          enum op { FILE_TO_FILE,   FILE_TO_DIR,   DIR_TO_DNE };
      98  
      99  static int Rflag,   rflag;
     100  
          static int main_cp(  rtems_shell_cp_globals* cp_globals,   int,   char *[] );
          static int copy(  rtems_shell_cp_globals* cp_globals,   char *[],   enum op,   int );
     103  static int mastercmp(  const FTSENT **,   const FTSENT ** );
          
          void
          rtems_shell_cp_exit (  rtems_shell_cp_globals* cp_global,   int code __attribute__(  (  unused ) ) )
          {
           longjmp (  cp_global->exit_jmp,   1 );
     109  }
          
          int
          rtems_shell_main_cp(  int argc,   char *argv[] )
          {
           rtems_shell_cp_globals cp_globals;
           memset (  &cp_globals,   0,   sizeof (  cp_globals ) );
           Rflag = rflag = 0;
           if (  setjmp (  cp_globals.exit_jmp ) == 0 )
           return main_cp (  &cp_globals,   argc,   argv );
           return 1;
     120  }
          
          int
          main_cp(  rtems_shell_cp_globals* cp_globals,   int argc,   char *argv[] )
          {
           struct stat to_stat,   tmp_stat;
           enum op type;
           int Hflag,   Lflag,   Pflag,   ch,   fts_options,   r,   have_trailing_slash;
           char *target;
           struct getopt_data getopt_reent;
          
           Hflag = Lflag = Pflag = 0;
           memset(  &getopt_reent,   0,   sizeof(  getopt_data ) );
          
           while (  (  ch = getopt_r(  argc,   argv,   "HLPRafilnprv",   &getopt_reent ) ) != -1 )
           switch (  ch ) {
           case 'H':
           Hflag = 1;
           Lflag = Pflag = 0;
           break;
           case 'L':
           Lflag = 1;
           Hflag = Pflag = 0;
           break;
           case 'P':
           Pflag = 1;
           Hflag = Lflag = 0;
           break;
           case 'R':
           Rflag = 1;
           break;
           case 'a':
           Pflag = 1;
           pflag = 1;
           Rflag = 1;
           Hflag = Lflag = 0;
           break;
           case 'f':
           fflag = 1;
           iflag = nflag = 0;
           break;
           case 'i':
           iflag = 1;
           fflag = nflag = 0;
           break;
           case 'l':
           lflag = 1;
           break;
           case 'n':
           nflag = 1;
           fflag = iflag = 0;
           break;
           case 'p':
           pflag = 1;
           break;
           case 'r':
           rflag = Lflag = 1;
           Hflag = Pflag = 0;
           break;
           case 'v':
           vflag = 1;
           break;
           default:
           usage(  cp_globals );
           break;
           }
           argc -= getopt_reent.optind;
           argv += getopt_reent.optind;
          
           if (  argc < 2 )
           usage(  cp_globals );
          
           fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
           if (  Rflag && rflag )
           errx(  exit_jump,   1,   "the -R and -r options may not be specified together" );
           if (  rflag )
           Rflag = 1;
           if (  Rflag ) {
           if (  Hflag )
           fts_options |= FTS_COMFOLLOW;
           if (  Lflag ) {
           fts_options &= ~FTS_PHYSICAL;
           fts_options |= FTS_LOGICAL;
           }
           } else {
           fts_options &= ~FTS_PHYSICAL;
           fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
           }
          #if 0
           (  void )signal(  SIGINFO,   siginfo );
          #endif
          
           /* Save the target base in "to". */
           target = argv[--argc];
           if (  strlcpy(  to.p_path,   target,   sizeof(  to.p_path ) ) >= sizeof(  to.p_path ) )
           errx(  exit_jump,   1,   "%s: name too long",   target );
           to.p_end = to.p_path + strlen(  to.p_path );
           if (  to.p_path == to.p_end ) {
           *to.p_end++ = '.';
           *to.p_end = 0;
           }
           have_trailing_slash = (  to.p_end[-1] == '/' );
           if (  have_trailing_slash )
           STRIP_TRAILING_SLASH(  to );
           to.target_end = to.p_end;
          
           /* Set end of argument list for fts(  3 ). */
           argv[argc] = NULL;
          
           /*
           * Cp has two distinct cases:
           *
           * cp [-R] source target
           * cp [-R] source1 ... sourceN directory
           *
           * In both cases,   source can be either a file or a directory.
           *
           * In (  1 ),   the target becomes a copy of the source. That is,   if the
           * source is a file,   the target will be a file,   and likewise for
           * directories.
           *
           * In (  2 ),   the real target is not directory,   but "directory/source".
           */
           r = stat(  to.p_path,   &to_stat );
           if (  r == -1 && errno != ENOENT )
           err(  exit_jump,   1,   "%s",   to.p_path );
           if (  r == -1 || !S_ISDIR(  to_stat.st_mode ) ) {
           /*
           * Case (  1 ). Target is not a directory.
           */
           if (  argc > 1 )
           errx(  exit_jump,   1,   "%s is not a directory",   to.p_path );
          
           /*
           * Need to detect the case:
           * cp -R dir foo
           * Where dir is a directory and foo does not exist,   where
           * we want pathname concatenations turned on but not for
           * the initial mkdir(   ).
           */
           if (  r == -1 ) {
           if (  Rflag && (  Lflag || Hflag ) )
           stat(  *argv,   &tmp_stat );
           else
           lstat(  *argv,   &tmp_stat );
          
           if (  S_ISDIR(  tmp_stat.st_mode ) && Rflag )
           type = DIR_TO_DNE;
           else
           type = FILE_TO_FILE;
           } else
           type = FILE_TO_FILE;
          
           if (  have_trailing_slash && type == FILE_TO_FILE ) {
           if (  r == -1 )
           errx(  exit_jump,   1,   "directory %s does not exist",  
           to.p_path );
           else
           errx(  exit_jump,   1,   "%s is not a directory",   to.p_path );
           }
           } else
           /*
           * Case (  2 ). Target is a directory.
           */
           type = FILE_TO_DIR;
          
           return copy(  cp_globals,   argv,   type,   fts_options );
     287  }
          
          int
          copy(  rtems_shell_cp_globals* cp_globals,  
           char *argv[],   enum op type,   int fts_options )
          {
           struct stat to_stat;
           FTS *ftsp;
           FTSENT *curr;
           int base = 0,   dne,   badcp,   rval;
           size_t nlen;
           char *p,   *target_mid;
           mode_t mask,   mode;
          
           /*
           * Keep an inverted copy of the umask,   for use in correcting
           * permissions on created directories when not using -p.
           */
           mask = ~umask(  0777 );
           umask(  ~mask );
          
           if (  (  ftsp = fts_open(  argv,   fts_options,   mastercmp ) ) == NULL )
           err(  exit_jump,   1,   "fts_open" );
           for (  badcp = rval = 0; (  curr = fts_read(  ftsp ) ) != NULL; badcp = 0 ) {
           switch (  curr->fts_info ) {
           case FTS_NS:
           case FTS_DNR:
           case FTS_ERR:
           warnx(  "%s: %s",  
           curr->fts_path,   strerror(  curr->fts_errno ) );
           badcp = rval = 1;
           continue;
           case FTS_DC: /* Warn,   continue. */
           warnx(  "%s: directory causes a cycle",   curr->fts_path );
           badcp = rval = 1;
           continue;
           default:
           ;
           }
          
           /*
           * If we are in case (  2 ) or (  3 ) above,   we need to append the
           * source name to the target name.
           */
           if (  type != FILE_TO_FILE ) {
           /*
           * Need to remember the roots of traversals to create
           * correct pathnames. If there's a directory being
           * copied to a non-existent directory,   e.g.
           * cp -R a/dir noexist
           * the resulting path name should be noexist/foo,   not
           * noexist/dir/foo (  where foo is a file in dir ),   which
           * is the case where the target exists.
           *
           * Also,   check for "..". This is for correct path
           * concatenation for paths ending in "..",   e.g.
           * cp -R .. /tmp
           * Paths ending in ".." are changed to ".". This is
           * tricky,   but seems the easiest way to fix the problem.
           *
           * XXX
           * Since the first level MUST be FTS_ROOTLEVEL,   base
           * is always initialized.
           */
           if (  curr->fts_level == FTS_ROOTLEVEL ) {
           if (  type != DIR_TO_DNE ) {
           p = strrchr(  curr->fts_path,   '/' );
           base = (  p == NULL ) ? 0 :
           (  int )(  p - curr->fts_path + 1 );
          
           if (  !strcmp(  &curr->fts_path[base],  
           ".." ) )
           base += 1;
           } else
           base = curr->fts_pathlen;
           }
          
           p = &curr->fts_path[base];
           nlen = curr->fts_pathlen - base;
           target_mid = to.target_end;
           if (  *p != '/' && target_mid[-1] != '/' )
           *target_mid++ = '/';
           *target_mid = 0;
           if (  target_mid - to.p_path + nlen >= PATH_MAX ) {
           warnx(  "%s%s: name too long (  not copied )",  
           to.p_path,   p );
           badcp = rval = 1;
           continue;
           }
           (  void )strncat(  target_mid,   p,   nlen );
           to.p_end = target_mid + nlen;
           *to.p_end = 0;
           STRIP_TRAILING_SLASH(  to );
           }
          
           if (  curr->fts_info == FTS_DP ) {
           /*
           * We are nearly finished with this directory. If we
           * didn't actually copy it,   or otherwise don't need to
           * change its attributes,   then we are done.
           */
           if (  !curr->fts_number )
           continue;
           /*
           * If -p is in effect,   set all the attributes.
           * Otherwise,   set the correct permissions,   limited
           * by the umask. Optimise by avoiding a chmod(   )
           * if possible (  which is usually the case if we
           * made the directory ). Note that mkdir(   ) does not
           * honour setuid,   setgid and sticky bits,   but we
           * normally want to preserve them on directories.
           */
           if (  pflag ) {
           if (  setfile(  cp_globals,   curr->fts_statp,   -1 ) )
           rval = 1;
           if (  preserve_dir_acls(  curr->fts_statp,  
           curr->fts_accpath,   to.p_path ) != 0 )
           rval = 1;
           } else {
           mode = curr->fts_statp->st_mode;
           if (  (  mode & (  S_ISUID | S_ISGID | S_ISTXT ) ) ||
           (  (  mode | S_IRWXU ) & mask ) != (  mode & mask ) )
           if (  chmod(  to.p_path,   mode & mask ) != 0 ){
           warn(  "chmod: %s",   to.p_path );
           rval = 1;
           }
           }
           continue;
           }
          
           /* Not an error but need to remember it happened */
           if (  stat(  to.p_path,   &to_stat ) == -1 )
           dne = 1;
           else {
           if (  to_stat.st_dev == curr->fts_statp->st_dev &&
           to_stat.st_ino == curr->fts_statp->st_ino ) {
           warnx(  "%s and %s are identical (  not copied ).",  
           to.p_path,   curr->fts_path );
           badcp = rval = 1;
           if (  S_ISDIR(  curr->fts_statp->st_mode ) )
           (  void )fts_set(  ftsp,   curr,   FTS_SKIP );
           continue;
           }
           if (  !S_ISDIR(  curr->fts_statp->st_mode ) &&
           S_ISDIR(  to_stat.st_mode ) ) {
           warnx(  "cannot overwrite directory %s with "
           "non-directory %s",  
           to.p_path,   curr->fts_path );
           badcp = rval = 1;
           continue;
           }
           dne = 0;
           }
          
           switch (  curr->fts_statp->st_mode & S_IFMT ) {
           case S_IFLNK:
           /* Catch special case of a non-dangling symlink */
           if (  (  fts_options & FTS_LOGICAL ) ||
           (  (  fts_options & FTS_COMFOLLOW ) &&
           curr->fts_level == 0 ) ) {
           if (  copy_file(  cp_globals,   curr,   dne ) )
           badcp = rval = 1;
           } else {
           if (  copy_link(  cp_globals,   curr,   !dne ) )
           badcp = rval = 1;
           }
           break;
           case S_IFDIR:
           if (  !Rflag ) {
           warnx(  "%s is a directory (  not copied ).",  
           curr->fts_path );
           (  void )fts_set(  ftsp,   curr,   FTS_SKIP );
           badcp = rval = 1;
           break;
           }
           /*
           * If the directory doesn't exist,   create the new
           * one with the from file mode plus owner RWX bits,  
           * modified by the umask. Trade-off between being
           * able to write the directory (  if from directory is
           * 555 ) and not causing a permissions race. If the
           * umask blocks owner writes,   we fail..
           */
           if (  dne ) {
           if (  mkdir(  to.p_path,  
           curr->fts_statp->st_mode | S_IRWXU ) < 0 )
           err(  exit_jump,   1,   "%s",   to.p_path );
           } else if (  !S_ISDIR(  to_stat.st_mode ) ) {
           errno = ENOTDIR;
           err(  exit_jump,   1,   "%s",   to.p_path );
           }
           /*
           * Arrange to correct directory attributes later
           * (  in the post-order phase ) if this is a new
           * directory,   or if the -p flag is in effect.
           */
           curr->fts_number = pflag || dne;
           break;
           case S_IFBLK:
           case S_IFCHR:
           if (  Rflag ) {
           if (  copy_special(  cp_globals,   curr->fts_statp,   !dne ) )
           badcp = rval = 1;
           } else {
           if (  copy_file(  cp_globals,   curr,   dne ) )
           badcp = rval = 1;
           }
           break;
           case S_IFSOCK:
           warnx(  "%s is a socket (  not copied ).",  
           curr->fts_path );
           case S_IFIFO:
           if (  Rflag ) {
           if (  copy_fifo(  cp_globals,   curr->fts_statp,   !dne ) )
           badcp = rval = 1;
           } else {
           if (  copy_file(  cp_globals,   curr,   dne ) )
           badcp = rval = 1;
           }
           break;
           default:
           if (  copy_file(  cp_globals,   curr,   dne ) )
           badcp = rval = 1;
           break;
           }
           if (  vflag && !badcp )
           (  void )printf(  "%s -> %s\n",   curr->fts_path,   to.p_path );
           }
           if (  errno )
           err(  exit_jump,   1,   "fts_read" );
           fts_close(  ftsp );
           return (  rval );
          }
          
          /*
           * mastercmp --
           * The comparison function for the copy order. The order is to copy
           * non-directory files before directory files. The reason for this
           * is because files tend to be in the same cylinder group as their
           * parent directory,   whereas directories tend not to be. Copying the
     527   * files first reduces seeking.
           */
          int
          mastercmp(  const FTSENT **a,   const FTSENT **b )
          {
           int a_info,   b_info;
          
           a_info = (  *a )->fts_info;
           if (  a_info == FTS_ERR || a_info == FTS_NS || a_info == FTS_DNR )
           return (  0 );
           b_info = (  *b )->fts_info;
           if (  b_info == FTS_ERR || b_info == FTS_NS || b_info == FTS_DNR )
           return (  0 );
           if (  a_info == FTS_D )
           return (  -1 );
           if (  b_info == FTS_D )
           return (  1 );
           return (  0 );
          }
          
          rtems_shell_cmd_t rtems_shell_CP_Command = {
           "cp",   /* name */
           "cp [-R [-H | -L | -P]] [-f | -i] [-pv] src target",   /* usage */
           "files",   /* topic */
           rtems_shell_main_cp,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };
          

libmisc/shell/main_cpuuse.c

       1  /*
           * CPUUSE Command Implementation
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: main_cpuuse.c,  v 1.5 2008/03/05 02:49:35 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          
          #include <rtems.h>
          #include <rtems/cpuuse.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      25  int rtems_shell_main_cpuuse(  
           int argc,  
           char *argv[]
           )
          {
           /*
           * When invoked with no arguments,   print the report.
           */
           if (   argc == 1  ) {
           rtems_cpu_usage_report_with_plugin(  stdout,   (  rtems_printk_plugin_t )fprintf );
           return 0;
           }
          
           /*
           * When invoked with the single argument -r,   reset the statistics.
           */
           if (   argc == 2 && !strcmp(   argv[1],   "-r"  )  ) {
           printf(   "Resetting CPU Usage information\n"  );
           rtems_cpu_usage_reset(   );
           return 0;
           }
          
           /*
           * OK. The user did something wrong.
           */
           fprintf(   stderr,   "%s: [-r]\n",   argv[0]  );
           return -1;
          }
          
          rtems_shell_cmd_t rtems_shell_CPUUSE_Command = {
           "cpuuse",   /* name */
           "[-r] print or reset per thread cpu usage",   /* usage */
           "rtems",   /* topic */
           rtems_shell_main_cpuuse,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_date.c

       1  /*
           * DATE Shell Command Implmentation
           *
           * OAuthor: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * Significantly rewritten by Joel Sherrill <joel.sherrill@oarcorp.com>.
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_date.c,  v 1.7 2010/08/27 18:04:28 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      30  int rtems_shell_main_date(  
           int argc,  
           char *argv[]
           )
          {
           /*
           * Print the current date and time in default format.
           */
           if (   argc == 1  ) {
           time_t t;
          
           time(  &t );
           printf(  "%s",   ctime(  &t ) );
           return 0;
           }
          
           /*
           * Set the current date and time
           */
           if (   argc == 3  ) {
           char buf[128];
           struct tm TOD;
           struct timespec timesp;
           char *result;
          
           snprintf(   buf,   sizeof(  buf ),   "%s %s",   argv[1],   argv[2]  );
           result = strptime(  
           buf,  
           "%Y-%m-%d %T",  
           &TOD
            );
           if (   result && !*result  ) {
           timesp.tv_sec = mktime(   &TOD  );
           timesp.tv_nsec = 0;
           clock_settime(   CLOCK_REALTIME,   &timesp  );
           return 0;
           }
           }
          
           fprintf(   stderr,   "%s: Usage: [YYYY-MM-DD HH:MM:SS]\n",   argv[0]  );
           return -1;
          }
          
          rtems_shell_cmd_t rtems_shell_DATE_Command = {
           "date",   /* name */
           "date [YYYY-MM-DD HH:MM:SS]",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_date,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_dd.c

       1  /*-
           * Copyright (  c ) 1991,   1993,   1994
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Keith Muller of the University of California,   San Diego and Lance
           * Visser of Convex Computer Corporation.
           *
           * 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if 0
          #ifndef lint
      40  static char const copyright[] =
          "@(  # ) Copyright (  c ) 1991,   1993,   1994\n\
           The Regents of the University of California. All rights reserved.\n";
          #endif /* not lint */
          
          #ifndef lint
          static char sccsid[] = "@(  # )dd.c 8.5 (  Berkeley ) 4/2/94";
          #endif /* not lint */
          #include <sys/cdefs.h>
      49  __FBSDID(  "$FreeBSD: src/bin/dd/dd.c,  v 1.43 2004/08/15 19:10:05 rwatson Exp $" );
          #endif
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          
          #include <sys/param.h>
          #include <sys/stat.h>
          #if RTEMS_REMOVED
          #include <sys/conf.h>
          #include <sys/disklabel.h>
          #endif
          #include <sys/filio.h>
          #include <sys/time.h>
          
          #include <ctype.h>
          #include <err.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <inttypes.h>
          #include <locale.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          
          #include "dd.h"
          #include "extern-dd.h"
          
          #define DEFFILEMODE 0
          
      81  static void dd_close(  rtems_shell_dd_globals* globals );
      82  static void dd_in(  rtems_shell_dd_globals* globals );
      83  static void getfdtype(  rtems_shell_dd_globals* globals,   IO * );
      84  static void setup(  rtems_shell_dd_globals* globals );
          
          #if RTEMS_REMOVED
          IO in,   out; /* input/output state */
          STAT st; /* statistics */
          void (  *cfunc )(  void ); /* conversion function */
          uintmax_t cpy_cnt; /* # of blocks to copy */
          static off_t pending = 0; /* pending seek if sparse */
          u_int ddflags = 0; /* conversion options */
          size_t cbsz; /* conversion block size */
          uintmax_t files_cnt = 1; /* # of files to copy */
          const u_char *ctab; /* conversion table */
          char fill_char; /* Character to fill with if defined */
          #endif
          
          static off_t pending = 0; /* pending seek if sparse */
          
          void
     102  rtems_shell_dd_exit (  rtems_shell_dd_globals* globals,   int code )
          {
           globals->exit_code = code;
           longjmp (  globals->exit_jmp,   1 );
          }
          
     108  static int main_dd(  rtems_shell_dd_globals* globals,   int argc,   char *argv[] );
          
          int
     111  rtems_shell_main_dd(  int argc,   char *argv[] )
          {
           rtems_shell_dd_globals dd_globals;
           rtems_shell_dd_globals* globals = &dd_globals;
           memset (  globals,   0,   sizeof (  dd_globals ) );
           pending = 0;
           ddflags = 0;
           files_cnt = 1;
           dd_globals.exit_code = 1;
           if (  setjmp (  dd_globals.exit_jmp ) == 0 )
           dd_globals.exit_code = main_dd (  globals,   argc,   argv );
           if (  in.fd )
           close(  in.fd );
           if (  out.fd )
           close(  out.fd );
           if (  in.name )
           free(  (  void* )in.name );
           if (  out.name )
           free(  (  void* )out.name );
           if (  in.db )
           free(  in.db );
           if (  out.db && (  in.db != out.db ) )
           free(  out.db );
           return dd_globals.exit_code;
          }
          
          int
     138  main_dd(  rtems_shell_dd_globals* globals,   int argc __unused,   char *argv[] )
          {
           (  void )setlocale(  LC_CTYPE,   "" );
           jcl(  globals,   argv );
           setup(  globals );
          
          #if RTEMS_REMOVED
           (  void )signal(  SIGINFO,   summaryx );
           (  void )signal(  SIGINT,   terminate );
          
           atexit(  summary );
          #endif
          
           while (  files_cnt-- )
           dd_in(  globals );
          
           dd_close(  globals );
           exit(  0 );
           /* NOTREACHED */
           return 0;
          }
          
          static int
     161  parity(  u_char c )
          {
           int i;
          
           i = c ^ (  c >> 1 ) ^ (  c >> 2 ) ^ (  c >> 3 ) ^
           (  c >> 4 ) ^ (  c >> 5 ) ^ (  c >> 6 ) ^ (  c >> 7 );
           return (  i & 1 );
          }
          
          static void
     171  setup(  rtems_shell_dd_globals* globals )
          {
           u_int cnt;
           struct timeval tv;
          
           if (  in.name == NULL ) {
           in.name = "stdin";
           in.fd = STDIN_FILENO;
           } else {
           in.fd = open(  in.name,   O_RDONLY,   0 );
           if (  in.fd == -1 )
           err(  exit_jump,   1,   "%s",   in.name );
           }
          
           getfdtype(  globals,   &in );
          
           if (  files_cnt > 1 && !(  in.flags & ISTAPE ) )
           errx(  exit_jump,   1,   "files is not supported for non-tape devices" );
          
           if (  out.name == NULL ) {
           /* No way to check for read access here. */
           out.fd = STDOUT_FILENO;
           out.name = "stdout";
           } else {
          #define OFLAGS \
           (  O_CREAT | (  ddflags & (  C_SEEK | C_NOTRUNC ) ? 0 : O_TRUNC ) )
           out.fd = open(  out.name,   O_RDWR | OFLAGS,   DEFFILEMODE );
           /*
           * May not have read access,   so try again with write only.
           * Without read we may have a problem if output also does
           * not support seeks.
           */
           if (  out.fd == -1 ) {
           out.fd = open(  out.name,   O_WRONLY | OFLAGS,   DEFFILEMODE );
           out.flags |= NOREAD;
           }
           if (  out.fd == -1 )
           err(  exit_jump,   1,   "%s",   out.name );
           }
          
           getfdtype(  globals,   &out );
          
           /*
           * Allocate space for the input and output buffers. If not doing
           * record oriented I/O,   only need a single buffer.
           */
           if (  !(  ddflags & (  C_BLOCK | C_UNBLOCK ) ) ) {
           if (  (  in.db = malloc(  out.dbsz + in.dbsz - 1 ) ) == NULL )
           err(  exit_jump,   1,   "input buffer" );
           out.db = in.db;
           } else if (  (  in.db = malloc(  MAX(  in.dbsz,   cbsz ) + cbsz ) ) == NULL ||
           (  out.db = malloc(  out.dbsz + cbsz ) ) == NULL )
           err(  exit_jump,   1,   "output buffer" );
           in.dbp = in.db;
           out.dbp = out.db;
          
           /* Position the input/output streams. */
           if (  in.offset )
           pos_in(  globals );
           if (  out.offset )
           pos_out(  globals );
          
           /*
           * Truncate the output file. If it fails on a type of output file
           * that it should _not_ fail on,   error out.
           */
           if (  (  ddflags & (  C_OF | C_SEEK | C_NOTRUNC ) ) == (  C_OF | C_SEEK ) &&
           out.flags & ISTRUNC )
           if (  ftruncate(  out.fd,   out.offset * out.dbsz ) == -1 )
           err(  exit_jump,   1,   "truncating %s",   out.name );
          
           if (  ddflags & (  C_LCASE | C_UCASE | C_ASCII | C_EBCDIC | C_PARITY ) ) {
           if (  ctab != NULL ) {
           for (  cnt = 0; cnt <= 0377; ++cnt )
           casetab[cnt] = ctab[cnt];
           } else {
           for (  cnt = 0; cnt <= 0377; ++cnt )
           casetab[cnt] = cnt;
           }
           if (  (  ddflags & C_PARITY ) && !(  ddflags & C_ASCII ) ) {
           /*
           * If the input is not EBCDIC,   and we do parity
           * processing,   strip input parity.
           */
           for (  cnt = 200; cnt <= 0377; ++cnt )
           casetab[cnt] = casetab[cnt & 0x7f];
           }
           if (  ddflags & C_LCASE ) {
           for (  cnt = 0; cnt <= 0377; ++cnt )
           casetab[cnt] = tolower(  casetab[cnt] );
           } else if (  ddflags & C_UCASE ) {
           for (  cnt = 0; cnt <= 0377; ++cnt )
           casetab[cnt] = toupper(  casetab[cnt] );
           }
           if (  (  ddflags & C_PARITY ) ) {
           /*
           * This should strictly speaking be a no-op,   but I
           * wonder what funny LANG settings could get us.
           */
           for (  cnt = 0; cnt <= 0377; ++cnt )
           casetab[cnt] = casetab[cnt] & 0x7f;
           }
           if (  (  ddflags & C_PARSET ) ) {
           for (  cnt = 0; cnt <= 0377; ++cnt )
           casetab[cnt] = casetab[cnt] | 0x80;
           }
           if (  (  ddflags & C_PAREVEN ) ) {
           for (  cnt = 0; cnt <= 0377; ++cnt )
           if (  parity(  casetab[cnt] ) )
           casetab[cnt] = casetab[cnt] | 0x80;
           }
           if (  (  ddflags & C_PARODD ) ) {
           for (  cnt = 0; cnt <= 0377; ++cnt )
           if (  !parity(  casetab[cnt] ) )
           casetab[cnt] = casetab[cnt] | 0x80;
           }
          
           ctab = casetab;
           }
          
           (  void )gettimeofday(  &tv,   (  struct timezone * )NULL );
           st.start = tv.tv_sec + tv.tv_usec * 1e-6;
          }
          
     295  static void
          getfdtype(  rtems_shell_dd_globals* globals,   IO *io )
          {
           struct stat sb;
          #if RTEMS_REMOVED
           int type;
          #endif
          
           if (  fstat(  io->fd,   &sb ) == -1 )
           err(  exit_jump,   1,   "%s",   io->name );
           if (  S_ISREG(  sb.st_mode ) )
           io->flags |= ISTRUNC;
          #if RTEMS_REMOVED
           if (  S_ISCHR(  sb.st_mode ) || S_ISBLK(  sb.st_mode ) ) {
           if (  ioctl(  io->fd,   FIODTYPE,   &type ) == -1 ) {
           err(  exit_jump,   1,   "%s",   io->name );
           } else {
           if (  type & D_TAPE )
           io->flags |= ISTAPE;
           else if (  type & (  D_DISK | D_MEM ) )
           io->flags |= ISSEEK;
           if (  S_ISCHR(  sb.st_mode ) && (  type & D_TAPE ) == 0 )
           io->flags |= ISCHR;
           }
           return;
           }
          #else
           io->flags |= ISSEEK;
          #endif
           errno = 0;
           if (  lseek(  io->fd,   (  off_t )0,   SEEK_CUR ) == -1 && errno == ESPIPE )
           io->flags |= ISPIPE;
           else
           io->flags |= ISSEEK;
          }
          
     331  static void
          dd_in(  rtems_shell_dd_globals* globals )
          {
           ssize_t n;
          
           for (  ;; ) {
           switch (  cpy_cnt ) {
           case -1: /* count=0 was specified */
           return;
           case 0:
           break;
           default:
           if (  st.in_full + st.in_part >= (  uintmax_t )cpy_cnt )
           return;
           break;
           }
          
           /*
           * Zero the buffer first if sync; if doing block operations,  
           * use spaces.
           */
           if (  ddflags & C_SYNC ) {
           if (  ddflags & C_FILL )
           memset(  in.dbp,   fill_char,   in.dbsz );
           else if (  ddflags & (  C_BLOCK | C_UNBLOCK ) )
           memset(  in.dbp,   ' ',   in.dbsz );
           else
           memset(  in.dbp,   0,   in.dbsz );
           }
          
           n = read(  in.fd,   in.dbp,   in.dbsz );
           if (  n == 0 ) {
           in.dbrcnt = 0;
           return;
           }
          
           /* Read error. */
           if (  n == -1 ) {
           /*
           * If noerror not specified,   die. POSIX requires that
           * the warning message be followed by an I/O display.
           */
           if (  !(  ddflags & C_NOERROR ) )
           err(  exit_jump,   1,   "%s",   in.name );
           warn(  "%s",   in.name );
           summary(  globals );
          
           /*
           * If it's a seekable file descriptor,   seek past the
           * error. If your OS doesn't do the right thing for
           * raw disks this section should be modified to re-read
           * in sector size chunks.
           */
           if (  in.flags & ISSEEK &&
           lseek(  in.fd,   (  off_t )in.dbsz,   SEEK_CUR ) )
           warn(  "%s",   in.name );
          
           /* If sync not specified,   omit block and continue. */
           if (  !(  ddflags & C_SYNC ) )
           continue;
          
           /* Read errors count as full blocks. */
           in.dbcnt += in.dbrcnt = in.dbsz;
           ++st.in_full;
          
           /* Handle full input blocks. */
           } else if (  (  size_t )n == in.dbsz ) {
           in.dbcnt += in.dbrcnt = n;
           ++st.in_full;
          
           /* Handle partial input blocks. */
           } else {
           /* If sync,   use the entire block. */
           if (  ddflags & C_SYNC )
           in.dbcnt += in.dbrcnt = in.dbsz;
           else
           in.dbcnt += in.dbrcnt = n;
           ++st.in_part;
           }
          
           /*
           * POSIX states that if bs is set and no other conversions
           * than noerror,   notrunc or sync are specified,   the block
           * is output without buffering as it is read.
           */
           if (  ddflags & C_BS ) {
           out.dbcnt = in.dbcnt;
           dd_out(  globals,   1 );
           in.dbcnt = 0;
           continue;
           }
          
           if (  ddflags & C_SWAB ) {
           if (  (  n = in.dbrcnt ) & 1 ) {
           ++st.swab;
           --n;
           }
           swab(  in.dbp,   in.dbp,   (  size_t )n );
           }
          
           in.dbp += in.dbrcnt;
           (  *cfunc )(  globals );
           }
          }
          
          /*
           * Clean up any remaining I/O and flush output. If necessary,   the output file
           * is truncated.
           */
     440  static void
          dd_close(  rtems_shell_dd_globals* globals )
          {
           if (  cfunc == def )
           def_close(  globals );
           else if (  cfunc == block )
           block_close(  globals );
           else if (  cfunc == unblock )
           unblock_close(  globals );
           if (  ddflags & C_OSYNC && out.dbcnt && out.dbcnt < out.dbsz ) {
           if (  ddflags & C_FILL )
           memset(  out.dbp,   fill_char,   out.dbsz - out.dbcnt );
           else if (  ddflags & (  C_BLOCK | C_UNBLOCK ) )
           memset(  out.dbp,   ' ',   out.dbsz - out.dbcnt );
           else
           memset(  out.dbp,   0,   out.dbsz - out.dbcnt );
           out.dbcnt = out.dbsz;
           }
           if (  out.dbcnt || pending )
           dd_out(  globals,   1 );
          }
          
     462  void
          dd_out(  rtems_shell_dd_globals* globals,   int force )
          {
           u_char *outp;
           size_t cnt,   i,   n;
           ssize_t nw;
           static int warned;
           int sparse;
          
           /*
           * Write one or more blocks out. The common case is writing a full
           * output block in a single write; increment the full block stats.
           * Otherwise,   we're into partial block writes. If a partial write,  
           * and it's a character device,   just warn. If a tape device,   quit.
           *
           * The partial writes represent two cases. 1: Where the input block
           * was less than expected so the output block was less than expected.
           * 2: Where the input block was the right size but we were forced to
           * write the block in multiple chunks. The original versions of dd(  1 )
           * never wrote a block in more than a single write,   so the latter case
           * never happened.
           *
           * One special case is if we're forced to do the write -- in that case
           * we play games with the buffer size,   and it's usually a partial write.
           */
           outp = out.db;
           for (  n = force ? out.dbcnt : out.dbsz;; n = out.dbsz ) {
           for (  cnt = n;; cnt -= nw ) {
           sparse = 0;
           if (  ddflags & C_SPARSE ) {
           sparse = 1; /* Is buffer sparse? */
           for (  i = 0; i < cnt; i++ )
           if (  outp[i] != 0 ) {
           sparse = 0;
           break;
           }
           }
           if (  sparse && !force ) {
           pending += cnt;
           nw = cnt;
           } else {
           if (  pending != 0 ) {
           if (  force )
           pending--;
           if (  lseek(  out.fd,   pending,   SEEK_CUR ) ==
           -1 )
           err(  exit_jump,   2,   "%s: seek error creating sparse file",  
           out.name );
           if (  force )
           write(  out.fd,   outp,   1 );
           pending = 0;
           }
           if (  cnt )
           nw = write(  out.fd,   outp,   cnt );
           else
           return;
           }
          
           if (  nw <= 0 ) {
           if (  nw == 0 )
           errx(  exit_jump,   1,   "%s: end of device",   out.name );
           if (  errno != EINTR )
           err(  exit_jump,   1,   "%s",   out.name );
           nw = 0;
           }
           outp += nw;
           st.bytes += nw;
           if (  (  size_t )nw == n ) {
           if (  n != out.dbsz )
           ++st.out_part;
           else
           ++st.out_full;
           break;
           }
           ++st.out_part;
           if (  (  size_t )nw == cnt )
           break;
           if (  out.flags & ISTAPE )
           errx(  exit_jump,   1,   "%s: short write on tape device",  
           out.name );
           if (  out.flags & ISCHR && !warned ) {
           warned = 1;
           warnx(  "%s: short write on character device",  
           out.name );
           }
           }
           if (  (  out.dbcnt -= n ) < out.dbsz )
           break;
           }
          
           /* Reassemble the output block. */
           if (  out.dbcnt )
           (  void )memmove(  out.db,   out.dbp - out.dbcnt,   out.dbcnt );
           out.dbp = out.db + out.dbcnt;
          }
          
          rtems_shell_cmd_t rtems_shell_DD_Command = {
           "dd",   /* name */
           "dd [OPERAND]...",   /* usage */
           "files",   /* topic */
           rtems_shell_main_dd,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_debugrfs.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_debugrfs.c,  v 1.1 2010/02/19 03:23:11 ccj Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include <rtems/shellconfig.h>
          #include <rtems/rtems-rfs-shell.h>
          #include <rtems/fsmount.h>
          #include "internal.h"
          
          #define OPTIONS "[-h]"
          
          rtems_shell_cmd_t rtems_shell_DEBUGRFS_Command = {
           "debugrfs",   /* name */
           "debugrfs " OPTIONS,   /* usage */
           "files",   /* topic */
           rtems_shell_debugrfs,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_dir.c

       1  /*
           * DIR Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_dir.c,  v 1.3 2007/12/17 22:39:28 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
          rtems_shell_alias_t rtems_shell_DIR_Alias = {
           "ls",   /* command */
           "dir" /* alias */
          };

libmisc/shell/main_echo.c

       1  /* $NetBSD: echo.c,  v 1.12 2005/02/06 04:43:43 perry Exp $ */
          
          /*-
           * Copyright (  c ) 1991,   1993
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Kenneth Almquist.
           *
           * 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. 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.
           *
           * @(  # )echo.c 8.1 (  Berkeley ) 5/31/93
           */
          
          /*
           * Echo command.
           *
           * echo is steeped in tradition - several of them!
           * netbsd has supported 'echo [-n | -e] args' in spite of -e not being
           * documented anywhere.
           * Posix requires that -n be supported,   output from strings containing
           * \ is implementation defined
           * The Single Unix Spec requires that \ escapes be treated as if -e
           * were set,   but that -n not be treated as an option.
           * (  ksh supports 'echo [-eEn] args',   but not -- so that it is actually
           * impossible to actually output '-n' )
           *
           * It is suggested that 'printf "%b" "string"' be used to get \ sequences
           * expanded. printf is now a builtin of netbsd's sh and csh.
           */
          
          /*
           * $Id: main_echo.c,  v 1.1 2008/03/05 02:49:35 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
          
          
      73  int rtems_shell_main_echo(  
           int argc,  
           char *argv[]
           )
          {
           char **ap;
           char *p;
           char c;
           int count;
           int nflag = 0;
           int eflag = 0;
          
           ap = argv;
           if (  argc )
           ap++;
          
           if (  (  p = *ap ) != NULL ) {
           if (  !strcmp(  p,   "-n" ) ) {
           nflag = 1;
           ap++;
           } else if (  !strcmp(  p,   "-e" ) ) {
           eflag = 1;
           ap++;
           }
           }
          
           while (  (  p = *ap++ ) != NULL ) {
           while (  (  c = *p++ ) != '\0' ) {
           if (  c == '\\' && eflag ) {
           switch (  *p++ ) {
           case 'a': c = '\a'; break; /* bell */
           case 'b': c = '\b'; break;
           case 'c': return 0; /* exit */
           case 'e': c = 033; break; /* escape */
           case 'f': c = '\f'; break;
           case 'n': c = '\n'; break;
           case 'r': c = '\r'; break;
           case 't': c = '\t'; break;
           case 'v': c = '\v'; break;
           case '\\': break; /* c = '\\' */
           case '0':
           c = 0;
           count = 3;
           while (  --count >= 0 && (  unsigned )(  *p - '0' ) < 8 )
           c = (  c << 3 ) + (  *p++ - '0' );
           break;
           default:
           /* Output the '/' and char following */
           p--;
           break;
           }
           }
           putchar(  c );
           }
           if (  *ap )
           putchar(  ' ' );
           }
           if (  ! nflag )
           putchar(  '\n' );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_ECHO_Command = {
           "echo",   /* name */
           "echo [args]",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_echo,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_exit.c

       1  /*
           * exit Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_exit.c,  v 1.3 2007/12/17 22:39:28 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
          rtems_shell_alias_t rtems_shell_EXIT_Alias = {
           "logoff",   /* command */
           "exit" /* alias */
          };

libmisc/shell/main_getenv.c

       1  /*
           * Get an environment vairable.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <stdlib.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      19  int rtems_shell_main_getenv(  int argc,   char *argv[] )
          {
           char* string;
          
           if (  argc != 2 )
           {
           printf (  "error: only argument is the variable name\n" );
           return 1;
           }
          
           string = getenv (  argv[1] );
          
           if (  !string )
           {
           printf (  "error: %s not found\n",   argv[1] );
           return 1;
           }
          
           printf (  "%s\n",   string );
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_GETENV_Command = {
           "getenv",   /* name */
           "getenv [var]",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_getenv,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_halt.c

       1  /*
           * Halt Command Implementation
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: main_halt.c,  v 1.2 2009/04/14 13:41:33 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      24  int rtems_shell_main_halt(  
           int argc __attribute__(  (  unused ) ),  
           char *argv[] __attribute__(  (  unused ) )
           )
          {
           exit(  0 );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_HALT_Command = {
           "halt",   /* name */
           "halt",   /* usage */
           "rtems",   /* topic */
           rtems_shell_main_halt,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_help.c

       1  /*
           *
           * Shell Help Command
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_help.c,  v 1.6 2009/07/22 18:18:41 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <time.h>
          
          #include <rtems.h>
          #include <rtems/error.h>
          #include <rtems/system.h>
          #include <rtems/shell.h>
          
          #include "internal.h"
          #include <string.h>
          
          /*
           * show the help for one command.
           */
      30  int rtems_shell_help_cmd(  
           rtems_shell_cmd_t *shell_cmd
           )
          {
           const char * pc;
           int col,  line;
          
           printf(  "%-12.12s - ",  shell_cmd->name );
           col = 14;
           line = 1;
           if (  shell_cmd->alias ) {
           printf(  "is an <alias> for command '%s'",  shell_cmd->alias->name );
           } else if (  shell_cmd->usage ) {
           pc = shell_cmd->usage;
           while (  *pc ) {
           switch(  *pc ) {
           case '\r':
           break;
           case '\n':
           putchar(  '\n' );
           col = 0;
           break;
           default:
           putchar(  *pc );
           col++;
           break;
           }
           pc++;
           if (  col>78 ) { /* What daring... 78?*/
           if (  *pc ) {
           putchar(  '\n' );
           col = 0;
           }
           }
           if (  !col && *pc ) {
           printf(  " " );
           col = 12;line++;
           }
           }
           }
           puts(  "" );
           return line;
          }
          
          /*
           * show the help. The first command implemented.
           * Can you see the header of routine? Known?
           * The same with all the commands....
           */
      79  int rtems_shell_help(  
           int argc,  
           char * argv[]
           )
          {
           int col,  line,  arg;
           rtems_shell_topic_t *topic;
           rtems_shell_cmd_t * shell_cmd = rtems_shell_first_cmd;
          
           if (  argc<2 ) {
           printf(  "help: (  'r' repeat last cmd - 'e' edit last cmd )\n"
           " TOPIC? The topics are\n" );
           topic = rtems_shell_first_topic;
           col = 0;
           while (  topic ) {
           if (  !col ){
           col = printf(  " %s",  topic->topic );
           } else {
           if (  (  col+strlen(  topic->topic )+2 )>78 ){
           printf(  "\n" );
           col = printf(  " %s",  topic->topic );
           } else {
           col+= printf(  ",   %s",  topic->topic );
           }
           }
           topic = topic->next;
           }
           printf(  "\n" );
           return 1;
           }
           line = 0;
           for (  arg = 1;arg<argc;arg++ ) {
           if (  line>16 ) {
           printf(  "Press any key to continue..." );getchar(   );
           printf(  "\n" );
           line = 0;
           }
           topic = rtems_shell_lookup_topic(  argv[arg] );
           if (  !topic ){
           if (  (  shell_cmd = rtems_shell_lookup_cmd(  argv[arg] ) ) == NULL ) {
           printf(  "help: topic or cmd '%s' not found. Try <help> alone for a list\n",  
           argv[arg] );
           line++;
           } else {
           line+= rtems_shell_help_cmd(  shell_cmd );
           }
           continue;
           }
           printf(  "help: list for the topic '%s'\n",  argv[arg] );
           line++;
           while (  shell_cmd ) {
           if (  !strcmp(  topic->topic,  shell_cmd->topic ) )
           line+= rtems_shell_help_cmd(  shell_cmd );
           if (  line>16 ) {
           printf(  "Press any key to continue..." );
           getchar(   );
           printf(  "\n" );
           line = 0;
           }
           shell_cmd = shell_cmd->next;
           }
           }
           puts(  "" );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_HELP_Command = {
           "help",   /* name */
           "help [topic] # list of usage of commands",   /* usage */
           "help",   /* topic */
           rtems_shell_help,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_hexdump.c

       1  /*
           * Copyright (  c ) 1989,   1993
           * The Regents of the University of California. 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.
           * 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.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef lint
          static const char copyright[] =
          "@(  # ) Copyright (  c ) 1989,   1993\n\
           The Regents of the University of California. All rights reserved.\n";
          #endif /* not lint */
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )hexdump.c 8.1 (  Berkeley ) 6/6/93";
          #include <sys/cdefs.h>
      48  __FBSDID(  "$FreeBSD: src/usr.bin/hexdump/hexdump.c,  v 1.7 2002/09/04 23:29:01 dwmalone Exp $" );
          #endif
          #endif /* not lint */
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          
          #include <sys/types.h>
          #include <locale.h>
          #include <stdlib.h>
          #include <stdio.h>
          #include <string.h>
          #ifdef HAVE_STRINGS_H
          #include <strings.h>
          #endif
          #include "hexdump.h"
          
          #if RTEMS_REMOVED
          FS *fshead; /* head of format strings */
          int blocksize; /* data block size */
          int exitval; /* final exit value */
          int length = -1; /* max bytes to read */
          #endif
          
          void
      74  rtems_shell_hexdump_exit (  rtems_shell_hexdump_globals* globals,   int code )
          {
           globals->exit_code = code;
           longjmp (  globals->exit_jmp,   1 );
          }
          
      80  static int main_hexdump(  rtems_shell_hexdump_globals* globals,   int argc,   char *argv[] );
          
          int
      83  rtems_shell_main_hexdump(  int argc,   char *argv[] )
          {
           rtems_shell_hexdump_globals hexdump_globals;
           rtems_shell_hexdump_globals* globals = &hexdump_globals;
           memset (  globals,   0,   sizeof (  hexdump_globals ) );
           vflag = FIRST;
           ateof = 1;
           hexdump_globals.exit_code = 1;
           if (  setjmp (  hexdump_globals.exit_jmp ) == 0 )
           hexdump_globals.exit_code = main_hexdump (  globals,   argc,   argv );
           if (  curp )
           free (  curp );
           if (  savp )
           free (  savp );
           while (  fshead )
           {
           FS* nextfs = fshead->nextfs;
           while (  fshead->nextfu )
           {
           FU* nextfu = fshead->nextfu->nextfu;
           if (  fshead->nextfu->fmt )
           free(  fshead->nextfu->fmt );
           while (  fshead->nextfu->nextpr )
           {
           PR* nextpr = fshead->nextfu->nextpr->nextpr;
           if (  (  (  fshead->nextfu->nextpr->flags & F_TEXT ) == 0 ) &&
           fshead->nextfu->nextpr->fmt )
           free(  fshead->nextfu->nextpr->fmt );
           free(  fshead->nextfu->nextpr );
           fshead->nextfu->nextpr = nextpr;
           }
           free(  fshead->nextfu );
           fshead->nextfu = nextfu;
           }
           free(  fshead );
           fshead = nextfs;
           }
           if (  hdstdin )
           {
           fclose (  hdstdin );
           free (  hdstdin );
           }
           return hexdump_globals.exit_code;
          }
          
          int
     129  main_hexdump(  rtems_shell_hexdump_globals* globals,   int argc,   char *argv[] )
          {
           FS *tfs;
           char *p;
          
          #if RTEMS_REMOVED
           (  void )setlocale(  LC_ALL,   "" );
          #endif
          
           if (  !(  p = rindex(  argv[0],   'o' ) ) || strcmp(  p,   "od" ) )
           newsyntax(  globals,   argc,   &argv );
           else
           oldsyntax(  globals,   argc,   &argv );
          
           /* figure out the data block size */
           for (  blocksize = 0,   tfs = fshead; tfs; tfs = tfs->nextfs ) {
           tfs->bcnt = size(  globals,   tfs );
           if (  blocksize < tfs->bcnt )
           blocksize = tfs->bcnt;
           }
           /* rewrite the rules,   do syntax checking */
           for (  tfs = fshead; tfs; tfs = tfs->nextfs )
           rewrite(  globals,   tfs );
          
           (  void )next(  globals,   argv );
           display(  globals );
           exit(  exitval );
           return exitval;
          }
          
          rtems_shell_cmd_t rtems_shell_HEXDUMP_Command = {
           "hexdump",   /* name */
           "hexdump [-bcCdovx] [-e fmt] [-f fmt_file] [-n length]\n" /* usage */
           " [-s skip] [file ...]",  
           "files",   /* topic */
           rtems_shell_main_hexdump,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };
          

libmisc/shell/main_id.c

       1  /*
           * ID Command Implementation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_id.c,  v 1.5 2009/01/02 13:01:21 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          #include <pwd.h>
          #include <grp.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      31  int rtems_shell_main_id(  
           int argc __attribute__(  (  unused ) ),  
           char *argv[] __attribute__(  (  unused ) )
           )
          {
           struct passwd *pwd;
           struct group *grp;
          
           pwd = getpwuid(  getuid(   ) );
           grp = getgrgid(  getgid(   ) );
           printf(  
           "uid=%d(  %s ),  gid=%d(  %s ),  ",  
           getuid(   ),  
           (  pwd ) ? pwd->pw_name : "",  
           getgid(   ),  
           (  grp ) ? grp->gr_name : ""
            );
           pwd = getpwuid(  geteuid(   ) );
           grp = getgrgid(  getegid(   ) );
           printf(  
           "euid=%d(  %s ),  egid=%d(  %s )\n",  
           geteuid(   ),  
           (  pwd ) ? pwd->pw_name : "",  
           getegid(   ),  
           (  grp ) ? grp->gr_name : ""
            );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_ID_Command = {
           "id",   /* name */
           "show uid,   gid,   euid,   and egid",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_id,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_ifconfig.c

       1  /*
           * IFCONFIG Command Implmentation
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_ifconfig.c,  v 1.5 2010/03/12 16:26:15 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <string.h>
          #include <ctype.h>
          #include <errno.h>
          
          #include <netinet/in.h>
          #include <sys/types.h>
          #include <sys/socket.h>
          #include <arpa/inet.h>
          #include <net/if.h>
          
          
          #include <rtems.h>
          #include <rtems/rtems_bsdnet.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      32  int rtems_shell_main_ifconfig(  
           int argc,  
           char *argv[]
           )
          {
           struct sockaddr_in ipaddr;
           struct sockaddr_in dstaddr;
           struct sockaddr_in netmask;
           struct sockaddr_in broadcast;
           char *iface;
           int f_ip = 0;
           int f_ptp = 0;
           int f_netmask = 0;
           int f_up = 0;
           int f_down = 0;
           int f_bcast = 0;
           int cur_idx;
           int rc;
           int flags;
          
           memset(  &ipaddr,   0,   sizeof(  ipaddr ) );
           memset(  &dstaddr,   0,   sizeof(  dstaddr ) );
           memset(  &netmask,   0,   sizeof(  netmask ) );
           memset(  &broadcast,   0,   sizeof(  broadcast ) );
          
           ipaddr.sin_len = sizeof(  ipaddr );
           ipaddr.sin_family = AF_INET;
          
           dstaddr.sin_len = sizeof(  dstaddr );
           dstaddr.sin_family = AF_INET;
          
           netmask.sin_len = sizeof(  netmask );
           netmask.sin_family = AF_INET;
          
           broadcast.sin_len = sizeof(  broadcast );
           broadcast.sin_family = AF_INET;
          
           cur_idx = 0;
           if (  argc <= 1 ) {
           /* display all interfaces */
           iface = NULL;
           cur_idx += 1;
           } else {
           iface = argv[1];
           if (  isdigit(  (  unsigned char )*argv[2] ) ) {
           if (  inet_pton(  AF_INET,   argv[2],   &ipaddr.sin_addr ) < 0 ) {
           printf(  "bad ip address: %s\n",   argv[2] );
           return 0;
           }
           f_ip = 1;
           cur_idx += 3;
           } else {
           cur_idx += 2;
           }
           }
          
           if (  (  f_down !=0 ) && (  f_ip != 0 ) ) {
           f_up = 1;
           }
          
           while(  argc > cur_idx ) {
           if (  strcmp(  argv[cur_idx],   "up" ) == 0 ) {
           f_up = 1;
           if (  f_down != 0 ) {
           printf(  "Can't make interface up and down\n" );
           }
           } else if(  strcmp(  argv[cur_idx],   "down" ) == 0 ) {
           f_down = 1;
           if (  f_up != 0 ) {
           printf(  "Can't make interface up and down\n" );
           }
           } else if(  strcmp(  argv[cur_idx],   "netmask" ) == 0 ) {
           if (  (  cur_idx + 1 ) >= argc ) {
           printf(  "No netmask address\n" );
           return -1;
           }
           if (  inet_pton(  AF_INET,   argv[cur_idx+1],   &netmask.sin_addr ) < 0 ) {
           printf(  "bad netmask: %s\n",   argv[cur_idx] );
           return -1;
           }
           f_netmask = 1;
           cur_idx += 1;
           } else if(  strcmp(  argv[cur_idx],   "broadcast" ) == 0 ) {
           if (  (  cur_idx + 1 ) >= argc ) {
           printf(  "No broadcast address\n" );
           return -1;
           }
           if (  inet_pton(  AF_INET,   argv[cur_idx+1],   &broadcast.sin_addr ) < 0 ) {
           printf(  "bad broadcast: %s\n",   argv[cur_idx] );
           return -1;
           }
           f_bcast = 1;
           cur_idx += 1;
           } else if(  strcmp(  argv[cur_idx],   "pointopoint" ) == 0 ) {
           if (  (  cur_idx + 1 ) >= argc ) {
           printf(  "No pointopoint address\n" );
           return -1;
           }
           if (  inet_pton(  AF_INET,   argv[cur_idx+1],   &dstaddr.sin_addr ) < 0 ) {
           printf(  "bad pointopoint: %s\n",   argv[cur_idx] );
           return -1;
           }
           f_ptp = 1;
           cur_idx += 1;
           } else {
           printf(  "Bad parameter: %s\n",   argv[cur_idx] );
           return -1;
           }
           cur_idx += 1;
           }
          
           printf(  "ifconfig " );
           if (  iface != NULL ) {
           printf(  "%s ",   iface );
           if (  f_ip != 0 ) {
           char str[256];
           inet_ntop(  AF_INET,   &ipaddr.sin_addr,   str,   256 );
           printf(  "%s ",   str );
           }
          
           if (  f_netmask != 0 ) {
           char str[256];
           inet_ntop(  AF_INET,   &netmask.sin_addr,   str,   256 );
           printf(  "netmask %s ",   str );
           }
          
           if (  f_bcast != 0 ) {
           char str[256];
           inet_ntop(  AF_INET,   &broadcast.sin_addr,   str,   256 );
           printf(  "broadcast %s ",   str );
           }
          
           if (  f_ptp != 0 ) {
           char str[256];
           inet_ntop(  AF_INET,   &dstaddr.sin_addr,   str,   256 );
           printf(  "pointopoint %s ",   str );
           }
          
           if (  f_up != 0 ) {
           printf(  "up\n" );
           } else if (  f_down != 0 ) {
           printf(  "down\n" );
           } else {
           printf(  "\n" );
           }
           }
          
           if (  (  iface == NULL ) || (  (  f_ip == 0 ) && (  f_down == 0 ) && (  f_up == 0 ) ) ) {
           rtems_bsdnet_show_if_stats(   );
           return 0;
           }
          
           flags = 0;
           if (  f_netmask ) {
           rc = rtems_bsdnet_ifconfig(  iface,   SIOCSIFNETMASK,   &netmask );
           if (  rc < 0 ) {
           printf(  "Could not set netmask: %s\n",   strerror(  errno ) );
           return -1;
           }
           }
          
           if (  f_bcast ) {
           rc = rtems_bsdnet_ifconfig(  iface,   SIOCSIFBRDADDR,   &broadcast );
           if (  rc < 0 ) {
           printf(  "Could not set broadcast: %s\n",   strerror(  errno ) );
           return -1;
           }
           }
          
           if (  f_ptp ) {
           rc = rtems_bsdnet_ifconfig(  iface,   SIOCSIFDSTADDR,   &dstaddr );
           if (  rc < 0 ) {
           printf(  "Could not set destination address: %s\n",   strerror(  errno ) );
           return -1;
           }
           flags |= IFF_POINTOPOINT;
           }
          
           /* This must come _after_ setting the netmask,   broadcast addresses */
           if (  f_ip ) {
           rc = rtems_bsdnet_ifconfig(  iface,   SIOCSIFADDR,   &ipaddr );
           if (  rc < 0 ) {
           printf(  "Could not set IP address: %s\n",   strerror(  errno ) );
           return -1;
           }
           }
          
           if (  f_up != 0 ) {
           flags |= IFF_UP;
           }
          
           if (  f_down != 0 ) {
           printf(  "Warning: taking interfaces down is not supported\n" );
           }
          
           rc = rtems_bsdnet_ifconfig(  iface,   SIOCSIFFLAGS,   &flags );
           if (  rc < 0 ) {
           printf(  "Could not set interface flags: %s\n",   strerror(  errno ) );
           return -1;
           }
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_IFCONFIG_Command = {
           "ifconfig",   /* name */
           "TBD",   /* usage */
           "network",   /* topic */
           rtems_shell_main_ifconfig,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_ln.c

       1  /* $NetBSD: ln.c,  v 1.34 2008/07/20 00:52:40 lukem Exp $ */
          
          /*
           * Copyright (  c ) 1987,   1993,   1994
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if 0
          #ifndef lint
      38  __COPYRIGHT(  "@(  # ) Copyright (  c ) 1987,   1993,   1994\
           The Regents of the University of California. All rights reserved." );
          #endif /* not lint */
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )ln.c 8.2 (  Berkeley ) 3/31/94";
          #else
      46  __RCSID(  "$NetBSD: ln.c,  v 1.34 2008/07/20 00:52:40 lukem Exp $" );
          #endif
          #endif /* not lint */
          #endif
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          #define __need_getopt_newlib
          #include <getopt.h>
          
          #include <sys/cdefs.h>
          #include <sys/param.h>
          #include <sys/stat.h>
          
          #include <err.h>
          #include <errno.h>
          #include <locale.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          
          #include <setjmp.h>
          
          typedef struct {
           int fflag; /* Unlink existing files. */
           int hflag; /* Check new name for symlink first. */
           int iflag; /* Interactive mode. */
           int sflag; /* Symbolic,   not hard,   link. */
           int vflag; /* Verbose output */
           char linkch;
          
           int exit_code;
           jmp_buf exit_jmp;
          } rtems_shell_ln_globals;
          
          #define fflag globals->fflag
          #define hflag globals->hflag
          #define iflag globals->iflag
          #define sflag globals->sflag
          #define vflag globals->vflag
          #define linkch globals->linkch
          
          #define exit_jump &(  globals->exit_jmp )
          
          #define exit(  ec ) rtems_shell_ln_exit(  globals,   ec )
          
      94  static int main_ln(  rtems_shell_ln_globals* ,   int,   char *[] );
          
          static void
      97  rtems_shell_ln_exit (  rtems_shell_ln_globals* globals,   int code )
          {
           globals->exit_code = code;
           longjmp (  globals->exit_jmp,   1 );
          }
          
     103  static int main_ln(  rtems_shell_ln_globals* globals,   int argc,   char *argv[] );
          
          int
     106  rtems_shell_main_ln(  int argc,   char *argv[] )
          {
           rtems_shell_ln_globals ln_globals;
           rtems_shell_ln_globals* globals = &ln_globals;
           memset (  globals,   0,   sizeof (  ln_globals ) );
           ln_globals.exit_code = 1;
           if (  setjmp (  ln_globals.exit_jmp ) == 0 )
           return main_ln (  globals,   argc,   argv );
           return ln_globals.exit_code;
          }
          
          #if RTEMS_REMOVED
          int fflag; /* Unlink existing files. */
          int hflag; /* Check new name for symlink first. */
          int iflag; /* Interactive mode. */
          int sflag; /* Symbolic,   not hard,   link. */
          int vflag; /* Verbose output */
          
           /* System link call. */
          int (  *linkf )(  const char *,   const char * );
          char linkch;
          #endif
          
          int (  *linkf )(  const char *,   const char * );
          
     131  static int linkit(  rtems_shell_ln_globals* ,   const char *,   const char *,   int );
     132  static void usage(  rtems_shell_ln_globals*  );
          
          static int
     135  main_ln(  rtems_shell_ln_globals* globals,   int argc,   char *argv[] )
          {
           struct stat sb;
           int ch,   exitval;
           char *sourcedir;
          
           struct getopt_data getopt_reent;
           memset(  &getopt_reent,   0,   sizeof(  getopt_data ) );
          
          #if RTEMS_REMOVED
           setprogname(  argv[0] );
           (  void )setlocale(  LC_ALL,   "" );
          #endif
          
           while (  (  ch = getopt_r(  argc,   argv,   "fhinsv",   &getopt_reent ) ) != -1 )
           switch (  ch ) {
           case 'f':
           fflag = 1;
           iflag = 0;
           break;
           case 'h':
           case 'n':
           hflag = 1;
           break;
           case 'i':
           iflag = 1;
           fflag = 0;
           break;
           case 's':
           sflag = 1;
           break;
           case 'v':
           vflag = 1;
           break;
           case '?':
           default:
           usage(  globals );
           /* NOTREACHED */
           }
          
           argv += getopt_reent.optind;
           argc -= getopt_reent.optind;
          
           if (  sflag ) {
           linkf = symlink;
           linkch = '-';
           } else {
           linkf = link;
           linkch = '=';
           }
          
           switch(  argc ) {
           case 0:
           usage(  globals );
           /* NOTREACHED */
           case 1: /* ln target */
           exit(  linkit(  globals,   argv[0],   ".",   1 ) );
           /* NOTREACHED */
           case 2: /* ln target source */
           exit(  linkit(  globals,   argv[0],   argv[1],   0 ) );
           /* NOTREACHED */
           }
          
           /* ln target1 target2 directory */
           sourcedir = argv[argc - 1];
           if (  hflag && lstat(  sourcedir,   &sb ) == 0 && S_ISLNK(  sb.st_mode ) ) {
           /* we were asked not to follow symlinks,   but found one at
           the target--simulate "not a directory" error */
           errno = ENOTDIR;
           err(  exit_jump,   EXIT_FAILURE,   "%s",   sourcedir );
           /* NOTREACHED */
           }
           if (  stat(  sourcedir,   &sb ) ) {
           err(  exit_jump,   EXIT_FAILURE,   "%s",   sourcedir );
           /* NOTREACHED */
           }
           if (  !S_ISDIR(  sb.st_mode ) ) {
           usage(  globals );
           /* NOTREACHED */
           }
           for (  exitval = 0; *argv != sourcedir; ++argv )
           exitval |= linkit(  globals,   *argv,   sourcedir,   1 );
           exit(  exitval );
           /* NOTREACHED */
           return 0;
          }
          
          int
     223  linkit(  rtems_shell_ln_globals* globals,   const char *source,   const char *target,   int isdir )
          {
           struct stat sb;
           const char *p;
           char path[MAXPATHLEN];
           int ch,   exists,   first;
          
           if (  !sflag ) {
           /* If target doesn't exist,   quit now. */
           if (  stat(  target,   &sb ) ) {
           warn(  "%s",   target );
           return (  1 );
           }
           }
          
           /* If the source is a directory (  and not a symlink if hflag ),  
           append the target's name. */
           if (  isdir ||
           (  !lstat(  source,   &sb ) && S_ISDIR(  sb.st_mode ) ) ||
           (  !hflag && !stat(  source,   &sb ) && S_ISDIR(  sb.st_mode ) ) ) {
           if (  (  p = strrchr(  target,   '/' ) ) == NULL )
           p = target;
           else
           ++p;
           (  void )snprintf(  path,   sizeof(  path ),   "%s/%s",   source,   p );
           source = path;
           }
          
           exists = !lstat(  source,   &sb );
          
           /*
           * If the file exists,   then unlink it forcibly if -f was specified
           * and interactively if -i was specified.
           */
           if (  fflag && exists ) {
           if (  unlink(  source ) ) {
           warn(  "%s",   source );
           return (  1 );
           }
           } else if (  iflag && exists ) {
           fflush(  stdout );
           (  void )fprintf(  stderr,   "replace %s? ",   source );
          
           first = ch = getchar(   );
           while (  ch != '\n' && ch != EOF )
           ch = getchar(   );
           if (  first != 'y' && first != 'Y' ) {
           (  void )fprintf(  stderr,   "not replaced\n" );
           return (  1 );
           }
          
           if (  unlink(  source ) ) {
           warn(  "%s",   source );
           return (  1 );
           }
           }
          
           /* Attempt the link. */
           if (  (  *linkf )(  target,   source ) ) {
           warn(  "%s",   source );
           return (  1 );
           }
           if (  vflag )
           (  void )printf(  "%s %c> %s\n",   source,   linkch,   target );
          
           return (  0 );
          }
          
          void
     292  usage(  rtems_shell_ln_globals* globals )
          {
          #define getprogname(   ) "ln"
           (  void )fprintf(  stderr,  
           "usage:\t%s [-fhinsv] file1 file2\n\t%s [-fhinsv] file ... directory\n",  
           getprogname(   ),   getprogname(   ) );
           exit(  1 );
           /* NOTREACHED */
          }
          
          rtems_shell_cmd_t rtems_shell_LN_Command = {
           "ln",   /* name */
           "ln ln [-fhinsv] source_file [target_file]",   /* usage */
           "files",   /* topic */
           rtems_shell_main_ln,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_logoff.c

       1  /*
           * LOGOFF Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_logoff.c,  v 1.6 2009/01/02 13:01:21 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      25  int rtems_shell_main_logoff(  
           int argc __attribute__(  (  unused ) ),  
           char *argv[] __attribute__(  (  unused ) )
           )
          {
           printf(  "logoff from the system..." );
          
           rtems_current_shell_env->exit_shell = true;
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_LOGOFF_Command = {
           "logoff",   /* name */
           "logoff from the system",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_logoff,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_ls.c

       1  /* $NetBSD: ls.c,  v 1.58 2005/10/26 02:24:22 jschauma Exp $ */
          
          /*
           * Copyright (  c ) 1989,   1993,   1994
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Michael Fischbein.
           *
           * 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. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if 0
          #include <sys/cdefs.h>
          #ifndef lint
      42  __COPYRIGHT(  "@(  # ) Copyright (  c ) 1989,   1993,   1994\n\
           The Regents of the University of California. All rights reserved.\n" );
          #endif /* not lint */
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )ls.c 8.7 (  Berkeley ) 8/5/94";
          #else
      50  __RCSID(  "$NetBSD: ls.c,  v 1.58 2005/10/26 02:24:22 jschauma Exp $" );
          #endif
          #endif /* not lint */
          #endif
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          #define __need_getopt_newlib
          #include <getopt.h>
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <sys/ioctl.h>
          
          #include <dirent.h>
          #include <err.h>
          #include <errno.h>
          #include <fts.h>
          #include <locale.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          #include <termios.h>
          #include <pwd.h>
          #include <grp.h>
          
          #include "extern-ls.h"
          
      80  static void display(  rtems_shell_ls_globals* globals,   FTSENT *,   FTSENT * );
      81  static int mastercmp_listdir(  const FTSENT **,   const FTSENT ** );
      82  static int mastercmp_no_listdir(  const FTSENT **,   const FTSENT ** );
      83  static void traverse(  rtems_shell_ls_globals* globals,   int,   char **,   int );
          
          static void (  *printfcn )(  rtems_shell_ls_globals* globals,   DISPLAY * );
          static int (  *sortfcn )(  const FTSENT *,   const FTSENT * );
          
          #define BY_NAME 0
          #define BY_SIZE 1
          #define BY_TIME 2
          
          #if RTEMS_REMOVED
          long blocksize; /* block size units */
          int termwidth = 80; /* default terminal width */
          int sortkey = BY_NAME;
          int rval = EXIT_SUCCESS; /* exit value - set if error encountered */
          
          /* flags */
          int f_accesstime; /* use time of last access */
          int f_column; /* columnated format */
          int f_columnacross; /* columnated format,   sorted across */
          int f_flags; /* show flags associated with a file */
          int f_grouponly; /* long listing without owner */
          int f_humanize; /* humanize the size field */
          int f_inode; /* print inode */
          int f_listdir; /* list actual directory,   not contents */
          int f_listdot; /* list files beginning with . */
          int f_longform; /* long listing format */
          int f_nonprint; /* show unprintables as ? */
          int f_nosort; /* don't sort output */
          int f_numericonly; /* don't convert uid/gid to name */
          int f_octal; /* print octal escapes for nongraphic characters */
          int f_octal_escape; /* like f_octal but use C escapes if possible */
          int f_recursive; /* ls subdirectories also */
          int f_reversesort; /* reverse whatever sort is used */
          int f_sectime; /* print the real time for all files */
          int f_singlecol; /* use single column output */
          int f_size; /* list size in short listing */
          int f_statustime; /* use time of last mode change */
          int f_stream; /* stream format */
          int f_type; /* add type character for non-regular files */
          int f_typedir; /* add type character for directories */
          int f_whiteout; /* show whiteout entries */
          #endif
          
          void
     127  rtems_shell_ls_exit (  rtems_shell_ls_globals* globals,   int code )
          {
           globals->exit_code = code;
           longjmp (  globals->exit_jmp,   1 );
          }
          
     133  static int main_ls(  rtems_shell_ls_globals* globals,   int argc,   char *argv[] );
          
          int
     136  rtems_shell_main_ls(  int argc,   char *argv[] )
          {
           rtems_shell_ls_globals ls_globals;
           rtems_shell_ls_globals* globals = &ls_globals;
           memset (  globals,   0,   sizeof (  ls_globals ) );
           termwidth = 80;
           sortkey = BY_NAME;
           rval = EXIT_SUCCESS;
           ls_globals.exit_code = 1;
           if (  setjmp (  ls_globals.exit_jmp ) == 0 )
           return main_ls (  globals,   argc,   argv );
           return ls_globals.exit_code;
          }
          
          int
     151  main_ls(  rtems_shell_ls_globals* globals,   int argc,   char *argv[] )
          {
           static char dot[] = ".",   *dotav[] = { dot,   NULL };
           //struct winsize win;
           int ch,   fts_options;
           int kflag = 0;
           const char *p;
          
           struct getopt_data getopt_reent;
           memset(  &getopt_reent,   0,   sizeof(  getopt_data ) );
          
          #if RTEMS_REMOVED
           setprogname(  argv[0] );
          #endif
           setlocale(  LC_ALL,   "" );
          
           /* Terminal defaults to -Cq,   non-terminal defaults to -1. */
           if (  isatty(  STDOUT_FILENO ) ) {
          #if RTEMS_REMOVED
           if (  ioctl(  STDOUT_FILENO,   TIOCGWINSZ,   &win ) == 0 &&
           win.ws_col > 0 )
           termwidth = win.ws_col;
           f_column = f_nonprint = 1;
          #endif
           } else
           f_singlecol = 1;
          
           /* Root is -A automatically. */
           if (  !getuid(   ) )
           f_listdot = 1;
          
           fts_options = FTS_PHYSICAL;
           while (  (  ch = getopt_r(  argc,   argv,  
           "1ABCFLRSTWabcdfghiklmnopqrstuwx",   &getopt_reent ) ) != -1 ) {
           switch (  ch ) {
           /*
           * The -1,   -C,   -l,   -m and -x options all override each other so
           * shell aliasing works correctly.
           */
           case '1':
           f_singlecol = 1;
           f_column = f_columnacross = f_longform = f_stream = 0;
           break;
           case 'C':
           f_column = 1;
           f_columnacross = f_longform = f_singlecol = f_stream =
           0;
           break;
           case 'g':
           if (  f_grouponly != -1 )
           f_grouponly = 1;
           f_longform = 1;
           f_column = f_columnacross = f_singlecol = f_stream = 0;
           break;
           case 'l':
           f_longform = 1;
           f_column = f_columnacross = f_singlecol = f_stream = 0;
           /* Never let -g take precedence over -l. */
           f_grouponly = -1;
           break;
           case 'm':
           f_stream = 1;
           f_column = f_columnacross = f_longform = f_singlecol =
           0;
           break;
           case 'x':
           f_columnacross = 1;
           f_column = f_longform = f_singlecol = f_stream = 0;
           break;
           /* The -c and -u options override each other. */
           case 'c':
           f_statustime = 1;
           f_accesstime = 0;
           break;
           case 'u':
           f_accesstime = 1;
           f_statustime = 0;
           break;
           case 'F':
           f_type = 1;
           break;
           case 'L':
           fts_options &= ~FTS_PHYSICAL;
           fts_options |= FTS_LOGICAL;
           break;
           case 'R':
           f_recursive = 1;
           break;
           case 'a':
           fts_options |= FTS_SEEDOT;
           /* FALLTHROUGH */
           case 'A':
           f_listdot = 1;
           break;
           /* The -B option turns off the -b,   -q and -w options. */
           case 'B':
           f_nonprint = 0;
           f_octal = 1;
           f_octal_escape = 0;
           break;
           /* The -b option turns off the -B,   -q and -w options. */
           case 'b':
           f_nonprint = 0;
           f_octal = 0;
           f_octal_escape = 1;
           break;
           /* The -d option turns off the -R option. */
           case 'd':
           f_listdir = 1;
           f_recursive = 0;
           break;
           case 'f':
           f_nosort = 1;
           break;
           case 'i':
           f_inode = 1;
           break;
           case 'k':
           blocksize = 1024;
           kflag = 1;
           break;
           /* The -h option forces all sizes to be measured in bytes. */
           case 'h':
           f_humanize = 1;
           break;
           case 'n':
           f_numericonly = 1;
           break;
           case 'o':
           f_flags = 1;
           break;
           case 'p':
           f_typedir = 1;
           break;
           /* The -q option turns off the -B,   -b and -w options. */
           case 'q':
           f_nonprint = 1;
           f_octal = 0;
           f_octal_escape = 0;
           break;
           case 'r':
           f_reversesort = 1;
           break;
           case 'S':
           sortkey = BY_SIZE;
           break;
           case 's':
           f_size = 1;
           break;
           case 'T':
           f_sectime = 1;
           break;
           case 't':
           sortkey = BY_TIME;
           break;
           case 'W':
           f_whiteout = 1;
           break;
           /* The -w option turns off the -B,   -b and -q options. */
           case 'w':
           f_nonprint = 0;
           f_octal = 0;
           f_octal_escape = 0;
           break;
           default:
           case '?':
           usage(  globals );
           }
           }
           argc -= getopt_reent.optind;
           argv += getopt_reent.optind;
          
           if (  f_column || f_columnacross || f_stream ) {
           if (  (  p = getenv(  "COLUMNS" ) ) != NULL )
           termwidth = atoi(  p );
           }
          
           /*
           * If both -g and -l options,   let -l take precedence.
           */
           if (  f_grouponly == -1 )
           f_grouponly = 0;
          
           /*
           * If not -F,   -i,   -l,   -p,   -S,   -s or -t options,   don't require stat
           * information.
           */
           if (  !f_inode && !f_longform && !f_size && !f_type && !f_typedir &&
           sortkey == BY_NAME )
           fts_options |= FTS_NOSTAT;
          
           /*
           * If not -F,   -d or -l options,   follow any symbolic links listed on
           * the command line.
           */
           if (  !f_longform && !f_listdir && !f_type )
           fts_options |= FTS_COMFOLLOW;
          
           /*
           * If -W,   show whiteout entries
           */
          #ifdef FTS_WHITEOUT
           if (  f_whiteout )
           fts_options |= FTS_WHITEOUT;
          #endif
          
           /* If -l or -s,   figure out block size. */
           if (  f_inode || f_longform || f_size ) {
          #if RTEMS_REMOVED
           if (  !kflag )
           (  void )getbsize(  NULL,   &blocksize );
          #else
           /* Make equal to 1 so ls -l shows the actual blcok count */
           blocksize = 512;
          #endif
           blocksize /= 512;
           }
          
           /* Select a sort function. */
           if (  f_reversesort ) {
           switch (  sortkey ) {
           case BY_NAME:
           sortfcn = revnamecmp;
           break;
           case BY_SIZE:
           sortfcn = revsizecmp;
           break;
           case BY_TIME:
           if (  f_accesstime )
           sortfcn = revacccmp;
           else if (  f_statustime )
           sortfcn = revstatcmp;
           else /* Use modification time. */
           sortfcn = revmodcmp;
           break;
           }
           } else {
           switch (  sortkey ) {
           case BY_NAME:
           sortfcn = namecmp;
           break;
           case BY_SIZE:
           sortfcn = sizecmp;
           break;
           case BY_TIME:
           if (  f_accesstime )
           sortfcn = acccmp;
           else if (  f_statustime )
           sortfcn = statcmp;
           else /* Use modification time. */
           sortfcn = modcmp;
           break;
           }
           }
          
           /* Select a print function. */
           if (  f_singlecol )
           printfcn = printscol;
           else if (  f_columnacross )
           printfcn = printacol;
           else if (  f_longform )
           printfcn = printlong;
           else if (  f_stream )
           printfcn = printstream;
           else
           printfcn = printcol;
          
           if (  argc )
           traverse(  globals,   argc,   argv,   fts_options );
           else
           traverse(  globals,   1,   dotav,   fts_options );
           exit(  rval );
           /* NOTREACHED */
           return 0;
          }
          
          #if RTEMS_REMOVED
          static int output; /* If anything output. */
          #endif
          
          /*
           * Traverse(   ) walks the logical directory structure specified by the argv list
           * in the order specified by the mastercmp(   ) comparison function. During the
           * traversal it passes linked lists of structures to display(   ) which represent
           * a superset (  may be exact set ) of the files to be displayed.
           */
          static void
     438  traverse(  rtems_shell_ls_globals* globals,   int argc,   char *argv[],   int options )
          {
           FTS *ftsp;
           FTSENT *p,   *chp;
           int ch_options;
          
           if (  (  ftsp =
           fts_open(  argv,   options,  
           f_nosort ? NULL : f_listdir ?
           mastercmp_listdir : mastercmp_no_listdir ) ) == NULL )
           err(  exit_jump,   EXIT_FAILURE,   NULL );
          
           display(  globals,   NULL,   fts_children(  ftsp,   0 ) );
           if (  f_listdir )
           {
           fts_close(  ftsp );
           return;
           }
          
           /*
           * If not recursing down this tree and don't need stat info,   just get
           * the names.
           */
           ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0;
          
           while (  (  p = fts_read(  ftsp ) ) != NULL )
           switch (  p->fts_info ) {
           case FTS_DC:
           warnx(  "%s: directory causes a cycle",   p->fts_name );
           break;
           case FTS_DNR:
           case FTS_ERR:
           warnx(  "%s: %s",   p->fts_name,   strerror(  p->fts_errno ) );
           rval = EXIT_FAILURE;
           break;
           case FTS_D:
           if (  p->fts_level != FTS_ROOTLEVEL &&
           p->fts_name[0] == '.' && !f_listdot )
           break;
          
           /*
           * If already output something,   put out a newline as
           * a separator. If multiple arguments,   precede each
           * directory with its name.
           */
           if (  output )
           (  void )printf(  "\n%s:\n",   p->fts_path );
           else if (  argc > 1 ) {
           (  void )printf(  "%s:\n",   p->fts_path );
           output = 1;
           }
          
           chp = fts_children(  ftsp,   ch_options );
           display(  globals,   p,   chp );
          
           if (  !f_recursive && chp != NULL )
           (  void )fts_set(  ftsp,   p,   FTS_SKIP );
           break;
           }
           fts_close(  ftsp );
           if (  errno )
           err(  exit_jump,   EXIT_FAILURE,   "fts_read" );
          }
          
          /*
           * Display(   ) takes a linked list of FTSENT structures and passes the list
           * along with any other necessary information to the print function. P
           * points to the parent directory of the display list.
           */
          static void
     508  display(  rtems_shell_ls_globals* globals,   FTSENT *p,   FTSENT *list )
          {
           struct stat *sp;
           DISPLAY d;
           FTSENT *cur;
           NAMES *np;
           u_int64_t btotal,   stotal,   maxblock,   maxsize;
           int maxinode,   maxnlink,   maxmajor,   maxminor;
           int bcfile,   entries,   flen,   glen,   ulen,   maxflags,   maxgroup,   maxlen;
           int maxuser,   needstats;
           const char *user,   *group;
           char buf[21]; /* 64 bits == 20 digits,   +1 for NUL */
           char nuser[12],   ngroup[12];
           char *flags = NULL;
          
          #ifdef __GNUC__
           /* This outrageous construct just to shut up a GCC warning. */
           (  void ) &maxsize;
          #endif
          
           /*
           * If list is NULL there are two possibilities: that the parent
           * directory p has no children,   or that fts_children(   ) returned an
           * error. We ignore the error case since it will be replicated
           * on the next call to fts_read(   ) on the post-order visit to the
           * directory p,   and will be signalled in traverse(   ).
           */
           if (  list == NULL )
           return;
          
           needstats = f_inode || f_longform || f_size;
           flen = 0;
           maxinode = maxnlink = 0;
           bcfile = 0;
           maxuser = maxgroup = maxflags = maxlen = 0;
           btotal = stotal = maxblock = maxsize = 0;
           maxmajor = maxminor = 0;
           for (  cur = list,   entries = 0; cur; cur = cur->fts_link ) {
           uint64_t size;
           if (  cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS ) {
           warnx(  "%s: %s",  
           cur->fts_name,   strerror(  cur->fts_errno ) );
           cur->fts_number = NO_PRINT;
           rval = EXIT_FAILURE;
           continue;
           }
          
           /*
           * P is NULL if list is the argv list,   to which different rules
           * apply.
           */
           if (  p == NULL ) {
           /* Directories will be displayed later. */
           if (  cur->fts_info == FTS_D && !f_listdir ) {
           cur->fts_number = NO_PRINT;
           continue;
           }
           } else {
           /* Only display dot file if -a/-A set. */
           if (  cur->fts_name[0] == '.' && !f_listdot ) {
           cur->fts_number = NO_PRINT;
           continue;
           }
           }
           if (  cur->fts_namelen > maxlen )
           maxlen = cur->fts_namelen;
           if (  needstats ) {
           sp = cur->fts_statp;
           if (  sp->st_size < 0 )
           size = sp->st_size * -1;
           else
           size = sp->st_size;
           if (  sp->st_blocks > maxblock )
           maxblock = sp->st_blocks;
           if (  sp->st_ino > maxinode )
           maxinode = sp->st_ino;
           if (  sp->st_nlink > maxnlink )
           maxnlink = sp->st_nlink;
           if (  size > maxsize )
           maxsize = size;
           if (  S_ISCHR(  sp->st_mode ) || S_ISBLK(  sp->st_mode ) ) {
           bcfile = 1;
           if (  major(  sp->st_rdev ) > maxmajor )
           maxmajor = major(  sp->st_rdev );
           if (  minor(  sp->st_rdev ) > maxminor )
           maxminor = minor(  sp->st_rdev );
           }
          
           btotal += sp->st_blocks;
           stotal += size;
           if (  f_longform ) {
           if (  f_numericonly ||
           (  user = user_from_uid(  sp->st_uid,   0 ) ) ==
           NULL ) {
           (  void )snprintf(  nuser,   sizeof(  nuser ),  
           "%u",   sp->st_uid );
           user = nuser;
           }
           if (  f_numericonly ||
           (  group = group_from_gid(  sp->st_gid,   0 ) ) ==
           NULL ) {
           (  void )snprintf(  ngroup,   sizeof(  ngroup ),  
           "%u",   sp->st_gid );
           group = ngroup;
           }
           if (  (  ulen = strlen(  user ) ) > maxuser )
           maxuser = ulen;
           if (  (  glen = strlen(  group ) ) > maxgroup )
           maxgroup = glen;
          #if RTEMS_REMOVED
           if (  f_flags ) {
           flags =
           flags_to_string(  sp->st_flags,   "-" );
           if (  (  flen = strlen(  flags ) ) > maxflags )
           maxflags = flen;
           } else
          #endif
           flen = 0;
          
           if (  (  np = malloc(  sizeof(  NAMES ) +
           ulen + glen + flen + 3 ) ) == NULL )
           err(  exit_jump,   EXIT_FAILURE,   NULL );
          
           np->user = &np->data[0];
           (  void )strcpy(  np->user,   user );
           np->group = &np->data[ulen + 1];
           (  void )strcpy(  np->group,   group );
          
           if (  f_flags && flags ) {
           np->flags = &np->data[ulen + glen + 2];
           (  void )strcpy(  np->flags,   flags );
           }
           cur->fts_pointer = np;
           }
           }
           ++entries;
           }
          
           if (  !entries )
           return;
          
           d.list = list;
           d.entries = entries;
           d.maxlen = maxlen;
           if (  needstats ) {
           d.btotal = btotal;
           d.stotal = stotal;
           if (  f_humanize ) {
           d.s_block = 4; /* min buf length for humanize_number */
           } else {
           (  void )snprintf(  buf,   sizeof(  buf ),   "%llu",  
           (  long long )howmany(  maxblock,   blocksize ) );
           d.s_block = strlen(  buf );
           }
           d.s_flags = maxflags;
           d.s_group = maxgroup;
           (  void )snprintf(  buf,   sizeof(  buf ),   "%u",   maxinode );
           d.s_inode = strlen(  buf );
           (  void )snprintf(  buf,   sizeof(  buf ),   "%u",   maxnlink );
           d.s_nlink = strlen(  buf );
           if (  f_humanize ) {
           d.s_size = 4; /* min buf length for humanize_number */
           } else {
           (  void )snprintf(  buf,   sizeof(  buf ),   "%llu",  
           (  long long )maxsize );
           d.s_size = strlen(  buf );
           }
           d.s_user = maxuser;
           if (  bcfile ) {
           (  void )snprintf(  buf,   sizeof(  buf ),   "%u",   maxmajor );
           d.s_major = strlen(  buf );
           (  void )snprintf(  buf,   sizeof(  buf ),   "%u",   maxminor );
           d.s_minor = strlen(  buf );
           if (  d.s_major + d.s_minor + 2 > d.s_size )
           d.s_size = d.s_major + d.s_minor + 2;
           else if (  d.s_size - d.s_minor - 2 > d.s_major )
           d.s_major = d.s_size - d.s_minor - 2;
           } else {
           d.s_major = 0;
           d.s_minor = 0;
           }
           }
          
           printfcn(  globals,   &d );
           output = 1;
          
           if (  f_longform )
           for (  cur = list; cur; cur = cur->fts_link )
           free(  cur->fts_pointer );
          }
          
          /*
           * Ordering for mastercmp:
           * If ordering the argv (  fts_level = FTS_ROOTLEVEL ) return non-directories
           * as larger than directories. Within either group,   use the sort function.
           * All other levels use the sort function. Error entries remain unsorted.
           */
          static int
     706  mastercmp_no_listdir(  const FTSENT **a,   const FTSENT **b )
          {
           int a_info,   b_info;
           int l_f_listdir = 0;
          
           a_info = (  *a )->fts_info;
           if (  a_info == FTS_ERR )
           return (  0 );
           b_info = (  *b )->fts_info;
           if (  b_info == FTS_ERR )
           return (  0 );
          
           if (  a_info == FTS_NS || b_info == FTS_NS ) {
           if (  b_info != FTS_NS )
           return (  1 );
           else if (  a_info != FTS_NS )
           return (  -1 );
           else
           return (  namecmp(  *a,   *b ) );
           }
          
           if (  a_info != b_info && !l_f_listdir &&
           (  *a )->fts_level == FTS_ROOTLEVEL ) {
           if (  a_info == FTS_D )
           return (  1 );
           else if (  b_info == FTS_D )
           return (  -1 );
           }
           return (  sortfcn(  *a,   *b ) );
          }
          
          static int
     738  mastercmp_listdir(  const FTSENT **a,   const FTSENT **b )
          {
           int a_info,   b_info;
           int l_f_listdir = 1;
          
           a_info = (  *a )->fts_info;
           if (  a_info == FTS_ERR )
           return (  0 );
           b_info = (  *b )->fts_info;
           if (  b_info == FTS_ERR )
           return (  0 );
          
           if (  a_info == FTS_NS || b_info == FTS_NS ) {
           if (  b_info != FTS_NS )
           return (  1 );
           else if (  a_info != FTS_NS )
           return (  -1 );
           else
           return (  namecmp(  *a,   *b ) );
           }
          
           if (  a_info != b_info && !l_f_listdir &&
           (  *a )->fts_level == FTS_ROOTLEVEL ) {
           if (  a_info == FTS_D )
           return (  1 );
           else if (  b_info == FTS_D )
           return (  -1 );
           }
           return (  sortfcn(  *a,   *b ) );
          }
          
          rtems_shell_cmd_t rtems_shell_LS_Command = {
           "ls",   /* name */
           "ls [dir] # list files in the directory",   /* usage */
           "files",   /* topic */
           rtems_shell_main_ls,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_mallocinfo.c

       1  /*
           * MALLOC_INFO Shell Command Implmentation
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: main_mallocinfo.c,  v 1.7 2008/09/19 16:15:21 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <rtems.h>
          #include <rtems/malloc.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      25  extern int malloc_info(   region_information_block *  );
      26  extern void rtems_shell_print_unified_work_area_message(  void );
          
      28  int rtems_shell_main_malloc_info(  
           int argc,  
           char *argv[]
           )
          {
           if (   argc == 2  ) {
           rtems_shell_print_unified_work_area_message(   );
          
           if (   !strcmp(   argv[1],   "info"  )  ) {
           region_information_block info;
          
           malloc_info(   &info  );
           rtems_shell_print_heap_info(   "free",   &info.Free  );
           rtems_shell_print_heap_info(   "used",   &info.Used  );
           return 0;
           } else if (   !strcmp(   argv[1],   "stats"  )  ) {
           malloc_report_statistics_with_plugin(  
           stdout,  
           (  rtems_printk_plugin_t ) fprintf
            );
           return 0;
           }
           }
           fprintf(   stderr,   "%s: [info|stats]\n",   argv[0]  );
           return -1;
          }
          
          rtems_shell_cmd_t rtems_shell_MALLOC_INFO_Command = {
           "malloc",   /* name */
           "[info|stats]",   /* usage */
           "mem",   /* topic */
           rtems_shell_main_malloc_info,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };
          

libmisc/shell/main_mdump.c

       1  /*
           * MDUMP Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_mdump.c,  v 1.9 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <ctype.h>
          #include <stdio.h>
          #include <inttypes.h>
          #include <string.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include "internal.h"
          
      29  int rtems_shell_main_mdump(  
           int argc,  
           char *argv[]
           )
          {
           unsigned char n;
           unsigned char m;
           int max;
           int res;
           void *addr = NULL;
           unsigned char *pb;
          
           if (  argc > 1 ) {
           if (   rtems_string_to_pointer(  argv[1],   &addr,   NULL )  ) {
           printf(   "Address argument (  %s ) is not a number\n",   argv[1]  );
           return -1;
           }
          
           }
          
           if (  argc > 2 ) {
           if (   rtems_string_to_int(  argv[1],   &max,   NULL,   0 )  ) {
           printf(   "Length argument (  %s ) is not a number\n",   argv[1]  );
           return -1;
           }
           if (  max <= 0 ) {
           max = 1; /* print 1 item if 0 or neg. */
           res = 0;
           } else {
           max--;
           res = max & 0xf;/* num bytes in last row */
           max >>= 4; /* div by 16 */
           max++; /* num of rows to print */
           if (  max > 20 ) { /* limit to 20 */
           max = 20;
           res = 0xf; /* 16 bytes print in last row */
           }
           }
           } else {
           max = 20;
           res = 0xf;
           }
          
           pb = addr;
           for (  m=0; m<max; m++ ) {
           printf(  "%10p ",   pb );
           for (  n=0;n<=(  m==(  max-1 )?res:0xf );n++ )
           printf(  "%02X%c",  pb[n],  n==7?'-':' ' );
           for (  ;n<=0xf;n++ )
           printf(  " %c",  n==7?'-':' ' );
           for (  n=0;n<=(  m==(  max-1 )?res:0xf );n++ ) {
           printf(  "%c",   isprint(  pb[n] ) ? pb[n] : '.' );
           }
           printf(  "\n" );
           pb += 16;
           }
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_MDUMP_Command = {
           "mdump",   /* name */
           "mdump [address [length]]",   /* usage */
           "mem",   /* topic */
           rtems_shell_main_mdump,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };
          

libmisc/shell/main_medit.c

       1  /*
           * MEDIT Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_medit.c,  v 1.6 2009/07/23 14:32:34 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <ctype.h>
          #include <stdio.h>
          #include <string.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include "internal.h"
          
      28  extern int rtems_shell_main_mdump(  int,   char * );
          
      30  int rtems_shell_main_medit(  
           int argc,  
           char *argv[]
           )
          {
           unsigned char *pb;
           void *tmpp;
           int n;
           int i;
          
           if (   argc < 3  ) {
           fprintf(  stderr,  "%s: too few arguments\n",   argv[0] );
           return -1;
           }
          
           /*
           * Convert arguments into numbers
           */
           if (   rtems_string_to_pointer(  argv[1],   &tmpp,   NULL )  ) {
           printf(   "Address argument (  %s ) is not a number\n",   argv[1]  );
           return -1;
           }
           pb = tmpp;
          
           /*
           * Now edit the memory
           */
           n = 0;
           for (  i=2 ; i<=argc ; i++ ) {
           unsigned char tmpc;
          
           if (   rtems_string_to_unsigned_char(  argv[i],   &tmpc,   NULL,   0 )  ) {
           printf(   "Value (  %s ) is not a number\n",   argv[i]  );
           continue;
           }
          
           pb[n++] = tmpc;
           }
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_MEDIT_Command = {
           "medit",   /* name */
           "medit address value1 [value2 ...]",   /* usage */
           "mem",   /* topic */
           rtems_shell_main_medit,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_mfill.c

       1  /*
           * MFILL Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_mfill.c,  v 1.6 2009/07/23 14:32:34 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <ctype.h>
          #include <stdio.h>
          #include <string.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include "internal.h"
          
      28  int rtems_shell_main_mfill(  
           int argc,  
           char *argv[]
           )
          {
           unsigned long tmp;
           void *addr;
           size_t size;
           unsigned char value;
          
           if (   argc != 4  ) {
           fprintf(  stderr,  "%s: too few arguments\n",   argv[0] );
           return -1;
           }
          
           /*
           * Convert arguments into numbers
           */
           if (   rtems_string_to_pointer(  argv[1],   &addr,   NULL )  ) {
           printf(   "Address argument (  %s ) is not a number\n",   argv[1]  );
           return -1;
           }
          
           if (   rtems_string_to_unsigned_long(  argv[2],   &tmp,   NULL,   0 )  ) {
           printf(   "Size argument (  %s ) is not a number\n",   argv[2]  );
           return -1;
           }
           size = (  size_t ) tmp;
          
           if (   rtems_string_to_unsigned_char(  argv[3],   &value,   NULL,   0 )  ) {
           printf(   "Value argument (  %s ) is not a number\n",   argv[3]  );
           return -1;
           }
          
           /*
           * Now fill the memory.
           */
           memset(  addr,   size,   value );
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_MFILL_Command = {
           "mfill",   /* name */
           "mfill address size value",   /* usage */
           "mem",   /* topic */
           rtems_shell_main_mfill,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_mkdir.c

       1  /*
           * MKDIR Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_mkdir.c,  v 1.4 2008/02/27 21:52:16 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <string.h>
          #include <stdlib.h>
          #include <errno.h>
          #include <sys/stat.h>
          #include <sys/types.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      30  int rtems_shell_main_mkdir(  
           int argc,  
           char *argv[]
           )
          {
           char *dir;
           int n;
          
           n = 1;
           while (  n<argc ) {
           dir = argv[n++];
           if (  mkdir(  dir,  S_IRWXU|S_IRWXG|S_IRWXO ) ) {
           fprintf(  stderr,   "mkdir '%s' failed:%s\n",   dir,   strerror(  errno ) );
           }
           }
           return errno;
          }
          
          rtems_shell_cmd_t rtems_shell_MKDIR_Command = {
           "mkdir",   /* name */
           "mkdir dir # make a directory",   /* usage */
           "files",   /* topic */
           rtems_shell_main_mkdir,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_mknod.c

       1  /* $NetBSD: mknod.c,  v 1.39 2009/02/13 01:37:23 lukem Exp $ */
          
          /*-
           * Copyright (  c ) 1998,   2001 The NetBSD Foundation,   Inc.
           * All rights reserved.
           *
           * This code is derived from software contributed to The NetBSD Foundation
           * by Charles M. Hannum.
           *
           * 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 NETBSD FOUNDATION,   INC. 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 FOUNDATION 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_NBTOOL_CONFIG_H
          #include "nbtool_config.h"
          #endif
          
          #if 0
          #ifndef lint
      42  __COPYRIGHT(  "@(  # ) Copyright (  c ) 1998\
           The NetBSD Foundation,   Inc. All rights reserved." );
      44  __RCSID(  "$NetBSD: mknod.c,  v 1.39 2009/02/13 01:37:23 lukem Exp $" );
          #endif /* not lint */
          #endif
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          #define __need_getopt_newlib
          #include <getopt.h>
          
          #include <sys/cdefs.h>
          
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <sys/param.h>
          #if !HAVE_NBTOOL_CONFIG_H && defined(  KERN_DRIVERS )
          #include <sys/sysctl.h>
          #endif
          
          #include <err.h>
          #include <errno.h>
          #include <limits.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <unistd.h>
          #include <pwd.h>
          #include <grp.h>
          #include <string.h>
          #include <ctype.h>
          
          #include "mknod-pack_dev.h"
          
          #include <setjmp.h>
          
          typedef struct {
           int exit_code;
           jmp_buf exit_jmp;
          } rtems_shell_mknod_globals;
          
          #define exit_jump &(  globals->exit_jmp )
          
          #define exit(  ec ) rtems_shell_mknod_exit(  globals,   ec )
          
      87  static int gid_name(  const char *,   gid_t * );
      88  static portdev_t callPack(  rtems_shell_mknod_globals* globals,  
           pack_t *,   int,   u_long * );
          
      91  static int main_mknod(  rtems_shell_mknod_globals*,   int,   char *[] );
      92  static void usage(  rtems_shell_mknod_globals*  );
          
          static void
      95  rtems_shell_mknod_exit (  rtems_shell_mknod_globals* globals,   int code )
          {
           globals->exit_code = code;
           longjmp (  globals->exit_jmp,   1 );
          }
          
          #include "mknod-pack_dev.c"
          
          int
     104  rtems_shell_main_mknod(  int argc,   char *argv[] )
          {
           rtems_shell_mknod_globals mknod_globals;
           rtems_shell_mknod_globals* globals = &mknod_globals;
           memset (  globals,   0,   sizeof (  mknod_globals ) );
           mknod_globals.exit_code = 1;
           if (  setjmp (  mknod_globals.exit_jmp ) == 0 )
           return main_mknod (  globals,   argc,   argv );
           return mknod_globals.exit_code;
          }
          
          #define getprogname(   ) "mknod"
          
          #ifdef KERN_DRIVERS
          #error invalid for RTEMS
          static struct kinfo_drivers *kern_drivers;
          static int num_drivers;
          
     122  static void get_device_info(  void );
     123  static void print_device_info(  char ** );
     124  static int major_from_name(  const char *,   mode_t );
          #endif
          
          #define MAXARGS 3 /* 3 for bsdos,   2 for rest */
          
          int
     130  main_mknod(  rtems_shell_mknod_globals* globals,   int argc,   char **argv )
          {
           char *name,   *p;
           mode_t mode;
           portdev_t dev;
           pack_t *pack;
           u_long numbers[MAXARGS];
           int n,   ch,   fifo,   hasformat;
           int r_flag = 0; /* force: delete existing entry */
          #ifdef KERN_DRIVERS
           int l_flag = 0; /* list device names and numbers */
           int major;
          #endif
          #if RTEMS_REMOVED
           void *modes = 0;
          #endif
           uid_t uid = -1;
           gid_t gid = -1;
           int rval;
          
           struct getopt_data getopt_reent;
           memset(  &getopt_reent,   0,   sizeof(  getopt_data ) );
          
           dev = 0;
           fifo = hasformat = 0;
           pack = pack_native;
          
          #ifdef KERN_DRIVERS
           while (  (  ch = getopt(  argc,   argv,   "lrRF:g:m:u:" ) ) != -1 ) {
          #else
           while (  (  ch = getopt_r(  argc,   argv,   "rRF:g:m:u:",   &getopt_reent ) ) != -1 ) {
          #endif
           switch (  ch ) {
          
          #ifdef KERN_DRIVERS
           case 'l':
           l_flag = 1;
           break;
          #endif
          
           case 'r':
           r_flag = 1;
           break;
          
           case 'R':
           r_flag = 2;
           break;
          
           case 'F':
           pack = pack_find(  getopt_reent.optarg );
           if (  pack == NULL )
           errx(  exit_jump,   1,   "invalid format: %s",   getopt_reent.optarg );
           hasformat++;
           break;
          
           case 'g':
           if (  getopt_reent.optarg[0] == '#' ) {
           gid = strtol(  getopt_reent.optarg + 1,   &p,   10 );
           if (  *p == 0 )
           break;
           }
           if (  gid_name(  getopt_reent.optarg,   &gid ) == 0 )
           break;
           gid = strtol(  getopt_reent.optarg,   &p,   10 );
           if (  *p == 0 )
           break;
           errx(  exit_jump,   1,   "%s: invalid group name",   getopt_reent.optarg );
          
           case 'm':
          #if RTEMS_REMOVED
           modes = setmode(  getopt_reent.optarg );
           if (  modes == NULL )
          #endif
           err(  exit_jump,   1,   "Cannot set file mode `%s'",   getopt_reent.optarg );
           break;
          
           case 'u':
           if (  getopt_reent.optarg[0] == '#' ) {
           uid = strtol(  getopt_reent.optarg + 1,   &p,   10 );
           if (  *p == 0 )
           break;
           }
          #if RTEMS_REMOVED
           if (  uid_from_user(  getopt_reent.optarg,   &uid ) == 0 )
           break;
          #endif
           uid = strtol(  getopt_reent.optarg,   &p,   10 );
           if (  *p == 0 )
           break;
           errx(  exit_jump,   1,   "%s: invalid user name",   getopt_reent.optarg );
          
           default:
           case '?':
           usage(  globals );
           }
           }
           argc -= getopt_reent.optind;
           argv += getopt_reent.optind;
          
          #ifdef KERN_DRIVERS
           if (  l_flag ) {
           print_device_info(  argv );
           return 0;
           }
          #endif
          
           if (  argc < 2 || argc > 10 )
           usage(  globals );
          
           name = *argv;
           argc--;
           argv++;
          
           umask(  mode = umask(  0 ) );
           mode = (  S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH ) & ~mode;
          
           if (  argv[0][1] != '\0' )
           goto badtype;
           switch (  *argv[0] ) {
           case 'c':
           mode |= S_IFCHR;
           break;
          
           case 'b':
           mode |= S_IFBLK;
           break;
          
           case 'p':
           if (  hasformat )
           errx(  exit_jump,   1,   "format is meaningless for fifos" );
           mode |= S_IFIFO;
           fifo = 1;
           break;
          
           default:
           badtype:
           errx(  exit_jump,   1,   "node type must be 'b',   'c' or 'p'." );
           }
           argc--;
           argv++;
          
           if (  fifo ) {
           if (  argc != 0 )
           usage(  globals );
           } else {
           if (  argc < 1 || argc > MAXARGS )
           usage(  globals );
           }
          
           for (  n = 0; n < argc; n++ ) {
           errno = 0;
           numbers[n] = strtoul(  argv[n],   &p,   0 );
           if (  *p == 0 && errno == 0 )
           continue;
          #ifdef KERN_DRIVERS
           if (  n == 0 ) {
           major = major_from_name(  argv[0],   mode );
           if (  major != -1 ) {
           numbers[0] = major;
           continue;
           }
           if (  !isdigit(  *(  unsigned char * )argv[0] ) )
           errx(  1,   "unknown driver: %s",   argv[0] );
           }
          #endif
           errx(  exit_jump,   1,   "invalid number: %s",   argv[n] );
           }
          
           switch (  argc ) {
           case 0:
           dev = 0;
           break;
          
           case 1:
           dev = numbers[0];
           break;
          
           default:
           dev = callPack(  globals,   pack,   argc,   numbers );
           break;
           }
          
          #if RTEMS_REMOVED
           if (  modes != NULL )
           mode = getmode(  modes,   mode );
          #endif
           umask(  0 );
           rval = fifo ? mkfifo(  name,   mode ) : mknod(  name,   mode,   dev );
           if (  rval < 0 && errno == EEXIST && r_flag ) {
           struct stat sb;
           if (  lstat(  name,   &sb ) != 0 || (  !fifo && sb.st_rdev != dev ) )
           sb.st_mode = 0;
          
           if (  (  sb.st_mode & S_IFMT ) == (  mode & S_IFMT ) ) {
           if (  r_flag == 1 )
           /* Ignore permissions and user/group */
           return 0;
           if (  sb.st_mode != mode )
           rval = chmod(  name,   mode );
           else
           rval = 0;
           } else {
           unlink(  name );
           rval = fifo ? mkfifo(  name,   mode )
           : mknod(  name,   mode,   dev );
           }
           }
           if (  rval < 0 )
           err(  exit_jump,   1,   "%s",   name );
           if (  (  uid != (  uid_t )-1 || gid != (  uid_t )-1 ) && chown(  name,   uid,   gid ) == -1 )
           /* XXX Should we unlink the files here? */
           warn(  "%s: uid/gid not changed",   name );
          
           return 0;
          }
          
          static void
          usage(  rtems_shell_mknod_globals* globals )
          {
           const char *progname = getprogname(   );
          
           (  void )fprintf(  stderr,  
           "usage: %s [-rR] [-F format] [-m mode] [-u user] [-g group]\n",  
           progname );
           (  void )fprintf(  stderr,  
          #ifdef KERN_DRIVERS
           " [ name [b | c] [major | driver] minor\n"
          #else
           " [ name [b | c] major minor\n"
          #endif
           " | name [b | c] major unit subunit\n"
           " | name [b | c] number\n"
           " | name p ]\n" );
          #ifdef KERN_DRIVERS
           (  void )fprintf(  stderr,   " %s -l [driver] ...\n",   progname );
          #endif
           exit(  1 );
          }
          
          static int
          gid_name(  const char *name,   gid_t *gid )
          {
           struct group *g;
          
           g = getgrnam(  name );
           if (  !g )
           return -1;
           *gid = g->gr_gid;
           return 0;
          }
          
          static portdev_t
          callPack(  rtems_shell_mknod_globals* globals,   pack_t *f,   int n,   u_long *numbers )
          {
           portdev_t d;
           const char *error = NULL;
          
           d = (  *f )(  n,   numbers,   &error );
           if (  error != NULL )
           errx(  exit_jump,   1,   "%s",   error );
           return d;
          }
          
          #ifdef KERN_DRIVERS
          static void
          get_device_info(  void )
          {
           static int mib[2] = {CTL_KERN,   KERN_DRIVERS};
           size_t len;
          
           if (  sysctl(  mib,   2,   NULL,   &len,   NULL,   0 ) != 0 )
           err(  1,   "kern.drivers"  );
           kern_drivers = malloc(  len );
           if (  kern_drivers == NULL )
           err(  1,   "malloc" );
           if (  sysctl(  mib,   2,   kern_drivers,   &len,   NULL,   0 ) != 0 )
           err(  1,   "kern.drivers"  );
          
           num_drivers = len / sizeof *kern_drivers;
          }
          
          static void
          print_device_info(  char **names )
          {
           int i;
           struct kinfo_drivers *kd;
          
           if (  kern_drivers == NULL )
           get_device_info(   );
          
           do {
           kd = kern_drivers;
           for (  i = 0; i < num_drivers; kd++,   i++ ) {
           if (  *names && strcmp(  *names,   kd->d_name ) )
           continue;
           printf(  "%s",   kd->d_name );
           if (  kd->d_cmajor != -1 )
           printf(  " character major %d",   kd->d_cmajor );
           if (  kd->d_bmajor != -1 )
           printf(  " block major %d",   kd->d_bmajor );
           printf(  "\n" );
           }
           } while (  *names && *++names );
          }
          
          static int
          major_from_name(  const char *name,   mode_t mode )
          {
           int i;
           struct kinfo_drivers *kd;
          
           if (  kern_drivers == NULL )
           get_device_info(   );
          
           kd = kern_drivers;
           for (  i = 0; i < num_drivers; kd++,   i++ ) {
           if (  strcmp(  name,   kd->d_name ) )
           continue;
           if (  S_ISCHR(  mode ) )
           return kd->d_cmajor;
           return kd->d_bmajor;
           }
           return -1;
          }
          #endif
          
          rtems_shell_cmd_t rtems_shell_MKNOD_Command = {
           "mknod",   /* name */
           "mknod mknod [-rR] [-F fmt] [-m mode] name [c | b] minor",   /* usage */
           "files",   /* topic */
           rtems_shell_main_mknod,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_mkrfs.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_mkrfs.c,  v 1.1 2010/02/19 03:23:11 ccj Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include <rtems/shellconfig.h>
          #include <rtems/rtems-rfs-shell.h>
          #include <rtems/fsmount.h>
          #include "internal.h"
          
          #define OPTIONS "[-v] [-s blksz] [-b grpblk] [-i grpinode] [-I] [-o %inode]"
          
          rtems_shell_cmd_t rtems_shell_MKRFS_Command = {
           "mkrfs",   /* name */
           "mkrfs " OPTIONS " dev",   /* usage */
           "files",   /* topic */
           rtems_shell_rfs_format,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_mmove.c

       1  /*
           * MMOVE Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_mmove.c,  v 1.6 2009/07/23 14:32:34 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <ctype.h>
          #include <stdio.h>
          #include <string.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include "internal.h"
          
      28  extern int rtems_shell_main_mdump(  int,   char * );
          
      30  int rtems_shell_main_mmove(  
           int argc,  
           char *argv[]
           )
          {
           unsigned long tmp;
           void *src;
           void *dst;
           size_t length;
          
           if (   argc < 4  ) {
           fprintf(  stderr,  "%s: too few arguments\n",   argv[0] );
           return -1;
           }
          
           /*
           * Convert arguments into numbers
           */
           if (   rtems_string_to_pointer(  argv[1],   &dst,   NULL )  ) {
           printf(   "Destination argument (  %s ) is not a number\n",   argv[1]  );
           return -1;
           }
          
           if (   rtems_string_to_pointer(  argv[2],   &src,   NULL )  ) {
           printf(   "Source argument (  %s ) is not a number\n",   argv[2]  );
           return -1;
           }
          
           if (   rtems_string_to_unsigned_long(  argv[3],   &tmp,   NULL,   0 )  ) {
           printf(   "Length argument (  %s ) is not a number\n",   argv[3]  );
           return -1;
           }
           length = (  size_t ) tmp;
          
           /*
           * Now copy the memory.
           */
           memcpy(  dst,   src,   length );
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_MMOVE_Command = {
           "mmove",   /* name */
           "mmove dst src length",   /* usage */
           "mem",   /* topic */
           rtems_shell_main_mmove,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_mount.c

       1  /*
           * Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_mount.c,  v 1.10 2010/07/01 13:05:18 sh Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          #include <rtems/libio.h>
          #include "internal.h"
          
      30  static bool print_filesystem(  const rtems_filesystem_table_t *entry,   void *arg )
          {
           printf(  "%s ",   entry->type );
          
           return false;
          }
          
      37  int rtems_shell_main_mount(  
           int argc,  
           char *argv[]
           )
          {
           rtems_filesystem_options_t options = RTEMS_FILESYSTEM_READ_WRITE;
           char* type = NULL;
           char* source = NULL;
           char* target = NULL;
           char* fsoptions = NULL;
           int arg;
          
           for (  arg = 1; arg < argc; arg++ ) {
           if (  argv[arg][0] == '-' ) {
           if (  argv[arg][1] == 't' ) {
           arg++;
           if (  arg == argc ) {
           fprintf(  
           stderr,  
           "%s: -t needs a type of file-system;; see -L.\n",  
           argv[0]
            );
           return 1;
           }
           type = argv[arg];
           } else if (  argv[arg][1] == 'r' ) {
           options = RTEMS_FILESYSTEM_READ_ONLY;
           } else if (  argv[arg][1] == 'L' ) {
           printf (  "File systems: " );
           rtems_filesystem_iterate(  print_filesystem,   NULL );
           printf (  "\n" );
           return 0;
           } else if (  argv[arg][1] == 'o' ) {
           arg++;
           if (  arg == argc ) {
           fprintf(  
           stderr,  
           "%s: -o needs a list if filesystem options.\n",  
           argv[0]
            );
           return 1;
           }
           fsoptions = argv[arg];
           } else {
           fprintf (  stderr,   "unknown option: %s\n",   argv[arg] );
           return 1;
           }
           } else {
           if (  !source )
           source = argv[arg];
           else if (  !target )
           target = argv[arg];
           else {
           fprintf (  
           stderr,   "mount: source and mount only require: %s\n",   argv[arg] );
           return 1;
           }
           }
           }
          
           if (  !type ) {
           fprintf (  stderr,   "mount: no file-system; see the -L option\n" );
           return 1;
           }
          
           if (  !source ) {
           fprintf (  stderr,   "mount: no source\n" );
           return 1;
           }
          
           if (  !target ) {
           fprintf (  stderr,   "mount: no mount point\n" );
           return 1;
           }
          
           /*
           * Mount the disk.
           */
          
           if (  mount (  source,   target,   type,   options,   fsoptions ) < 0 ) {
           fprintf (  stderr,   "error: %s\n",   strerror(  errno ) );
           return 1;
           }
          
           printf (  "mounted %s -> %s\n",   source,   target );
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_MOUNT_Command = {
           "mount",   /* name */
           "mount [-t type] [-r] [-L] source target",   /* usage */
           "files",   /* topic */
           rtems_shell_main_mount,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_mount_nfs.c

       1  /*
           * Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_mount_nfs.c,  v 1.6 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
          #include <librtemsNfs.h>
          
          static int
      31  rtems_shell_nfs_mounter (  
           const char* device,  
           const char* mntpoint,  
           rtems_shell_filesystems_t* fs __attribute__(  (  unused ) ),  
           rtems_filesystem_options_t options __attribute__(  (  unused ) ) )
          {
           char* uidhost;
           char* path;
           int ret;
          
           if (  strchr (  device,   ':' ) == NULL ) {
           fprintf (  stderr,   "error: nfs mount device is [uid.gid@]host:path\n" );
           return -1;
           }
          
           if (  rpcUdpInit (   ) < 0 ) {
           fprintf (  stderr,   "error: initialising RPC\n" );
           return -1;
           }
          
           nfsInit (  0,   0 );
          
           uidhost = strdup (  device );
           path = strchr (  uidhost,   ':' );
           *path = '\0';
           path++;
          
           ret = nfsMount(  uidhost,   path,   (  char* ) mntpoint );
          
           free (  uidhost );
          
           return ret;
          }
          
          rtems_shell_filesystems_t rtems_shell_Mount_NFS = {
           name: "nfs",  
           driver_needed: 1,  
           fs_ops: NULL,  
           mounter: rtems_shell_nfs_mounter
          };

libmisc/shell/main_msdosfmt.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_msdosfmt.c,  v 1.11 2010/06/15 05:42:28 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          #include <inttypes.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include <rtems/shellconfig.h>
          #include <rtems/dosfs.h>
          #include <rtems/fsmount.h>
          #include "internal.h"
          
      27  int rtems_shell_main_msdos_format(  
           int argc,  
           char *argv[]
           )
          {
           msdos_format_request_param_t rqdata = {
           OEMName: "RTEMS",  
           VolLabel: "RTEMSDisk",  
           sectors_per_cluster: 0,  
           fat_num: 0,  
           files_per_root_dir: 0,  
           fattype: MSDOS_FMT_FATANY,  
           media: 0,  
           quick_format: TRUE,  
           cluster_align: 0,  
           info_level: 0
           };
          
           unsigned long tmp;
           const char* driver = NULL;
           int arg;
          
           for (  arg = 1; arg < argc; arg++ ) {
           if (  argv[arg][0] == '-' ) {
           switch (  argv[arg][1] ) {
           case 'V':
           arg++;
           if (  arg == argc ) {
           fprintf (  stderr,   "error: no volume label.\n" );
           return 1;
           }
           rqdata.VolLabel = argv[arg];
           break;
          
           case 's':
           arg++;
           if (  arg == argc ) {
           fprintf (  stderr,   "error: sectors per cluster count.\n" );
           return 1;
           }
          
           if (   rtems_string_to_unsigned_long(  argv[arg],   &tmp,   NULL,   0 )  ) {
           printf(  
           "sector per cluster argument (  %s ) is not a number\n",  
           argv[arg]
            );
           return -1;
           }
          
           rqdata.sectors_per_cluster = (  uint32_t ) tmp;
           break;
          
           case 'r':
           arg++;
           if (  arg == argc ) {
           fprintf (  stderr,   "error: no root directory size.\n" );
           return 1;
           }
          
           if (   rtems_string_to_unsigned_long(  argv[arg],   &tmp,   NULL,   0 )  ) {
           printf(  
           "root directory size argument (  %s ) is not a number\n",  
           argv[arg]
            );
           return -1;
           }
          
           rqdata.files_per_root_dir = (  uint32_t ) tmp;
           break;
          
           case 't':
           arg++;
           if (  arg == argc ) {
           fprintf (  stderr,   "error: no FAT type.\n" );
           return 1;
           }
          
           if (  strcmp (  argv[arg],   "any" ) == 0 )
           rqdata.fattype = MSDOS_FMT_FATANY;
           else if (  strcmp (  argv[arg],   "12" ) == 0 )
           rqdata.fattype = MSDOS_FMT_FAT12;
           else if (  strcmp (  argv[arg],   "16" ) == 0 )
           rqdata.fattype = MSDOS_FMT_FAT16;
           else if (  strcmp (  argv[arg],   "32" ) == 0 )
           rqdata.fattype = MSDOS_FMT_FAT32;
           else {
           fprintf (  stderr,   "error: invalid type,   can any,   12,   16,   or 32\n" );
           return 1;
           }
           break;
          
           case 'v':
           rqdata.info_level++;
           break;
          
           default:
           fprintf (  stderr,   "error: invalid option: %s\n",   argv[arg] );
           return 1;
          
           }
           } else {
           if (  !driver )
           driver = argv[arg];
           else {
           fprintf (  stderr,   "error: only one driver allowed: %s\n",   argv[arg] );
           return 1;
           }
           }
           }
          
           if (  !driver ) {
           fprintf (  stderr,   "error: no driver\n" );
           return 1;
           }
          
           printf (  "msdos format: %s\n",   driver );
          
           if (  rqdata.info_level )
           {
           printf (  " %-20s: %s\n",   "OEMName",   "RTEMS" );
           printf (  " %-20s: %s\n",   "VolLabel",   "RTEMSDisk" );
           printf (  " %-20s: %" PRIu32 "\n",   "sectors per cluster",   rqdata.sectors_per_cluster );
           printf (  " %-20s: %" PRIu32 "\n",   "fats",   rqdata.fat_num );
           printf (  " %-20s: %" PRIu32 "\n",   "files per root dir",   rqdata.files_per_root_dir );
           printf (  " %-20s: %i\n",   "fat type",   rqdata.fattype );
           printf (  " %-20s: %d\n",   "media",   rqdata.media );
           printf (  " %-20s: %d\n",   "quick_format",   rqdata.quick_format );
           printf (  " %-20s: %" PRIu32 "\n",   "cluster align",   rqdata.cluster_align );
           }
          
           if (  msdos_format (  driver,   &rqdata ) < 0 ) {
           fprintf (  stderr,   "error: format failed: %s\n",   strerror (  errno ) );
           return 1;
           }
          
           printf (  "msdos format successful\n" );
          
           return 0;
          }
          
          #define OPTIONS "[-v label] [-r size] [-t any/12/16/32]"
          
          rtems_shell_cmd_t rtems_shell_MSDOSFMT_Command = {
           "mkdos",   /* name */
           "mkdos " OPTIONS " path # format disk",   /* usage */
           "files",   /* topic */
           rtems_shell_main_msdos_format,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };
          
          rtems_shell_cmd_t rtems_shell_MSDOSFMT_Alias = {
           "msdosfmt",   /* name */
           NULL,   /* usage */
           "files",   /* topic */
           NULL,   /* command */
           &rtems_shell_MSDOSFMT_Command,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_mv.c

       1  /* $NetBSD: mv.c,  v 1.41 2008/07/20 00:52:40 lukem Exp $ */
          
          /*
           * Copyright (  c ) 1989,   1993,   1994
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Ken Smith of The State University of New York at Buffalo.
           *
           * 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. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if 0
          #include <sys/cdefs.h>
          #ifndef lint
      42  __COPYRIGHT(  "@(  # ) Copyright (  c ) 1989,   1993,   1994\
           The Regents of the University of California. All rights reserved." );
          #endif /* not lint */
          
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )mv.c 8.2 (  Berkeley ) 4/2/94";
          #else
      50  __RCSID(  "$NetBSD: mv.c,  v 1.41 2008/07/20 00:52:40 lukem Exp $" );
          #endif
          #endif /* not lint */
          #endif
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          #define __need_getopt_newlib
          #include <getopt.h>
          
          #include <sys/param.h>
          #include <sys/time.h>
          #include <sys/wait.h>
          #include <sys/stat.h>
          
          #include <err.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <grp.h>
          #include <locale.h>
          #include <pwd.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          
          #include "pathnames-mv.h"
          
          /* RTEMS specific changes */
          typedef struct {
           int fflg,   iflg,   vflg;
           int stdin_ok;
           int exit_code;
           jmp_buf exit_jmp;
          } rtems_shell_mv_globals;
          
      87  int copy(  char *,   char * );
      88  int do_move(  char *,   char * );
      89  int fastcopy(  char *,   char *,   struct stat * );
      90  void usage(  void );
      91  int main(  int,   char *[] );
          
          #define fflg globals->fflg
          #define iflg globals->iflg
          #define vflg globals->vflg
          #define stdin_ok globals->stdin_ok
          #define exit_jump &(  globals->exit_jmp )
          
          #include <setjmp.h>
          
          #define exit(  ec ) rtems_shell_mv_exit(  globals,   ec )
          
          void
     104  rtems_shell_mv_exit (  rtems_shell_mv_globals* globals,   int code )
          {
           globals->exit_code = code;
           longjmp (  globals->exit_jmp,   1 );
          }
          
     110  void strmode(  mode_t mode,   char *p );
     111  const char *user_from_uid(  uid_t uid,   int nouser );
     112  char *group_from_gid(  gid_t gid,   int nogroup );
          
     114  static int main_mv(  rtems_shell_mv_globals* globals,   int argc,   char *argv[] );
          
     116  int rtems_shell_main_cp(  int argc,   char *argv[] );
     117  int rtems_shell_main_rm(  int argc,   char *argv[] );
          
          int
     120  rtems_shell_main_mv(  int argc,   char *argv[] )
          {
           rtems_shell_mv_globals mv_globals;
           memset (  &mv_globals,   0,   sizeof (  mv_globals ) );
           mv_globals.exit_code = 1;
           if (  setjmp (  mv_globals.exit_jmp ) == 0 )
           return main_mv (  &mv_globals,   argc,   argv );
           return mv_globals.exit_code;
          }
          
          #define do_move(  a1,   a2 ) do_move_mv(  globals,   a1,   a2 )
          #define fastcopy(  a1,   a2,   a3 ) fastcopy_mv(  globals,   a1,   a2,   a3 )
          #define copy(  a1,   a2 ) copy_mv(  globals,   a1,   a2 )
          #define usage(   ) usage_mv(  globals )
          
     135  static int do_move_mv(  rtems_shell_mv_globals* globals,   char *from,   char *to );
     136  static int fastcopy_mv(  rtems_shell_mv_globals* globals,  
           char *from,   char *to,   struct stat *sbp );
     138  static int copy_mv(  rtems_shell_mv_globals* globals,   char *from,   char *to );
     139  static void usage_mv(  rtems_shell_mv_globals* globals );
          
          /* RTEMS changes */
          
          int
     144  main_mv(  rtems_shell_mv_globals* globals,   int argc,   char *argv[] )
          {
           int ch,   len,   rval;
           char *p,   *endp;
           struct stat sb;
           char path[MAXPATHLEN + 1];
           size_t baselen;
          
           struct getopt_data getopt_reent;
           memset(  &getopt_reent,   0,   sizeof(  getopt_data ) );
          
          /* setprogname(  argv[0] ); */
          
           (  void )setlocale(  LC_ALL,   "" );
          
           while (  (  ch = getopt_r(  argc,   argv,   "ifv",   &getopt_reent ) ) != -1 )
           switch (  ch ) {
           case 'i':
           fflg = 0;
           iflg = 1;
           break;
           case 'f':
           iflg = 0;
           fflg = 1;
           break;
           case 'v':
           vflg = 1;
           break;
           default:
           usage(   );
           }
           argc -= getopt_reent.optind;
           argv += getopt_reent.optind;
          
           if (  argc < 2 )
           usage(   );
          
           stdin_ok = isatty(  STDIN_FILENO );
          
           /*
           * If the stat on the target fails or the target isn't a directory,  
           * try the move. More than 2 arguments is an error in this case.
           */
           if (  stat(  argv[argc - 1],   &sb ) || !S_ISDIR(  sb.st_mode ) ) {
           if (  argc > 2 )
           usage(   );
           exit(  do_move(  argv[0],   argv[1] ) );
           }
          
           /* It's a directory,   move each file into it. */
           baselen = strlcpy(  path,   argv[argc - 1],   sizeof(  path ) );
           if (  baselen >= sizeof(  path ) )
           errx(  exit_jump,   1,   "%s: destination pathname too long",   argv[argc - 1] );
           endp = &path[baselen];
           if (  !baselen || *(  endp - 1 ) != '/' ) {
           *endp++ = '/';
           ++baselen;
           }
           for (  rval = 0; --argc; ++argv ) {
           p = *argv + strlen(  *argv ) - 1;
           while (  *p == '/' && p != *argv )
           *p-- = '\0';
           if (  (  p = strrchr(  *argv,   '/' ) ) == NULL )
           p = *argv;
           else
           ++p;
          
           if (  (  baselen + (  len = strlen(  p ) ) ) >= MAXPATHLEN ) {
           warnx(  "%s: destination pathname too long",   *argv );
           rval = 1;
           } else {
           memmove(  endp,   p,   len + 1 );
           if (  do_move(  *argv,   path ) )
           rval = 1;
           }
           }
           return rval;
          }
          
          int
     224  do_move_mv(  rtems_shell_mv_globals* globals,   char *from,   char *to )
          {
           struct stat sb;
           char modep[15];
          
           /*
           * (  1 ) If the destination path exists,   the -f option is not specified
           * and either of the following conditions are true:
           *
           * (  a ) The permissions of the destination path do not permit
           * writing and the standard input is a terminal.
           * (  b ) The -i option is specified.
           *
           * the mv utility shall write a prompt to standard error and
           * read a line from standard input. If the response is not
           * affirmative,   mv shall do nothing more with the current
           * source file...
           */
           if (  !fflg && !access(  to,   F_OK ) ) {
           int ask = 1;
           int ch;
          
           if (  iflg ) {
           if (  access(  from,   F_OK ) ) {
           warn(  "rename %s",   from );
           return (  1 );
           }
           (  void )fprintf(  stderr,   "overwrite %s? ",   to );
           } else if (  stdin_ok && access(  to,   W_OK ) && !stat(  to,   &sb ) ) {
           if (  access(  from,   F_OK ) ) {
           warn(  "rename %s",   from );
           return (  1 );
           }
           strmode(  sb.st_mode,   modep );
           (  void )fprintf(  stderr,   "override %s%s%s/%s for %s? ",  
           modep + 1,   modep[9] == ' ' ? "" : " ",  
           user_from_uid(  sb.st_uid,   0 ),  
           group_from_gid(  sb.st_gid,   0 ),   to );
           } else
           ask = 0;
           if (  ask ) {
           if (  (  ch = getchar(   ) ) != EOF && ch != '\n' ) {
           int ch2;
           while (  (  ch2 = getchar(   ) ) != EOF && ch2 != '\n' )
           continue;
           }
           if (  ch != 'y' && ch != 'Y' )
           return (  0 );
           }
           }
          
           /*
           * (  2 ) If rename(   ) succeeds,   mv shall do nothing more with the
           * current source file. If it fails for any other reason than
           * EXDEV,   mv shall write a diagnostic message to the standard
           * error and do nothing more with the current source file.
           *
           * (  3 ) If the destination path exists,   and it is a file of type
           * directory and source_file is not a file of type directory,  
           * or it is a file not of type directory,   and source file is
           * a file of type directory,   mv shall write a diagnostic
           * message to standard error,   and do nothing more with the
           * current source file...
           */
           if (  !rename(  from,   to ) ) {
           if (  vflg )
           printf(  "%s -> %s\n",   from,   to );
           return (  0 );
           }
          
           if (  errno != EXDEV ) {
           warn(  "rename %s to %s",   from,   to );
           return (  1 );
           }
          
           /*
           * (  4 ) If the destination path exists,   mv shall attempt to remove it.
           * If this fails for any reason,   mv shall write a diagnostic
           * message to the standard error and do nothing more with the
           * current source file...
           */
           if (  !lstat(  to,   &sb ) ) {
           if (  (  S_ISDIR(  sb.st_mode ) ) ? rmdir(  to ) : unlink(  to ) ) {
           warn(  "can't remove %s",   to );
           return (  1 );
           }
           }
          
           /*
           * (  5 ) The file hierarchy rooted in source_file shall be duplicated
           * as a file hierarchy rooted in the destination path...
           */
           if (  lstat(  from,   &sb ) ) {
           warn(  "%s",   from );
           return (  1 );
           }
          
           return (  S_ISREG(  sb.st_mode ) ?
           fastcopy(  from,   to,   &sb ) : copy(  from,   to ) );
          }
          
          int
     326  fastcopy_mv(  rtems_shell_mv_globals* globals,   char *from,   char *to,   struct stat *sbp )
          {
           struct timeval tval[2];
           uint32_t blen;
           static char *bp;
           int nread,   from_fd,   to_fd;
          
           blen = 0;
          
           if (  (  from_fd = open(  from,   O_RDONLY,   0 ) ) < 0 ) {
           warn(  "%s",   from );
           return (  1 );
           }
           if (  (  to_fd =
           open(  to,   O_CREAT | O_TRUNC | O_WRONLY,   sbp->st_mode ) ) < 0 ) {
           warn(  "%s",   to );
           (  void )close(  from_fd );
           return (  1 );
           }
           if (  !blen && !(  bp = malloc(  blen = sbp->st_blksize ) ) ) {
           warn(  NULL );
           blen = 0;
           (  void )close(  from_fd );
           (  void )close(  to_fd );
           return (  1 );
           }
           while (  (  nread = read(  from_fd,   bp,   blen ) ) > 0 )
           if (  write(  to_fd,   bp,   nread ) != nread ) {
           warn(  "%s",   to );
           goto err;
           }
           if (  nread < 0 ) {
           warn(  "%s",   from );
          err: if (  unlink(  to ) )
           warn(  "%s: remove",   to );
           (  void )free(  bp );
           (  void )close(  from_fd );
           (  void )close(  to_fd );
           return (  1 );
           }
          
           (  void )free(  bp );
           (  void )close(  from_fd );
          #ifdef xBSD4_4
           TIMESPEC_TO_TIMEVAL(  &tval[0],   &sbp->st_atimespec );
           TIMESPEC_TO_TIMEVAL(  &tval[1],   &sbp->st_mtimespec );
          #else
           tval[0].tv_sec = sbp->st_atime;
           tval[1].tv_sec = sbp->st_mtime;
           tval[0].tv_usec = 0;
           tval[1].tv_usec = 0;
          #endif
          #if 0
          #ifdef _SRV5
           if (  utimes(  to,   tval ) )
          #else
           if (  futimes(  to_fd,   tval ) )
          #endif
           warn(  "%s: set times",   to );
          #endif
           if (  fchown(  to_fd,   sbp->st_uid,   sbp->st_gid ) ) {
           if (  errno != EPERM )
           warn(  "%s: set owner/group",   to );
           sbp->st_mode &= ~(  S_ISUID | S_ISGID );
           }
           if (  fchmod(  to_fd,   sbp->st_mode ) )
           warn(  "%s: set mode",   to );
          #if 0
           if (  fchflags(  to_fd,   sbp->st_flags ) && (  errno != EOPNOTSUPP ) )
           warn(  "%s: set flags (  was: 0%07o )",   to,   sbp->st_flags );
          #endif
           if (  close(  to_fd ) ) {
           warn(  "%s",   to );
           return (  1 );
           }
          
           if (  unlink(  from ) ) {
           warn(  "%s: remove",   from );
           return (  1 );
           }
          
           if (  vflg )
           printf(  "%s -> %s\n",   from,   to );
          
           return (  0 );
          }
          
          int
     414  copy_mv(  rtems_shell_mv_globals* globals,   char *from,   char *to )
          {
           char* cp_argv[5] = { "mv",   vflg ? "-PRpv" : "-PRp",   "--",   from,   to };
           char* rm_argv[4] = { "mv",   "-rf",   "--",   from };
           int result;
          
           result = rtems_shell_main_cp(  5,   cp_argv );
           if (  result ) {
           warnx(  "%s: did not terminate normally",   _PATH_CP );
           return (  1 );
           }
           result = rtems_shell_main_rm(  4,   rm_argv );
           if (  result ) {
           warnx(  "%s: did not terminate normally",   _PATH_RM );
           return (  1 );
           }
          #if 0
           pid_t pid;
           int status;
          
           if (  (  pid = vfork(   ) ) == 0 ) {
           execl(  _PATH_CP,   "mv",   vflg ? "-PRpv" : "-PRp",   "--",   from,   to,   NULL );
           warn(  "%s",   _PATH_CP );
           _exit(  1 );
           }
           if (  waitpid(  pid,   &status,   0 ) == -1 ) {
           warn(  "%s: waitpid",   _PATH_CP );
           return (  1 );
           }
           if (  !WIFEXITED(  status ) ) {
           warnx(  "%s: did not terminate normally",   _PATH_CP );
           return (  1 );
           }
           if (  WEXITSTATUS(  status ) ) {
           warnx(  "%s: terminated with %d (  non-zero ) status",  
           _PATH_CP,   WEXITSTATUS(  status ) );
           return (  1 );
           }
           if (  !(  pid = vfork(   ) ) ) {
           execl(  _PATH_RM,   "mv",   "-rf",   "--",   from,   NULL );
           warn(  "%s",   _PATH_RM );
           _exit(  1 );
           }
           if (  waitpid(  pid,   &status,   0 ) == -1 ) {
           warn(  "%s: waitpid",   _PATH_RM );
           return (  1 );
           }
           if (  !WIFEXITED(  status ) ) {
           warnx(  "%s: did not terminate normally",   _PATH_RM );
           return (  1 );
           }
           if (  WEXITSTATUS(  status ) ) {
           warnx(  "%s: terminated with %d (  non-zero ) status",  
           _PATH_RM,   WEXITSTATUS(  status ) );
           return (  1 );
           }
          #endif
           return (  0 );
          }
          
          void
     475  usage_mv(  rtems_shell_mv_globals* globals )
          {
           (  void )fprintf(  stderr,   "usage: %s [-fiv] source target\n"
           " %s [-fiv] source ... directory\n",  
           "mv",   "mv" );
           exit(  1 );
           /* NOTREACHED */
          }
          
          rtems_shell_cmd_t rtems_shell_MV_Command = {
           "mv",   /* name */
           "[-fiv] source target ...",   /* usage */
           "files",   /* topic */
           rtems_shell_main_mv,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_mwdump.c

       1  /*
           * MWDUMP Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_mwdump.c,  v 1.9 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <ctype.h>
          #include <stdio.h>
          #include <string.h>
          #include <inttypes.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include "internal.h"
          
      29  int rtems_shell_main_mwdump(  
           int argc,  
           char *argv[]
           )
          {
           unsigned char n;
           unsigned char m;
           int max;
           int res;
           void *addr = 0;
           unsigned char *pb;
          
           if (   argc > 1  ) {
           if (   rtems_string_to_pointer(  argv[1],   &addr,   NULL )  ) {
           printf(   "Address argument (  %s ) is not a number\n",   argv[1]  );
           return -1;
           }
           }
          
           if (   argc > 2  ) {
           if (   rtems_string_to_int(  argv[2],   &max,   NULL,   0 )  ) {
           printf(   "Address argument (  %s ) is not a number\n",   argv[1]  );
           return -1;
           }
          
           if (  max <= 0 ) {
           max = 1; /* print 1 item if 0 or neg. */
           res = 0;
           } else {
           max--;
           res = max & 0xf;/* num bytes in last row */
           max >>= 4; /* div by 16 */
           max++; /* num of rows to print */
           if (  max > 20 ) { /* limit to 20 */
           max = 20;
           res = 0xf; /* 16 bytes print in last row */
           }
           }
           } else {
           max = 20;
           res = 0xf;
           }
          
           pb = addr;
           for (  m=0;m<max;m++ ) {
           printf(  "%10p ",   pb );
           for (  n=0;n<=(  m==(  max-1 )?res:0xf );n+=2 )
           printf(  "%04X%c",  *(  (  unsigned short* )(  pb+n ) ),  n==6?'-':' ' );
           for (  ;n<=0xf;n+=2 )
           printf(  " %c",   n==6?'-':' ' );
           for (  n=0;n<=(  m==(  max-1 )?res:0xf );n++ ) {
           printf(  "%c",   isprint(  pb[n] ) ? pb[n] : '.' );
           }
           printf(  "\n" );
           pb += 16;
           }
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_WDUMP_Command = {
           "wdump",   /* name */
           "wdump [address [length]]",   /* usage */
           "mem",   /* topic */
           rtems_shell_main_mwdump,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_netstats.c

       1  /*
           * Network Statistics Shell Command Implmentation
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: main_netstats.c,  v 1.7 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #define __need_getopt_newlib
          #include <getopt.h>
          
          #include <rtems.h>
          #include <rtems/rtems_bsdnet.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      27  static void netstats_usage(  void )
          {
           printf(  
           "netstats [-vAimfpcut] where:\n"
           " -A print All statistics\n"
           " -i print Inet Routes\n"
           " -m print MBUF Statistics\n"
           " -f print IF Statistics\n"
           " -p print IP Statistics\n"
           " -c print ICMP Statistics\n"
           " -u print UDP Statistics\n"
           " -t print TCP Statistics\n"
            );
          }
          
      42  int rtems_shell_main_netstats(   /* command */
           int argc,  
           char *argv[]
           )
          {
           int option;
           int doAll = 0;
           int doInetRoutes = 0;
           int doMBUFStats = 0;
           int doIFStats = 0;
           int doIPStats = 0;
           int doICMPStats = 0;
           int doUDPStats = 0;
           int doTCPStats = 0;
           int verbose = 0;
           struct getopt_data getopt_reent;
          
           memset(  &getopt_reent,   0,   sizeof(  getopt_data ) );
           while (   (  option = getopt_r(   argc,   argv,   "Aimfpcutv",   &getopt_reent ) ) != -1  ) {
          
           switch (  (  char )option ) {
           case 'A': doAll = 1; break;
           case 'i': doInetRoutes = 1; break;
           case 'm': doMBUFStats = 1; break;
           case 'f': doIFStats = 1; break;
           case 'p': doIPStats = 1; break;
           case 'c': doICMPStats = 1; break;
           case 'u': doUDPStats = 1; break;
           case 't': doTCPStats = 1; break;
           case 'v': verbose = 1; break;
           case '?':
           default:
           netstats_usage(   );
           return -1;
           }
           }
          
           if (   verbose  ) {
           printf(  
           "doAll=%d\n"
           "doInetRoutes=%d\n"
           "doMBUFStats=%d\n"
           "doIFStats=%d\n"
           "doIPStats=%d\n"
           "doICMPStats=%d\n"
           "doUDPStats=%d\n"
           "doTCPStats=%d\n",  
           doAll,  
           doInetRoutes,  
           doMBUFStats,  
           doIFStats,  
           doIPStats,  
           doICMPStats,  
           doUDPStats,  
           doTCPStats
            );
           }
          
           if (   doInetRoutes == 1 || doAll == 1  ) {
           rtems_bsdnet_show_inet_routes(   );
           }
          
           if (   doMBUFStats == 1 || doAll == 1  ) {
           rtems_bsdnet_show_mbuf_stats(   );
           }
          
           if (   doIFStats == 1 || doAll == 1  ) {
           rtems_bsdnet_show_if_stats(   );
           }
          
           if (   doIPStats == 1 || doAll == 1  ) {
           rtems_bsdnet_show_ip_stats(   );
           }
          
           if (   doICMPStats == 1 || doAll == 1  ) {
           rtems_bsdnet_show_icmp_stats(   );
           }
          
           if (   doUDPStats == 1 || doAll == 1  ) {
           rtems_bsdnet_show_udp_stats(   );
           }
          
           if (   doTCPStats == 1 || doAll == 1  ) {
           rtems_bsdnet_show_tcp_stats(   );
           }
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_NETSTATS_Command = {
           "netstats",   /* name */
           "netstats [-Aimfpcutv]",   /* usage */
           "network",   /* topic */
           rtems_shell_main_netstats,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_perioduse.c

       1  /*
           * perioduse Command Implementation
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: main_perioduse.c,  v 1.3 2008/03/05 02:49:35 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      24  int rtems_shell_main_perioduse(  
           int argc,  
           char *argv[]
           )
          {
           /*
           * When invoked with no arguments,   print the report.
           */
           if (   argc == 1  ) {
           rtems_rate_monotonic_report_statistics_with_plugin(  
           stdout,  
           (  rtems_printk_plugin_t )fprintf
            );
           return 0;
           }
          
           /*
           * When invoked with the single argument -r,   reset the statistics.
           */
           if (   argc == 2 && !strcmp(   argv[1],   "-r"  )  ) {
           printf(   "Resetting Period Usage information\n"  );
           rtems_rate_monotonic_reset_all_statistics(   );
           return 0;
           }
          
           /*
           * OK. The user did something wrong.
           */
           fprintf(   stderr,   "%s: [-r]\n",   argv[0]  );
           return -1;
          }
          
          rtems_shell_cmd_t rtems_shell_PERIODUSE_Command = {
           "perioduse",   /* name */
           "[-r] print or reset per period usage",   /* usage */
           "rtems",   /* topic */
           rtems_shell_main_perioduse,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_pwd.c

       1  /*
           * PWD Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_pwd.c,  v 1.5 2009/01/02 13:01:21 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      26  int rtems_shell_main_pwd(  
           int argc __attribute__(  (  unused ) ),  
           char *argv[] __attribute__(  (  unused ) )
           )
          {
           char dir[1024];
          
           getcwd(  dir,  1024 );
           puts(  dir );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_PWD_Command = {
           "pwd",   /* name */
           "pwd # print work directory",   /* usage */
           "files",   /* topic */
           rtems_shell_main_pwd,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_rm.c

       1  /*-
           * Copyright (  c ) 1990,   1993,   1994
           * The Regents of the University of California. 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if 0
          #ifndef lint
          static const char copyright[] =
          "@(  # ) Copyright (  c ) 1990,   1993,   1994\n\
           The Regents of the University of California. All rights reserved.\n";
          #endif /* not lint */
          
          #ifndef lint
          static char sccsid[] = "@(  # )rm.c 8.5 (  Berkeley ) 4/18/94";
          #endif /* not lint */
          #endif
          #if 0
          #include <sys/cdefs.h>
      47  __FBSDID(  "$FreeBSD: src/bin/rm/rm.c,  v 1.58 2006/10/31 02:22:36 delphij Exp $" );
          #endif
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          #define __need_getopt_newlib
          #include <getopt.h>
          
          #include <sys/stat.h>
          #include <sys/param.h>
          
          #include <err.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <fts.h>
          #include <grp.h>
          #include <pwd.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #ifdef HAVE_STRINGS_H
          #include <strings.h>
          #endif
          #include <unistd.h>
          
          /* RTEMS specific changes */
          typedef struct {
           int dflag,   eval,   fflag,   iflag,   Pflag,   vflag,   Wflag,   stdin_ok;
           int rflag,   Iflag;
           uid_t uid;
           int exit_code;
           jmp_buf exit_jmp;
          } rtems_shell_rm_globals;
          
          #define dflag globals->dflag
          #define eval globals->eval
          #define fflag globals->fflag
          #define iflag globals->iflag
          #define Pflag globals->Pflag
          #define vflag globals->vflag
          #define Wflag globals->Wflag
          #define stdin_ok globals->stdin_ok
          #define rflag globals->rflag
          #define Iflag globals->Iflag
          #define xuid globals->uid
          #define exit_jump &(  globals->exit_jmp )
          
          #include <setjmp.h>
          
          #define exit(  ec ) rtems_shell_rm_exit(  globals,   ec )
          void
      99  rtems_shell_rm_exit (  rtems_shell_rm_globals* globals,   int code )
          {
           globals->exit_code = code;
           longjmp (  globals->exit_jmp,   1 );
          }
          
     105  static int main_rm(  rtems_shell_rm_globals* globals,   int argc,   char *argv[] );
          
          int
     108  rtems_shell_main_rm(  int argc,   char *argv[] )
          {
           rtems_shell_rm_globals rm_globals;
           memset (  &rm_globals,   0,   sizeof (  rm_globals ) );
           rm_globals.exit_code = 1;
           if (  setjmp (  rm_globals.exit_jmp ) == 0 )
           return main_rm (  &rm_globals,   argc,   argv );
           return rm_globals.exit_code;
          }
          
          #define check(  a1,   a2,   a3 ) check_rm(  globals,   a1,   a2,   a3 )
          #define check2(  a1 ) check2_rm(  globals,   a1 )
          #define checkdot(  a1 ) checkdot_rm(  globals,   a1 )
          #define checkslash(  a1 ) checkslash_rm(  globals,   a1 )
          #define rm_file(  a1 ) rm_file_rm(  globals,   a1 )
          #define rm_overwrite(  a1,   a2 ) rm_overwrite_rm(  globals,   a1,   a2 )
          #define rm_tree(  a1 ) rm_tree_rm(  globals,   a1 )
          #define usage(   ) usage_rm(  globals )
          
          
          /* RTEMS changes */
          
     130  static int check_rm(  rtems_shell_rm_globals* globals,   char *,   char *,   struct stat * );
     131  static int check2_rm(  rtems_shell_rm_globals* globals,   char ** );
     132  static void checkdot_rm(  rtems_shell_rm_globals* globals,   char ** );
     133  static void checkslash_rm(  rtems_shell_rm_globals* globals,   char ** );
     134  static void rm_file_rm(  rtems_shell_rm_globals* globals,   char ** );
     135  static int rm_overwrite_rm(  rtems_shell_rm_globals* globals,   char *,   struct stat * );
     136  static void rm_tree_rm(  rtems_shell_rm_globals* globals,   char ** );
     137  static void usage_rm(  rtems_shell_rm_globals* globals );
          
          /*
           * rm --
           * This rm is different from historic rm's,   but is expected to match
           * POSIX 1003.2 behavior. The most visible difference is that -f
           * has two specific effects now,   ignore non-existent files and force
           * file removal.
           */
          int
     147  main_rm(  rtems_shell_rm_globals* globals,   int argc,   char *argv[] )
          {
           int ch;
           char *p;
          
           struct getopt_data getopt_reent;
           memset(  &getopt_reent,   0,   sizeof(  getopt_data ) );
          
           /*
           * Test for the special case where the utility is called as
           * "unlink",   for which the functionality provided is greatly
           * simplified.
           */
           if (  (  p = rindex(  argv[0],   '/' ) ) == NULL )
           p = argv[0];
           else
           ++p;
           if (  strcmp(  p,   "unlink" ) == 0 ) {
           while (  getopt_r(  argc,   argv,   "",   &getopt_reent ) != -1 )
           usage(   );
           argc -= getopt_reent.optind;
           argv += getopt_reent.optind;
           if (  argc != 1 )
           usage(   );
           rm_file(  &argv[0] );
           exit(  eval );
           }
          
           Pflag = rflag = 0;
           while (  (  ch = getopt_r(  argc,   argv,   "dfiIPRrvW",   &getopt_reent ) ) != -1 )
           switch(  ch ) {
           case 'd':
           dflag = 1;
           break;
           case 'f':
           fflag = 1;
           iflag = 0;
           break;
           case 'i':
           fflag = 0;
           iflag = 1;
           break;
           case 'I':
           Iflag = 1;
           break;
           case 'P':
           Pflag = 1;
           break;
           case 'R':
           case 'r': /* Compatibility. */
           rflag = 1;
           break;
           case 'v':
           vflag = 1;
           break;
           case 'W':
           Wflag = 1;
           break;
           default:
           usage(   );
           }
           argc -= getopt_reent.optind;
           argv += getopt_reent.optind;
          
           if (  argc < 1 ) {
           if (  fflag )
           return (  0 );
           usage(   );
           }
          
           checkdot(  argv );
           if (  getenv(  "POSIXLY_CORRECT" ) == NULL )
           checkslash(  argv );
           xuid = geteuid(   );
          
           if (  *argv ) {
           stdin_ok = isatty(  STDIN_FILENO );
          
           if (  Iflag ) {
           if (  check2(  argv ) == 0 )
           exit (  1 );
           }
           if (  rflag )
           rm_tree(  argv );
           else
           rm_file(  argv );
           }
          
           exit (  eval );
           return 0;
          }
          
          void
     240  rm_tree_rm(  rtems_shell_rm_globals* globals,   char **argv )
          {
           FTS *fts;
           FTSENT *p;
           int needstat;
           int flags;
           int rval;
          
           /*
           * Remove a file hierarchy. If forcing removal (  -f ),   or interactive
           * (  -i ) or can't ask anyway (  stdin_ok ),   don't stat the file.
           */
           needstat = !xuid || (  !fflag && !iflag && stdin_ok );
          
           /*
           * If the -i option is specified,   the user can skip on the pre-order
           * visit. The fts_number field flags skipped directories.
           */
          #define SKIPPED 1
          
           flags = FTS_PHYSICAL;
           if (  !needstat )
           flags |= FTS_NOSTAT;
           if (  Wflag )
           flags |= FTS_WHITEOUT;
           if (  !(  fts = fts_open(  argv,   flags,   NULL ) ) ) {
           if (  fflag && errno == ENOENT )
           return;
           err(  exit_jump,   1,   "fts_open" );
           }
           while (  (  p = fts_read(  fts ) ) != NULL ) {
           switch (  p->fts_info ) {
           case FTS_DNR:
           if (  !fflag || p->fts_errno != ENOENT ) {
           warnx(  "%s: %s",  
           p->fts_path,   strerror(  p->fts_errno ) );
           eval = 1;
           }
           continue;
           case FTS_ERR:
           errx(  exit_jump,   1,   "%s: %s",   p->fts_path,   strerror(  p->fts_errno ) );
           case FTS_NS:
           /*
           * Assume that since fts_read(   ) couldn't stat the
           * file,   it can't be unlinked.
           */
           if (  !needstat )
           break;
           if (  !fflag || p->fts_errno != ENOENT ) {
           warnx(  "%s: %s",  
           p->fts_path,   strerror(  p->fts_errno ) );
           eval = 1;
           }
           continue;
           case FTS_D:
           /* Pre-order: give user chance to skip. */
           if (  !fflag && !check(  p->fts_path,   p->fts_accpath,  
           p->fts_statp ) ) {
           (  void )fts_set(  fts,   p,   FTS_SKIP );
           p->fts_number = SKIPPED;
           }
          #if RTEMS_REMOVED
           else if (  !xuid &&
           (  p->fts_statp->st_flags & (  UF_APPEND|UF_IMMUTABLE ) ) &&
           !(  p->fts_statp->st_flags & (  SF_APPEND|SF_IMMUTABLE ) ) &&
           chflags(  p->fts_accpath,  
           p->fts_statp->st_flags &= ~(  UF_APPEND|UF_IMMUTABLE ) ) < 0 )
           goto err;
          #endif
           continue;
           case FTS_DP:
           /* Post-order: see if user skipped. */
           if (  p->fts_number == SKIPPED )
           continue;
           break;
           default:
           if (  !fflag &&
           !check(  p->fts_path,   p->fts_accpath,   p->fts_statp ) )
           continue;
           }
          
           rval = 0;
          #if RTEMS_REMOVED
           if (  !xuid &&
           (  p->fts_statp->st_flags & (  UF_APPEND|UF_IMMUTABLE ) ) &&
           !(  p->fts_statp->st_flags & (  SF_APPEND|SF_IMMUTABLE ) ) )
           rval = chflags(  p->fts_accpath,  
           p->fts_statp->st_flags &= ~(  UF_APPEND|UF_IMMUTABLE ) );
          #endif
           if (  rval == 0 ) {
           /*
           * If we can't read or search the directory,   may still be
           * able to remove it. Don't print out the un{read,  search}able
           * message unless the remove fails.
           */
           switch (  p->fts_info ) {
           case FTS_DP:
           case FTS_DNR:
           rval = rmdir(  p->fts_accpath );
           if (  rval == 0 || (  fflag && errno == ENOENT ) ) {
           if (  rval == 0 && vflag )
           (  void )printf(  "%s\n",  
           p->fts_path );
           continue;
           }
           break;
          
          #if RTEMS_REMOVED
           case FTS_W:
           rval = undelete(  p->fts_accpath );
           if (  rval == 0 && (  fflag && errno == ENOENT ) ) {
           if (  vflag )
           (  void )printf(  "%s\n",  
           p->fts_path );
           continue;
           }
           break;
          #endif
          
           case FTS_NS:
           /*
           * Assume that since fts_read(   ) couldn't stat
           * the file,   it can't be unlinked.
           */
           if (  fflag )
           continue;
           /* FALLTHROUGH */
           default:
           if (  Pflag )
           if (  !rm_overwrite(  p->fts_accpath,   NULL ) )
           continue;
           rval = unlink(  p->fts_accpath );
           if (  rval == 0 || (  fflag && errno == ENOENT ) ) {
           if (  rval == 0 && vflag )
           (  void )printf(  "%s\n",  
           p->fts_path );
           continue;
           }
           }
           }
          #if RTEMS_REMOVED
          err:
          #endif
           warn(  "%s",   p->fts_path );
           eval = 1;
           }
           if (  errno )
           err(  exit_jump,   1,   "fts_read" );
           fts_close(  fts );
          }
          
          #define S_ISWHT(  m ) (  0 )
          
          void
     394  rm_file_rm(  rtems_shell_rm_globals* globals,   char **argv )
          {
           struct stat sb;
           int rval;
           char *f;
          
           /*
           * Remove a file. POSIX 1003.2 states that,   by default,   attempting
           * to remove a directory is an error,   so must always stat the file.
           */
           while (  (  f = *argv++ ) != NULL ) {
           /* Assume if can't stat the file,   can't unlink it. */
           if (  lstat(  f,   &sb ) ) {
          #if RTEMS_REMOVED
           if (  Wflag ) {
           sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
           } else {
          #endif
           if (  !fflag || errno != ENOENT ) {
           warn(  "%s",   f );
           eval = 1;
           }
           continue;
          #if RTEMS_REMOVED
           }
          #endif
           } else if (  Wflag ) {
           warnx(  "%s: %s",   f,   strerror(  EEXIST ) );
           eval = 1;
           continue;
           }
          
           if (  S_ISDIR(  sb.st_mode ) && !dflag ) {
           warnx(  "%s: is a directory",   f );
           eval = 1;
           continue;
           }
           if (  !fflag && !S_ISWHT(  sb.st_mode ) && !check(  f,   f,   &sb ) )
           continue;
           rval = 0;
          #if RTEMS_REMOVED
           if (  !xuid && !S_ISWHT(  sb.st_mode ) &&
           (  sb.st_flags & (  UF_APPEND|UF_IMMUTABLE ) ) &&
           !(  sb.st_flags & (  SF_APPEND|SF_IMMUTABLE ) ) )
           rval = chflags(  f,   sb.st_flags & ~(  UF_APPEND|UF_IMMUTABLE ) );
          #endif
           if (  rval == 0 ) {
           if (  S_ISWHT(  sb.st_mode ) )
          #if RTEMS_REMOVED
           rval = undelete(  f );
          #endif
           ;
           else if (  S_ISDIR(  sb.st_mode ) )
           rval = rmdir(  f );
           else {
           if (  Pflag )
           if (  !rm_overwrite(  f,   &sb ) )
           continue;
           rval = unlink(  f );
           }
           }
           if (  rval && (  !fflag || errno != ENOENT ) ) {
           warn(  "%s",   f );
           eval = 1;
           }
           if (  vflag && rval == 0 )
           (  void )printf(  "%s\n",   f );
           }
          }
          
          /*
           * rm_overwrite --
           * Overwrite the file 3 times with varying bit patterns.
           *
           * XXX
           * This is a cheap way to *really* delete files. Note that only regular
           * files are deleted,   directories (  and therefore names ) will remain.
           * Also,   this assumes a fixed-block file system (  like FFS,   or a V7 or a
           * System V file system ). In a logging file system,   you'll have to have
           * kernel support.
           */
          int
     476  rm_overwrite_rm(  rtems_shell_rm_globals* globals,   char *file,   struct stat *sbp )
          {
           struct stat sb;
          #if RTEMS_REMOVED
           struct statfs fsb;
          #endif
           off_t len;
           int bsize,   fd,   wlen;
           char *buf = NULL;
          
           fd = -1;
           if (  sbp == NULL ) {
           if (  lstat(  file,   &sb ) )
           goto err;
           sbp = &sb;
           }
           if (  !S_ISREG(  sbp->st_mode ) )
           return (  1 );
           if (  sbp->st_nlink > 1 && !fflag ) {
           warnx(  "%s (  inode %lu ): not overwritten due to multiple links",  
           file,   sbp->st_ino );
           return (  0 );
           }
           if (  (  fd = open(  file,   O_WRONLY,   0 ) ) == -1 )
           goto err;
          #if RTEMS_REMOVED
           if (  fstatfs(  fd,   &fsb ) == -1 )
           goto err;
           bsize = MAX(  fsb.f_iosize,   1024 );
          #endif
           bsize = 1024;
           if (  (  buf = malloc(  bsize ) ) == NULL )
           err(  exit_jump,   1,   "%s: malloc",   file );
          
          #define PASS(  byte ) { \
           memset(  buf,   byte,   bsize ); \
           for (  len = sbp->st_size; len > 0; len -= wlen ) { \
           wlen = len < bsize ? len : bsize; \
           if (  write(  fd,   buf,   wlen ) != wlen ) \
           goto err; \
           } \
          }
           PASS(  0xff );
           if (  fsync(  fd ) || lseek(  fd,   (  off_t )0,   SEEK_SET ) )
           goto err;
           PASS(  0x00 );
           if (  fsync(  fd ) || lseek(  fd,   (  off_t )0,   SEEK_SET ) )
           goto err;
           PASS(  0xff );
           if (  !fsync(  fd ) && !close(  fd ) ) {
           free(  buf );
           return (  1 );
           }
          
          err: eval = 1;
           if (  buf )
     532   free(  buf );
     533   if (  fd != -1 )
     534   close(  fd );
           warn(  "%s",   file );
           return (  0 );
     537  }
          
          void strmode(  mode_t mode,   char *p );
          char *fflagstostr(  u_long flags );
          const char *user_from_uid(  uid_t uid,   int nouser );
          
          int
          check_rm(  rtems_shell_rm_globals* globals,   char *path,   char *name,   struct stat *sp )
          {
           int ch,   first;
           char modep[15],   *flagsp;
          
           /* Check -i first. */
           if (  iflag )
           (  void )fprintf(  stderr,   "remove %s? ",   path );
           else {
           /*
           * If it's not a symbolic link and it's unwritable and we're
           * talking to a terminal,   ask. Symbolic links are excluded
           * because their permissions are meaningless. Check stdin_ok
           * first because we may not have stat'ed the file.
           */
          #if RTEMS_REMOVED
           if (  !stdin_ok || S_ISLNK(  sp->st_mode ) ||
           (  !access(  name,   W_OK ) &&
           !(  sp->st_flags & (  SF_APPEND|SF_IMMUTABLE ) ) &&
           (  !(  sp->st_flags & (  UF_APPEND|UF_IMMUTABLE ) ) || !xuid ) ) )
          #endif
           if (  !stdin_ok || S_ISLNK(  sp->st_mode ) ||
           (  !access(  name,   W_OK ) ) )
           return (  1 );
           strmode(  sp->st_mode,   modep );
          #if RTEMS_REMOVED
           if (  (  flagsp = fflagstostr(  sp->st_flags ) ) == NULL )
           err(  exit_jump,   1,   "fflagstostr" );
          #else
           flagsp = "no supported";
          #endif
           if (  Pflag )
           errx(  exit_jump,   1,  
           "%s: -P was specified,   but file is not writable",  
           path );
           (  void )fprintf(  stderr,   "override %s%s%s/%s %s%sfor %s? ",  
           modep + 1,   modep[9] == ' ' ? "" : " ",  
           user_from_uid(  sp->st_uid,   0 ),  
           group_from_gid(  sp->st_gid,   0 ),  
           *flagsp ? flagsp : "",   *flagsp ? " " : "",  
           path );
          #if RTEMS_REMOVED
           free(  flagsp );
          #endif
           }
           (  void )fflush(  stderr );
          
           first = ch = getchar(   );
     592   while (  ch != '\n' && ch != EOF )
           ch = getchar(   );
           return (  first == 'y' || first == 'Y' );
          }
          
          #define ISSLASH(  a ) (  (  a )[0] == '/' && (  a )[1] == '\0' )
          void
          checkslash_rm(  rtems_shell_rm_globals* globals,   char **argv )
          {
           char **t,   **u;
           int complained;
          
           complained = 0;
           for (  t = argv; *t; ) {
           if (  ISSLASH(  *t ) ) {
           if (  !complained++ )
           warnx(  "\"/\" may not be removed" );
           eval = 1;
           for (  u = t; u[0] != NULL; ++u )
           u[0] = u[1];
     612   } else {
           ++t;
           }
           }
          }
          
          int
          check2_rm(  rtems_shell_rm_globals* globals,   char **argv )
          {
           struct stat st;
           int first;
           int ch;
           int fcount = 0;
           int dcount = 0;
           int i;
           const char *dname = NULL;
          
           for (  i = 0; argv[i]; ++i ) {
           if (  lstat(  argv[i],   &st ) == 0 ) {
           if (  S_ISDIR(  st.st_mode ) ) {
           ++dcount;
           dname = argv[i]; /* only used if 1 dir */
           } else {
           ++fcount;
           }
           }
           }
           first = 0;
           while (  first != 'n' && first != 'N' && first != 'y' && first != 'Y' ) {
           if (  dcount && rflag ) {
           fprintf(  stderr,   "recursively remove" );
           if (  dcount == 1 )
           fprintf(  stderr,   " %s",   dname );
           else
           fprintf(  stderr,   " %d dirs",   dcount );
           if (  fcount == 1 )
           fprintf(  stderr,   " and 1 file" );
           else if (  fcount > 1 )
           fprintf(  stderr,   " and %d files",   fcount );
           } else if (  dcount + fcount > 3 ) {
           fprintf(  stderr,   "remove %d files",   dcount + fcount );
           } else {
           return(  1 );
           }
           fprintf(  stderr,   "? " );
           fflush(  stderr );
          
           first = ch = getchar(   );
           while (  ch != '\n' && ch != EOF )
           ch = getchar(   );
           if (  ch == EOF )
     663   break;
           }
           return (  first == 'y' || first == 'Y' );
          }
          
          #define ISDOT(  a ) (  (  a )[0] == '.' && (  !(  a )[1] || (  (  a )[1] == '.' && !(  a )[2] ) ) )
          void
          checkdot_rm(  rtems_shell_rm_globals* globals,   char **argv )
          {
           char *p,   **save,   **t;
           int complained;
          
           complained = 0;
           for (  t = argv; *t; ) {
           if (  (  p = strrchr(  *t,   '/' ) ) != NULL )
           ++p;
           else
           p = *t;
           if (  ISDOT(  p ) ) {
           if (  !complained++ )
           warnx(  "\".\" and \"..\" may not be removed" );
           eval = 1;
           for (  save = t; (  t[0] = t[1] ) != NULL; ++t )
           continue;
     687   t = save;
           } else
           ++t;
           }
          }
          
          void
          usage_rm(  rtems_shell_rm_globals* globals )
          {
          
           (  void )fprintf(  stderr,   "%s\n%s\n",  
           "usage: rm [-f | -i] [-dIPRrvW] file ...",  
           " unlink file" );
           exit(  1 );
          }
          
          rtems_shell_cmd_t rtems_shell_RM_Command = {
           "rm",   /* name */
           "[-f | -i] [-dIPRrvW] file ...",   /* usage */
           "files",   /* topic */
           rtems_shell_main_rm,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_rmdir.c

       1  /*
           * RMDIR Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_rmdir.c,  v 1.4 2008/02/27 21:52:16 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <string.h>
          #include <errno.h>
          #include <unistd.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      28  int rtems_shell_main_rmdir (  int argc,   char *argv[] )
          {
           char *dir;
           int n;
          
           n = 1;
           while (  n < argc ) {
           dir = argv[n++];
           if (  rmdir(  dir ) ) {
           fprintf(  stderr,  "%s: %s: %s\n",   argv[0],   dir,   strerror(  errno ) );
           return -1;
           }
           }
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_RMDIR_Command = {
           "rmdir",   /* name */
           "rmdir dir # remove directory",   /* usage */
           "files",   /* topic */
           rtems_shell_main_rmdir,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_route.c

       1  /*
           * ROUTE Command Implmentation
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_route.c,  v 1.2 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <string.h>
          #include <ctype.h>
          
          #include <netinet/in.h>
          #include <sys/types.h>
          #include <sys/socket.h>
          #include <arpa/inet.h>
          #include <net/route.h>
          
          #include <rtems.h>
          #include <rtems/rtems_bsdnet.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      30  int rtems_shell_main_route(  
           int argc,  
           char *argv[]
           )
          {
           int cmd;
           struct sockaddr_in dst;
           struct sockaddr_in gw;
           struct sockaddr_in netmask;
           int f_host;
           int f_gw = 0;
           int cur_idx;
           int flags;
           int rc;
          
           memset(  &dst,   0,   sizeof(  dst ) );
           memset(  &gw,   0,   sizeof(  gw ) );
           memset(  &netmask,   0,   sizeof(  netmask ) );
          
           dst.sin_len = sizeof(  dst );
           dst.sin_family = AF_INET;
           dst.sin_addr.s_addr = inet_addr(  "0.0.0.0" );
          
           gw.sin_len = sizeof(  gw );
           gw.sin_family = AF_INET;
           gw.sin_addr.s_addr = inet_addr(  "0.0.0.0" );
          
           netmask.sin_len = sizeof(  netmask );
           netmask.sin_family = AF_INET;
           netmask.sin_addr.s_addr = inet_addr(  "255.255.255.0" );
          
           if (  argc < 2 ) {
           rtems_bsdnet_show_inet_routes(   );
           return 0;
           }
          
           if (  strcmp(  argv[1],   "add" ) == 0 ) {
           cmd = RTM_ADD;
           } else if (  strcmp(  argv[1],   "del" ) == 0 ) {
           cmd = RTM_DELETE;
           } else {
           printf(  "invalid command: %s\n",   argv[1] );
           printf(  "\tit should be 'add' or 'del'\n" );
           return -1;
           }
          
           if (  argc < 3 ) {
           printf(  "not enough arguments\n" );
           return -1;
           }
          
           if (  strcmp(  argv[2],   "-host" ) == 0 ) {
           f_host = 1;
           } else if (  strcmp(  argv[2],   "-net" ) == 0 ) {
           f_host = 0;
           } else {
           printf(  "Invalid type: %s\n",   argv[1] );
           printf(  "\tit should be '-host' or '-net'\n" );
           return -1;
           }
          
           if (  argc < 4 ) {
           printf(  "not enough arguments\n" );
           return -1;
           }
          
           inet_pton(  AF_INET,   argv[3],   &dst.sin_addr );
          
           cur_idx = 4;
           while(  cur_idx < argc ) {
           if (  strcmp(  argv[cur_idx],   "gw" ) == 0 ) {
           if (  (  cur_idx +1 ) >= argc ) {
           printf(  "no gateway address\n" );
           return -1;
           }
           f_gw = 1;
           inet_pton(  AF_INET,   argv[cur_idx + 1],   &gw.sin_addr );
           cur_idx += 1;
           } else if(  strcmp(  argv[cur_idx],   "netmask" ) == 0 ) {
           if (  (  cur_idx +1 ) >= argc ) {
           printf(  "no netmask address\n" );
           return -1;
           }
           f_gw = 1;
           inet_pton(  AF_INET,   argv[cur_idx + 1],   &netmask.sin_addr );
           cur_idx += 1;
           } else {
           printf(  "Unknown argument\n" );
           return -1;
           }
           cur_idx += 1;
           }
          
           flags = RTF_STATIC;
           if (  f_gw != 0 ) {
           flags |= RTF_GATEWAY;
           }
           if (  f_host != 0 ) {
           flags |= RTF_HOST;
           }
          
           rc = rtems_bsdnet_rtrequest(  
           cmd,  
           (  struct sockaddr * )&dst,  
           (  struct sockaddr * )&gw,  
           (  struct sockaddr * )&netmask,  
           flags,  
           NULL
            );
           if (  rc < 0 ) {
           printf(  "Error adding route\n" );
           }
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_ROUTE_Command = {
           "route",   /* name */
           "TBD",   /* usage */
           "network",   /* topic */
           rtems_shell_main_route,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_rtc.c

       1  /**
           * @file
           *
           * Real time clock shell command.
           */
          
          /*
           * Copyright (  c ) 2009
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * D-82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <inttypes.h>
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          
          #include <rtems.h>
          #include <rtems/rtc.h>
          #include <rtems/error.h>
          #include <rtems/shell.h>
          
          #define RTEMS_RTC_SHELL_ERROR(   fmt,   ... ) \
           do { \
           printf(   "error: " fmt "\n",   ##__VA_ARGS__ ); \
           return -1; \
           } while (  0 )
          
          #define RTEMS_RTC_SHELL_ERROR_SC(   sc,   fmt,   ... ) \
           if (  (  sc ) != RTEMS_SUCCESSFUL ) { \
           printf(   "error: " fmt ": %s\n",   ##__VA_ARGS__,   rtems_status_text(   sc ) ); \
           return -1; \
           }
          
          static const char rtems_rtc_shell_usage [] =
      48   "real time clock read and set\n"
           "\n"
           "rtc\n"
           "\tprints the current time of day\n"
           "\n"
           "rtc YYYY-MM-DD [HH:MM:SS [TICKS]]\n"
           "\tsets the time of day and real time clock";
          
          static int rtems_rtc_shell_main(   int argc,   char **argv )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           rtems_time_of_day tod = {
           .year = 1988,  
           .month = 1,  
           .day = 1,  
           .hour = 0,  
           .minute = 0,  
           .second = 0,  
           .ticks = 0
           };
          
           if (  argc == 1 ) {
           sc = rtems_clock_get_tod(   &tod );
           RTEMS_RTC_SHELL_ERROR_SC(   sc,   "get time of day" );
          
           printf(  
           "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
           " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
           " %02" PRIu32 "\n",  
           tod.year,  
           tod.month,  
           tod.day,  
           tod.hour,  
           tod.minute,  
           tod.second,  
           tod.ticks
            );
           } else if (  argc > 1 && argc < 5 ) {
           int rv = 0;
           int fd = 0;
           ssize_t n = 0;
           uint32_t v [3];
          
           if (  argc > 1 ) {
           rv = sscanf(  
           argv [1],  
           "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32,  
           v,  
           v + 1,  
           v + 2
            );
          
           if (  rv == 3 ) {
           tod.year = v [0];
           tod.month = v [1];
           tod.day = v [2];
           } else {
           RTEMS_RTC_SHELL_ERROR(   "unexpected YYYY-MM-DD input: %s",   argv [1] );
           }
           }
          
           if (  argc > 2 ) {
           rv = sscanf(  
           argv [2],  
           "%04" PRIu32 ":%02" PRIu32 ":%02" PRIu32,  
           v,  
           v + 1,  
           v + 2
            );
          
           if (  rv == 3 ) {
           tod.hour = v [0];
           tod.minute = v [1];
           tod.second = v [2];
           } else {
           RTEMS_RTC_SHELL_ERROR(   "unexpected HH:MM:SS input: %s",   argv [2] );
           }
           }
          
           if (  argc > 3 ) {
           rv = sscanf(   argv [3],   "%" PRIu32,   v );
          
           if (  rv == 1 ) {
           tod.ticks = v [0];
           } else {
           RTEMS_RTC_SHELL_ERROR(   "unexpected TICKS input: %s",   argv [3] );
           }
           }
          
           sc = rtems_clock_set(   &tod );
           RTEMS_RTC_SHELL_ERROR_SC(   sc,   "set time of day" );
          
           fd = open(   RTC_DEVICE_NAME,   O_WRONLY );
           if (  fd < 0 ) {
           perror(   "error: open " RTC_DEVICE_NAME );
           return -1;
           }
          
           n = write(   fd,   &tod,   sizeof(   tod ) );
           if (  n != (  ssize_t ) sizeof(   tod ) ) {
           perror(   "error: write to " RTC_DEVICE_NAME );
           close(   fd );
           return -1;
           }
          
           rv = close(   fd );
           if (  rv != 0 ) {
           perror(   "error: close " RTC_DEVICE_NAME );
           return -1;
           }
           } else {
           puts(   rtems_rtc_shell_usage );
           return -1;
           }
          
           return 0;
          }
          
          struct rtems_shell_cmd_tt rtems_shell_RTC_Command = {
           .name = "rtc",  
           .usage = rtems_rtc_shell_usage,  
           .topic = "misc",  
           .command = rtems_rtc_shell_main,  
           .alias = NULL,  
           .next = NULL
          };

libmisc/shell/main_setenv.c

       1  /*
           * Set an environment vairable.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <stdlib.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      19  int rtems_shell_main_setenv(  int argc,   char *argv[] )
          {
           char* env = NULL;
           char* string = NULL;
           int len = 0;
           int arg;
           char* p;
          
           if (  argc <= 2 ) {
           printf(  "error: no variable or string\n" );
           return 1;
           }
          
           env = argv[1];
          
           for (  arg = 2; arg < argc; arg++ )
           len += strlen(  argv[arg] );
          
           len += argc - 2 - 1;
          
           string = malloc(  len + 1 );
          
           if (  !string ) {
           printf(  "error: no memory\n" );
           return 1;
           }
          
           for (  arg = 2,   p = string; arg < argc; arg++ ) {
           strcpy(  p,   argv[arg] );
           p += strlen(  argv[arg] );
           if (  arg < (  argc - 1 ) ) {
           *p = ' ';
           p++;
           }
           }
          
           if (  setenv(  env,   string,   1 ) < 0 ) {
           printf(   "error: %s\n",   strerror(  errno )  );
           free(   string  );
           return 1;
           }
          
           free(   string  );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_SETENV_Command = {
           "setenv",   /* name */
           "setenv [var] [string]",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_setenv,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_sleep.c

       1  /*
           * Sleep Shell Command Implmentation
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: main_sleep.c,  v 1.3 2009/07/23 14:32:34 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <time.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include "internal.h"
          
      26  int rtems_shell_main_sleep(  
           int argc,  
           char *argv[]
           )
          {
           struct timespec delay;
           unsigned long tmp;
          
           if (  (  argc != 2 ) && (  argc != 3 ) ) {
           fprintf(   stderr,   "%s: Usage seconds [nanoseconds]\n",   argv[0]  );
           return -1;
           }
          
           /*
           * Convert the seconds argument to a number
           */
           if (   rtems_string_to_unsigned_long(  argv[1],   &tmp,   NULL,   0 )  ) {
           printf(   "Seconds argument (  %s ) is not a number\n",   argv[1]  );
           return -1;
           }
           delay.tv_sec = (  time_t ) tmp;
          
           /*
           * If the user specified a nanoseconds argument,   convert it
           */
           delay.tv_nsec = 0;
           if (  argc == 3 ) {
           if (   rtems_string_to_unsigned_long(  argv[2],   &tmp,   NULL,   0 )  ) {
           printf(   "Seconds argument (  %s ) is not a number\n",   argv[1]  );
           return -1;
           }
           delay.tv_nsec = tmp;
           }
          
           /*
           * Now sleep as requested.
           */
           nanosleep(   &delay,   NULL  );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_SLEEP_Command = {
           "sleep",   /* name */
           "sleep seconds [nanoseconds]",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_sleep,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_stackuse.c

       1  /*
           * stackuse Command Implementation
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: main_stackuse.c,  v 1.6 2009/01/02 13:01:21 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          
          #include <rtems.h>
          #include <rtems/stackchk.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      25  int rtems_shell_main_stackuse(  
           int argc __attribute__(  (  unused ) ),  
           char *argv[] __attribute__(  (  unused ) )
           )
          {
           rtems_stack_checker_report_usage_with_plugin(  
           stdout,  
           (  rtems_printk_plugin_t )fprintf
            );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_STACKUSE_Command = {
           "stackuse",   /* name */
           "print per thread stack usage",   /* usage */
           "rtems",   /* topic */
           rtems_shell_main_stackuse,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_time.c

       1  /*
           * Time Shell Command Implmentation
           *
           * Author: Chris Johns <chrisj@rtems.org>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_time.c,  v 1.2 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          #include <sys/types.h>
          #include <sys/stat.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      28  int rtems_shell_main_time(  
           int argc,  
           char *argv[]
           )
          {
           rtems_shell_cmd_t* shell_cmd;
           int errorlevel = 0;
           struct timespec start;
           struct timespec end;
           struct timespec period;
           rtems_status_code sc;
          
           argc--;
          
           sc = rtems_clock_get_uptime(  &start );
           if (  sc != RTEMS_SUCCESSFUL )
           printf(  "error: cannot read time\n" );
          
           if (  argc ) {
           shell_cmd = rtems_shell_lookup_cmd(  argv[1] );
           if (   argv[1] == NULL  ) {
           errorlevel = -1;
           } else if (   shell_cmd == NULL  ) {
           errorlevel = rtems_shell_script_file(  argc,   &argv[1] );
           } else {
           errorlevel = shell_cmd->command(  argc,   &argv[1] );
           }
           }
          
           sc = rtems_clock_get_uptime(  &end );
           if (  sc != RTEMS_SUCCESSFUL )
           printf(  "error: cannot read time\n" );
          
           period.tv_sec = end.tv_sec - start.tv_sec;
           period.tv_nsec = end.tv_nsec - start.tv_nsec;
           if (  period.tv_nsec < 0 )
           {
           --period.tv_sec;
           period.tv_nsec += 1000000000UL;
           }
          
           printf(  "time: %li:%02li:%02li.%03li\n",  
           period.tv_sec / 3600,  
           period.tv_sec / 60,   period.tv_sec % 60,  
           period.tv_nsec / 1000000 );
          
           return errorlevel;
          }
          
          rtems_shell_cmd_t rtems_shell_TIME_Command = {
           "time",   /* name */
           "time command [arguments...]",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_time,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_tty.c

       1  /*
           * TTY Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_tty.c,  v 1.6 2009/01/02 13:01:21 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      28  int rtems_shell_main_tty(  
           int argc __attribute__(  (  unused ) ),  
           char *argv[] __attribute__(  (  unused ) )
           )
          {
           printf(  "%s\n",   ttyname(  fileno(  stdin ) ) );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_TTY_Command = {
           "tty",   /* name */
           "show ttyname",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_tty,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_umask.c

       1  /*
           * UMASK Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_umask.c,  v 1.7 2009/07/23 14:32:34 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          #include <sys/types.h>
          #include <sys/stat.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include "internal.h"
          
      31  int rtems_shell_main_umask(  
           int argc,  
           char *argv[]
           )
          {
           unsigned long tmp;
           mode_t msk = umask(  0 );
          
           if (  argc == 2 ) {
           if (   rtems_string_to_unsigned_long(  argv[1],   &tmp,   NULL,   0 )  ) {
           printf(   "Mask argument (  %s ) is not a number\n",   argv[1]  );
           return -1;
           }
           msk = (  mode_t ) tmp;
          
           }
           umask(  msk );
          
           msk = umask(  0 );
           printf(  "0%o\n",   (  unsigned int ) msk );
           umask(  msk );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_UMASK_Command = {
           "umask",   /* name */
           "umask [new_umask]",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_umask,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_unmount.c

       1  /*
           * Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_unmount.c,  v 1.4 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          #include <rtems/fsmount.h>
          #include "internal.h"
          
      30  int rtems_shell_main_unmount(  
           int argc,  
           char *argv[]
           )
          {
           char* mount_point = NULL;
           int arg;
          
           for (  arg = 1; arg < argc; arg++ ) {
           if (  !mount_point )
           mount_point = argv[arg];
           else {
           fprintf (  stderr,   "error: only one mount path require: %s\n",   argv[arg] );
           return 1;
           }
           }
          
           if (  !mount_point ) {
           fprintf (  stderr,   "error: no mount point\n" );
           return 1;
           }
          
           /*
           * Unmount the disk.
           */
          
           if (  unmount (  mount_point ) < 0 ) {
           fprintf (  stderr,   "error: unmount failed: %s: %s\n",  
           mount_point,   strerror (  errno ) );
           return 1;
           }
          
           printf (  "unmounted %s\n",   mount_point );
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_UNMOUNT_Command = {
           "unmount",   /* name */
           "unmount path # unmount disk",   /* usage */
           "files",   /* topic */
           rtems_shell_main_unmount,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_unsetenv.c

       1  /*
           * Unset an environment vairable.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <stdlib.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      19  int rtems_shell_main_unsetenv(  int argc,   char *argv[] )
          {
           if (  argc != 2 )
           {
           printf (  "error: only argument is the variable name\n" );
           return 1;
           }
          
           if (  unsetenv (  argv[1] ) < 0 )
           {
           printf (  "error: %s\n",   strerror (  errno ) );
           return 1;
           }
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_UNSETENV_Command = {
           "unsetenv",   /* name */
           "unsetenv [var]",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_unsetenv,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_whoami.c

       1  /*
           * WHOAMI Shell Command Implmentation
           *
           * Author: Fernando RUIZ CASAS
           * Work: fernando.ruiz@ctv.es
           * Home: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: main_whoami.c,  v 1.6 2009/01/02 13:01:21 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          #include <pwd.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      29  int rtems_shell_main_whoami(  
           int argc __attribute__(  (  unused ) ),  
           char *argv[] __attribute__(  (  unused ) )
           )
          {
           struct passwd *pwd;
          
           pwd = getpwuid(  geteuid(   ) );
           printf(   "%s\n",   (  pwd ) ? pwd->pw_name : "nobody" );
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_WHOAMI_Command = {
           "whoami",   /* name */
           "show current user",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_whoami,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/main_wkspaceinfo.c

       1  /*
           * MALLOC_INFO Shell Command Implmentation
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: main_wkspaceinfo.c,  v 1.7 2009/01/02 13:01:21 ralf Exp $
           */
          
          #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <rtems.h>
          #include <rtems/malloc.h>
          #include <rtems/shell.h>
          #include <rtems/score/protectedheap.h>
          #include "internal.h"
          
          extern bool rtems_unified_work_area;
          
      29  void rtems_shell_print_unified_work_area_message(  void )
          {
           printf(   "\nC Program Heap and RTEMS Workspace are %s.\n",  
           (  (  rtems_unified_work_area ) ? "the same" : "separate" )
            );
          }
          
      36  int rtems_shell_main_wkspace_info(  
           int argc __attribute__(  (  unused ) ),  
           char *argv[] __attribute__(  (  unused ) )
           )
          {
           Heap_Information_block info;
          
           rtems_shell_print_unified_work_area_message(   );
          
           _Protected_heap_Get_information(   &_Workspace_Area,   &info  );
           rtems_shell_print_heap_info(   "free",   &info.Free  );
           rtems_shell_print_heap_info(   "used",   &info.Used  );
          
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_WKSPACE_INFO_Command = {
           "wkspace",   /* name */
           "Report on RTEMS Executive Workspace",   /* usage */
           "rtems",   /* topic */
           rtems_shell_main_wkspace_info,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };

libmisc/shell/mknod-pack_dev.c

          /* $NetBSD: pack_dev.c,  v 1.10 2009/02/13 01:37:23 lukem Exp $ */
          
          /*-
           * Copyright (  c ) 1998,   2001 The NetBSD Foundation,   Inc.
           * All rights reserved.
           *
           * This code is derived from software contributed to The NetBSD Foundation
           * by Charles M. Hannum.
           *
           * 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 NETBSD FOUNDATION,   INC. 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 FOUNDATION 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_NBTOOL_CONFIG_H
          #include "nbtool_config.h"
          #endif
          
          #if 0
          #include <sys/cdefs.h>
          #if !defined(  lint )
      43  __RCSID(  "$NetBSD: pack_dev.c,  v 1.10 2009/02/13 01:37:23 lukem Exp $" );
          #endif /* not lint */
          
          #include <sys/types.h>
          #include <sys/stat.h>
          
          #include <limits.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          
          #include "pack_dev.h"
          #endif
          
          static pack_t pack_netbsd;
          static pack_t pack_freebsd;
          static pack_t pack_8_8;
          static pack_t pack_12_20;
          static pack_t pack_14_18;
          static pack_t pack_8_24;
          static pack_t pack_bsdos;
      65  static int compare_format(  const void *,   const void * );
          
          static const char iMajorError[] = "invalid major number";
          static const char iMinorError[] = "invalid minor number";
          static const char tooManyFields[] = "too many fields for format";
          
          #define makedev(  x,  y ) rtems_filesystem_make_dev_t(  x,  y )
          #define major(  d ) rtems_filesystem_dev_major_t(  d )
          #define minor(  d ) rtems_filesystem_dev_minor_t(  d )
          
           /* exported */
          portdev_t
      77  pack_native(  int n,   u_long numbers[],   const char **error )
          {
           portdev_t dev = 0;
          
           if (  n == 2 ) {
           dev = makedev(  numbers[0],   numbers[1] );
           if (  (  u_long )major(  dev ) != numbers[0] )
           *error = iMajorError;
           else if (  (  u_long )minor(  dev ) != numbers[1] )
           *error = iMinorError;
           } else
           *error = tooManyFields;
           return (  dev );
          }
          
          
          static portdev_t
      94  pack_netbsd(  int n,   u_long numbers[],   const char **error )
          {
           portdev_t dev = 0;
          
           if (  n == 2 ) {
           dev = makedev_netbsd(  numbers[0],   numbers[1] );
           if (  (  u_long )major_netbsd(  dev ) != numbers[0] )
           *error = iMajorError;
           else if (  (  u_long )minor_netbsd(  dev ) != numbers[1] )
           *error = iMinorError;
           } else
           *error = tooManyFields;
           return (  dev );
          }
          
          
          #define major_freebsd(  x ) (  (  int32_t )(  (  (  x ) & 0x0000ff00 ) >> 8 ) )
          #define minor_freebsd(  x ) (  (  int32_t )(  (  (  x ) & 0xffff00ff ) >> 0 ) )
          #define makedev_freebsd(  x,  y ) (  (  portdev_t )(  (  (  (  x ) << 8 ) & 0x0000ff00 ) | \
           (  (  (  y ) << 0 ) & 0xffff00ff ) ) )
          
     115  static portdev_t
          pack_freebsd(  int n,   u_long numbers[],   const char **error )
          {
           portdev_t dev = 0;
          
           if (  n == 2 ) {
           dev = makedev_freebsd(  numbers[0],   numbers[1] );
           if (  (  u_long )major_freebsd(  dev ) != numbers[0] )
           *error = iMajorError;
           if (  (  u_long )minor_freebsd(  dev ) != numbers[1] )
           *error = iMinorError;
           } else
           *error = tooManyFields;
           return (  dev );
          }
          
          
          #define major_8_8(  x ) (  (  int32_t )(  (  (  x ) & 0x0000ff00 ) >> 8 ) )
          #define minor_8_8(  x ) (  (  int32_t )(  (  (  x ) & 0x000000ff ) >> 0 ) )
          #define makedev_8_8(  x,  y ) (  (  portdev_t )(  (  (  (  x ) << 8 ) & 0x0000ff00 ) | \
           (  (  (  y ) << 0 ) & 0x000000ff ) ) )
     136  
          static portdev_t
          pack_8_8(  int n,   u_long numbers[],   const char **error )
          {
           portdev_t dev = 0;
          
           if (  n == 2 ) {
           dev = makedev_8_8(  numbers[0],   numbers[1] );
           if (  (  u_long )major_8_8(  dev ) != numbers[0] )
           *error = iMajorError;
           if (  (  u_long )minor_8_8(  dev ) != numbers[1] )
           *error = iMinorError;
           } else
           *error = tooManyFields;
           return (  dev );
          }
          
          
          #define major_12_20(  x ) (  (  int32_t )(  (  (  x ) & 0xfff00000 ) >> 20 ) )
          #define minor_12_20(  x ) (  (  int32_t )(  (  (  x ) & 0x000fffff ) >> 0 ) )
          #define makedev_12_20(  x,  y ) (  (  portdev_t )(  (  (  (  x ) << 20 ) & 0xfff00000 ) | \
     157   (  (  (  y ) << 0 ) & 0x000fffff ) ) )
          
          static portdev_t
          pack_12_20(  int n,   u_long numbers[],   const char **error )
          {
           portdev_t dev = 0;
          
           if (  n == 2 ) {
           dev = makedev_12_20(  numbers[0],   numbers[1] );
           if (  (  u_long )major_12_20(  dev ) != numbers[0] )
           *error = iMajorError;
           if (  (  u_long )minor_12_20(  dev ) != numbers[1] )
           *error = iMinorError;
           } else
           *error = tooManyFields;
           return (  dev );
          }
          
          
          #define major_14_18(  x ) (  (  int32_t )(  (  (  x ) & 0xfffc0000 ) >> 18 ) )
          #define minor_14_18(  x ) (  (  int32_t )(  (  (  x ) & 0x0003ffff ) >> 0 ) )
     178  #define makedev_14_18(  x,  y ) (  (  portdev_t )(  (  (  (  x ) << 18 ) & 0xfffc0000 ) | \
           (  (  (  y ) << 0 ) & 0x0003ffff ) ) )
          
          static portdev_t
          pack_14_18(  int n,   u_long numbers[],   const char **error )
          {
           portdev_t dev = 0;
          
           if (  n == 2 ) {
           dev = makedev_14_18(  numbers[0],   numbers[1] );
           if (  (  u_long )major_14_18(  dev ) != numbers[0] )
           *error = iMajorError;
           if (  (  u_long )minor_14_18(  dev ) != numbers[1] )
           *error = iMinorError;
           } else
           *error = tooManyFields;
           return (  dev );
          }
          
          
          #define major_8_24(  x ) (  (  int32_t )(  (  (  x ) & 0xff000000 ) >> 24 ) )
     199  #define minor_8_24(  x ) (  (  int32_t )(  (  (  x ) & 0x00ffffff ) >> 0 ) )
          #define makedev_8_24(  x,  y ) (  (  portdev_t )(  (  (  (  x ) << 24 ) & 0xff000000 ) | \
           (  (  (  y ) << 0 ) & 0x00ffffff ) ) )
          
          static portdev_t
          pack_8_24(  int n,   u_long numbers[],   const char **error )
          {
           portdev_t dev = 0;
          
           if (  n == 2 ) {
           dev = makedev_8_24(  numbers[0],   numbers[1] );
           if (  (  u_long )major_8_24(  dev ) != numbers[0] )
           *error = iMajorError;
           if (  (  u_long )minor_8_24(  dev ) != numbers[1] )
           *error = iMinorError;
           } else
           *error = tooManyFields;
           return (  dev );
          }
          
          
          #define major_12_12_8(  x ) (  (  int32_t )(  (  (  x ) & 0xfff00000 ) >> 20 ) )
     221  #define unit_12_12_8(  x ) (  (  int32_t )(  (  (  x ) & 0x000fff00 ) >> 8 ) )
          #define subunit_12_12_8(  x ) (  (  int32_t )(  (  (  x ) & 0x000000ff ) >> 0 ) )
          #define makedev_12_12_8(  x,  y,  z ) (  (  portdev_t )(  (  (  (  x ) << 20 ) & 0xfff00000 ) | \
           (  (  (  y ) << 8 ) & 0x000fff00 ) | \
           (  (  (  z ) << 0 ) & 0x000000ff ) ) )
          
          static portdev_t
          pack_bsdos(  int n,   u_long numbers[],   const char **error )
          {
           portdev_t dev = 0;
          
           if (  n == 2 ) {
           dev = makedev_12_20(  numbers[0],   numbers[1] );
           if (  (  u_long )major_12_20(  dev ) != numbers[0] )
           *error = iMajorError;
           if (  (  u_long )minor_12_20(  dev ) != numbers[1] )
           *error = iMinorError;
           } else if (  n == 3 ) {
           dev = makedev_12_12_8(  numbers[0],   numbers[1],   numbers[2] );
           if (  (  u_long )major_12_12_8(  dev ) != numbers[0] )
           *error = iMajorError;
           if (  (  u_long )unit_12_12_8(  dev ) != numbers[1] )
           *error = "invalid unit number";
           if (  (  u_long )subunit_12_12_8(  dev ) != numbers[2] )
           *error = "invalid subunit number";
           } else
           *error = tooManyFields;
           return (  dev );
          }
          
     251  
           /* list of formats and pack functions */
           /* this list must be sorted lexically */
          struct format {
           const char *name;
           pack_t *pack;
          } formats[] = {
           {"386bsd",   pack_8_8},  
           {"4bsd",   pack_8_8},  
           {"bsdos",   pack_bsdos},  
           {"freebsd",   pack_freebsd},  
           {"hpux",   pack_8_24},  
           {"isc",   pack_8_8},  
           {"linux",   pack_8_8},  
           {"native",   pack_native},  
           {"netbsd",   pack_netbsd},  
           {"osf1",   pack_12_20},  
           {"sco",   pack_8_8},  
           {"solaris",   pack_14_18},  
           {"sunos",   pack_8_8},  
           {"svr3",   pack_8_8},  
           {"svr4",   pack_14_18},  
           {"ultrix",   pack_8_8},  
          };
          
          static int
          compare_format(  const void *key,   const void *element )
          {
           const char *name;
           const struct format *format;
          
           name = key;
           format = element;
          
           return (  strcmp(  name,   format->name ) );
          }
          
          
          pack_t *
          pack_find(  const char *name )
          {
           struct format *format;
          
           format = bsearch(  name,   formats,  
           sizeof(  formats )/sizeof(  formats[0] ),  
           sizeof(  formats[0] ),   compare_format );
           if (  format == 0 )
           return (  NULL );
           return (  format->pack );
          }

libmisc/shell/print-ls.c

       1  /* $NetBSD: print.c,  v 1.40 2004/11/17 17:00:00 mycroft Exp $ */
          
          /*
           * Copyright (  c ) 1989,   1993,   1994
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Michael Fischbein.
           *
           * 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. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if 0
          #include <sys/cdefs.h>
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )print.c 8.5 (  Berkeley ) 7/28/94";
          #else
      45  __RCSID(  "$NetBSD: print.c,  v 1.40 2004/11/17 17:00:00 mycroft Exp $" );
          #endif
          #endif /* not lint */
          #endif
          
          #include <inttypes.h>
          
          #include <rtems.h>
          #include <rtems/libio.h>
          
          #include <sys/param.h>
          #include <sys/stat.h>
          
          #include <err.h>
          #include <errno.h>
          #include <fts.h>
          #include <grp.h>
          #include <pwd.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <time.h>
          //#include <tzfile.h>
          #include <unistd.h>
          //#include <util.h>
          
          #include "extern-ls.h"
          
          #define DAYSPERNYEAR (  (  time_t )365 )
          #define SECSPERDAY (  (  time_t )60 * (  time_t )60 * (  time_t )24 )
          
          
          #if RTEMS_REMOVED
          extern int termwidth;
          #endif
          
      81  static int printaname(  rtems_shell_ls_globals* globals,   FTSENT *,   int,   int );
      82  static void printlink(  rtems_shell_ls_globals* globals,   FTSENT * );
      83  static void printtime(  rtems_shell_ls_globals* globals,   time_t );
      84  static int printtype(  u_int );
          
          #if RTEMS_REMOVED
          static time_t now;
          #endif
          
          #define IS_NOPRINT(  p ) (  (  p )->fts_number == NO_PRINT )
          
          void
      93  printscol(  rtems_shell_ls_globals* globals,   DISPLAY *dp )
          {
           FTSENT *p;
          
           for (  p = dp->list; p; p = p->fts_link ) {
           if (  IS_NOPRINT(  p ) )
           continue;
           (  void )printaname(  globals,   p,   dp->s_inode,   dp->s_block );
           (  void )putchar(  '\n' );
           }
          }
          
          void
     106  printlong(  rtems_shell_ls_globals* globals,   DISPLAY *dp )
          {
           struct stat *sp;
           FTSENT *p;
           NAMES *np;
           char buf[20]; //,   szbuf[5];
          
           now = time(  NULL );
          
           if (  dp->list->fts_level != FTS_ROOTLEVEL && (  f_longform || f_size ) ) {
          #if RTEMS_REMOVED
           if (  f_humanize ) {
           if (  (  humanize_number(  szbuf,   sizeof(  szbuf ),   dp->stotal,  
           "",   HN_AUTOSCALE,  
           (  HN_DECIMAL | HN_B | HN_NOSPACE ) ) ) == -1 )
           err(  exit_jump,   1,   "humanize_number" );
           (  void )printf(  "total %s\n",   szbuf );
           } else {
          #endif
           (  void )printf(  "total %llu\n",  
           (  long long )(  howmany(  dp->btotal,   blocksize ) ) );
          #if RTEMS_REMOVED
           }
          #endif
           }
          
           for (  p = dp->list; p; p = p->fts_link ) {
           if (  IS_NOPRINT(  p ) )
           continue;
           sp = p->fts_statp;
           if (  f_inode )
           (  void )printf(  "%*lu ",   dp->s_inode,   sp->st_ino );
           if (  f_size && !f_humanize ) {
           (  void )printf(  "%*llu ",   dp->s_block,  
           (  long long )howmany(  sp->st_blocks,   blocksize ) );
           }
           (  void )strmode(  sp->st_mode,   buf );
           np = p->fts_pointer;
           (  void )printf(  "%s %*lu ",   buf,   dp->s_nlink,  
           (  unsigned long )sp->st_nlink );
           if (  !f_grouponly )
           (  void )printf(  "%-*s ",   dp->s_user,   np->user );
           (  void )printf(  "%-*s ",   dp->s_group,   np->group );
           if (  f_flags )
           (  void )printf(  "%-*s ",   dp->s_flags,   np->flags );
           if (  S_ISCHR(  sp->st_mode ) || S_ISBLK(  sp->st_mode ) )
           (  void )printf(  "%*"PRIu32",   %*"PRIu32" ",  
           dp->s_major,   major(  sp->st_rdev ),   dp->s_minor,  
           minor(  sp->st_rdev ) );
           else
          #if RTEMS_REMOVED
           if (  f_humanize ) {
           if (  (  humanize_number(  szbuf,   sizeof(  szbuf ),  
           sp->st_size,   "",   HN_AUTOSCALE,  
           (  HN_DECIMAL | HN_B | HN_NOSPACE ) ) ) == -1 )
           err(  1,   "humanize_number" );
           (  void )printf(  "%*s ",   dp->s_size,   szbuf );
           } else {
          #endif
           {
           unsigned long long size;
           if (  sp->st_size < 0 )
           size = sp->st_size * -1;
           else
           size = sp->st_size;
           (  void )printf(  "%*llu ",   dp->s_size,   size );
           }
           if (  f_accesstime )
           printtime(  globals,   sp->st_atime );
           else if (  f_statustime )
           printtime(  globals,   sp->st_ctime );
           else
           printtime(  globals,   sp->st_mtime );
           if (  f_octal || f_octal_escape )
           (  void )safe_print(  globals,   p->fts_name );
           else if (  f_nonprint )
           (  void )printescaped(  globals,   p->fts_name );
           else
           (  void )printf(  "%s",   p->fts_name );
          
           if (  f_type || (  f_typedir && S_ISDIR(  sp->st_mode ) ) )
           (  void )printtype(  sp->st_mode );
           if (  S_ISLNK(  sp->st_mode ) )
           printlink(  globals,   p );
           (  void )putchar(  '\n' );
           }
          }
          
          void
          printcol(  rtems_shell_ls_globals* globals,   DISPLAY *dp )
          {
           static FTSENT **array;
           static int lastentries = -1;
           FTSENT *p;
           int base,   chcnt,   col,   colwidth,   num;
           int numcols,   numrows,   row;
           //char szbuf[5];
          
           colwidth = dp->maxlen;
           if (  f_inode )
           colwidth += dp->s_inode + 1;
           if (  f_size ) {
           if (  f_humanize )
           colwidth += dp->s_size + 1;
           else
           colwidth += dp->s_block + 1;
           }
           if (  f_type || f_typedir )
           colwidth += 1;
          
           colwidth += 1;
          
           if (  termwidth < 2 * colwidth ) {
           printscol(  globals,   dp );
           return;
           }
          
           /*
           * Have to do random access in the linked list -- build a table
           * of pointers.
           */
           if (  dp->entries > lastentries ) {
           lastentries = dp->entries;
           if (  (  array =
           realloc(  array,   dp->entries * sizeof(  FTSENT * ) ) ) == NULL ) {
           warn(  NULL );
           printscol(  globals,   dp );
           }
           }
           for (  p = dp->list,   num = 0; p; p = p->fts_link )
           if (  p->fts_number != NO_PRINT )
           array[num++] = p;
          
           numcols = termwidth / colwidth;
           colwidth = termwidth / numcols; /* spread out if possible */
           numrows = num / numcols;
           if (  num % numcols )
           ++numrows;
          
           if (  dp->list->fts_level != FTS_ROOTLEVEL && (  f_longform || f_size ) ) {
          #if RTEMS_REMOVED
           if (  f_humanize ) {
           if (  (  humanize_number(  szbuf,   sizeof(  szbuf ),   dp->stotal,  
           "",   HN_AUTOSCALE,  
           (  HN_DECIMAL | HN_B | HN_NOSPACE ) ) ) == -1 )
           err(  1,   "humanize_number" );
           (  void )printf(  "total %s\n",   szbuf );
           } else {
          #endif
           (  void )printf(  "total %llu\n",  
           (  long long )(  howmany(  dp->btotal,   blocksize ) ) );
          #if RTEMS_REMOVED
           }
          #endif
           }
           for (  row = 0; row < numrows; ++row ) {
           for (  base = row,   chcnt = col = 0; col < numcols; ++col ) {
           chcnt = printaname(  globals,   array[base],   dp->s_inode,  
           f_humanize && 0 ? dp->s_size : dp->s_block );
           if (  (  base += numrows ) >= num )
           break;
           while (  chcnt++ < colwidth )
           (  void )putchar(  ' ' );
           }
           (  void )putchar(  '\n' );
           }
          }
          
          void
          printacol(  rtems_shell_ls_globals* globals,   DISPLAY *dp )
          {
           FTSENT *p;
           int chcnt,   col,   colwidth;
           int numcols;
           //char szbuf[5];
          
           colwidth = dp->maxlen;
           if (  f_inode )
           colwidth += dp->s_inode + 1;
           if (  f_size ) {
           if (  f_humanize )
           colwidth += dp->s_size + 1;
           else
           colwidth += dp->s_block + 1;
           }
           if (  f_type || f_typedir )
           colwidth += 1;
          
           colwidth += 1;
          
           if (  termwidth < 2 * colwidth ) {
           printscol(  globals,   dp );
           return;
           }
          
           numcols = termwidth / colwidth;
           colwidth = termwidth / numcols; /* spread out if possible */
          
           if (  dp->list->fts_level != FTS_ROOTLEVEL && (  f_longform || f_size ) ) {
          #if RTEMS_REMOVED
           if (  f_humanize ) {
           if (  (  humanize_number(  szbuf,   sizeof(  szbuf ),   dp->stotal,  
           "",   HN_AUTOSCALE,  
           (  HN_DECIMAL | HN_B | HN_NOSPACE ) ) ) == -1 )
           err(  1,   "humanize_number" );
           (  void )printf(  "total %s\n",   szbuf );
           } else {
          #endif
           (  void )printf(  "total %llu\n",  
           (  long long )(  howmany(  dp->btotal,   blocksize ) ) );
          #if RTEMS_REMOVED
           }
          #endif
           }
           chcnt = col = 0;
           for (  p = dp->list; p; p = p->fts_link ) {
           if (  IS_NOPRINT(  p ) )
           continue;
           if (  col >= numcols ) {
           chcnt = col = 0;
           (  void )putchar(  '\n' );
           }
           chcnt = printaname(  globals,   p,   dp->s_inode,  
           f_humanize && 0 ? dp->s_size : dp->s_block );
           while (  chcnt++ < colwidth )
           (  void )putchar(  ' ' );
           col++;
           }
           (  void )putchar(  '\n' );
          }
          
          void
          printstream(  rtems_shell_ls_globals* globals,   DISPLAY *dp )
          {
           FTSENT *p;
           int col;
           int extwidth;
          
           extwidth = 0;
           if (  f_inode )
           extwidth += dp->s_inode + 1;
           if (  f_size ) {
           if (  f_humanize )
           extwidth += dp->s_size + 1;
           else
           extwidth += dp->s_block + 1;
           }
           if (  f_type )
           extwidth += 1;
          
           for (  col = 0,   p = dp->list; p != NULL; p = p->fts_link ) {
           if (  IS_NOPRINT(  p ) )
           continue;
           if (  col > 0 ) {
           (  void )putchar(  ',  ' ),   col++;
           if (  col + 1 + extwidth + p->fts_namelen >= termwidth )
           (  void )putchar(  '\n' ),   col = 0;
           else
           (  void )putchar(  ' ' ),   col++;
           }
           col += printaname(  globals,   p,   dp->s_inode,  
           f_humanize && 0 ? dp->s_size : dp->s_block );
           }
           (  void )putchar(  '\n' );
          }
          
          /*
           * print [inode] [size] name
           * return # of characters printed,   no trailing characters.
           */
          static int
          printaname(  rtems_shell_ls_globals* globals,  
           FTSENT *p,   int inodefield,   int sizefield )
          {
           struct stat *sp;
           int chcnt;
           //char szbuf[5];
          
           sp = p->fts_statp;
           chcnt = 0;
           if (  f_inode )
           chcnt += printf(  "%*lu ",   inodefield,   sp->st_ino );
           if (  f_size ) {
          #if RTEMS_REMOVED
           if (  f_humanize ) {
           if (  (  humanize_number(  szbuf,   sizeof(  szbuf ),   sp->st_size,  
           "",   HN_AUTOSCALE,  
           (  HN_DECIMAL | HN_B | HN_NOSPACE ) ) ) == -1 )
           err(  1,   "humanize_number" );
           chcnt += printf(  "%*s ",   sizefield,   szbuf );
           } else {
          #endif
           chcnt += printf(  "%*llu ",   sizefield,  
           (  long long )howmany(  sp->st_blocks,   blocksize ) );
          #if RTEMS_REMOVED
           }
          #endif
           }
           if (  f_octal || f_octal_escape )
           chcnt += safe_print(  globals,   p->fts_name );
           else if (  f_nonprint )
           chcnt += printescaped(  globals,   p->fts_name );
           else
           chcnt += printf(  "%s",   p->fts_name );
           if (  f_type || (  f_typedir && S_ISDIR(  sp->st_mode ) ) )
           chcnt += printtype(  sp->st_mode );
           return (  chcnt );
          }
          
          static void
          printtime(  rtems_shell_ls_globals* globals,   time_t ftime )
          {
           int i;
           char *longstring;
          
           longstring = ctime(  &ftime );
           for (  i = 4; i < 11; ++i )
           (  void )putchar(  longstring[i] );
          
          #define SIXMONTHS (  (  DAYSPERNYEAR / 2 ) * SECSPERDAY )
           if (  f_sectime )
           for (  i = 11; i < 24; i++ )
           (  void )putchar(  longstring[i] );
           else if (  ftime + SIXMONTHS > now && ftime - SIXMONTHS < now )
           for (  i = 11; i < 16; ++i )
           (  void )putchar(  longstring[i] );
           else {
           (  void )putchar(  ' ' );
           for (  i = 20; i < 24; ++i )
           (  void )putchar(  longstring[i] );
           }
           (  void )putchar(  ' ' );
          }
          
          static int
          printtype(  u_int mode )
          {
           switch (  mode & S_IFMT ) {
           case S_IFDIR:
           (  void )putchar(  '/' );
           return (  1 );
           case S_IFIFO:
           (  void )putchar(  '|' );
           return (  1 );
           case S_IFLNK:
           (  void )putchar(  '@' );
           return (  1 );
           case S_IFSOCK:
           (  void )putchar(  '=' );
           return (  1 );
          #if RTEMS_REMOVED
           case S_IFWHT:
           (  void )putchar(  '%' );
           return (  1 );
          #endif
           }
           if (  mode & (  S_IXUSR | S_IXGRP | S_IXOTH ) ) {
           (  void )putchar(  '*' );
           return (  1 );
           }
           return (  0 );
          }
          
          static void
          printlink(  rtems_shell_ls_globals* globals,   FTSENT *p )
          {
           int lnklen;
           char name[MAXPATHLEN + 1],   path[MAXPATHLEN + 1];
          
           if (  p->fts_level == FTS_ROOTLEVEL )
           (  void )snprintf(  name,   sizeof(  name ),   "%s",   p->fts_name );
           else
           (  void )snprintf(  name,   sizeof(  name ),  
           "%s/%s",   p->fts_parent->fts_accpath,   p->fts_name );
           if (  (  lnklen = readlink(  name,   path,   sizeof(  path ) - 1 ) ) == -1 ) {
           (  void )fprintf(  stderr,   "\nls: %s: %s\n",   name,   strerror(  errno ) );
           return;
           }
           path[lnklen] = '\0';
           (  void )printf(  " -> " );
           if (  f_octal || f_octal_escape )
           (  void )safe_print(  globals,   path );
           else if (  f_nonprint )
           (  void )printescaped(  globals,   path );
           else
           (  void )printf(  "%s",   path );
          }

libmisc/shell/print_heapinfo.c

       1  /*
           * Print Heap Information Structure
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: print_heapinfo.c,  v 1.2 2008/03/05 02:49:35 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <inttypes.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
      24  void rtems_shell_print_heap_info(  
           const char *c,  
           Heap_Information *h
           )
          {
           printf(  
           "Number of %s blocks: %" PRId32 "\n"
           "Largest %s block: %" PRId32 "\n"
           "Total bytes %s: %" PRId32 "\n",  
           c,   h->number,  
           c,   h->largest,  
           c,   h->total
            );
          }

libmisc/shell/pwcache.c

       1  /*
           * Copyright (  c ) 1989,   1993
           * The Regents of the University of California. 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.
           * 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          static char sccsid[] = "@(  # )pwcache.c 8.1 (  Berkeley ) 6/4/93";
          #endif /* LIBC_SCCS and not lint */
          #include <sys/cdefs.h>
      38  __FBSDID(  "$FreeBSD: src/lib/libc/gen/pwcache.c,  v 1.11 2007/01/09 00:27:55 imp Exp $" );
          
          #include <sys/types.h>
          
          #include <grp.h>
          #include <pwd.h>
          #include <stdio.h>
          #include <string.h>
          //#include <utmp.h>
          
          #define UT_NAMESIZE 64
          
          #define NCACHE 64 /* power of 2 */
          #define MASK (  NCACHE - 1 ) /* bits to store with */
          
          const char *
      54  user_from_uid(  uid_t uid,   int nouser )
          {
           static struct ncache {
           uid_t uid;
           int found;
           char name[UT_NAMESIZE + 1];
           } c_uid[NCACHE];
           static int pwopen;
           struct passwd *pw;
           struct ncache *cp;
          
           cp = c_uid + (  uid & MASK );
           if (  cp->uid != uid || !*cp->name ) {
           if (  pwopen == 0 ) {
           //setpassent(  1 );
           pwopen = 1;
           }
           pw = getpwuid(  uid );
           cp->uid = uid;
           if (  pw != NULL ) {
           cp->found = 1;
           (  void )strncpy(  cp->name,   pw->pw_name,   UT_NAMESIZE );
           cp->name[UT_NAMESIZE] = '\0';
           } else {
           cp->found = 0;
           (  void )snprintf(  cp->name,   UT_NAMESIZE,   "%u",   uid );
           if (  nouser )
           return (  NULL );
           }
           }
           return (  (  nouser && !cp->found ) ? NULL : cp->name );
          }
          
          char *
      88  group_from_gid(  gid_t gid,   int nogroup )
          {
           static struct ncache {
           gid_t gid;
           int found;
           char name[UT_NAMESIZE + 1];
           } c_gid[NCACHE];
           static int gropen;
           struct group *gr;
           struct ncache *cp;
          
           cp = c_gid + (  gid & MASK );
           if (  cp->gid != gid || !*cp->name ) {
           if (  gropen == 0 ) {
           //setgroupent(  1 );
           gropen = 1;
           }
           gr = getgrgid(  gid );
           cp->gid = gid;
           if (  gr != NULL ) {
           cp->found = 1;
           (  void )strncpy(  cp->name,   gr->gr_name,   UT_NAMESIZE );
           cp->name[UT_NAMESIZE] = '\0';
           } else {
           cp->found = 0;
           (  void )snprintf(  cp->name,   UT_NAMESIZE,   "%u",   gid );
           if (  nogroup )
           return (  NULL );
           }
           }
           return (  (  nogroup && !cp->found ) ? NULL : cp->name );
          }
          

libmisc/shell/shell.c

       1  /*
           *
           * Instantatiate a new terminal shell.
           *
           * Author:
           *
           * WORK: fernando.ruiz@ctv.es
           * HOME: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: shell.c,  v 1.48 2010/03/12 16:26:15 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <time.h>
          
          #include <rtems.h>
          #include <rtems/error.h>
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/system.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          #include <rtems/console.h>
          #include "internal.h"
          
          #include <termios.h>
          #include <string.h>
          #include <stdlib.h>
          #include <ctype.h>
          #include <sys/stat.h>
          #include <unistd.h>
          #include <errno.h>
          #include <pwd.h>
          
          rtems_shell_env_t rtems_global_shell_env = {
           .magic = rtems_build_name(  'S',   'E',   'N',   'V' ),  
           .devname = CONSOLE_DEVICE_NAME,  
           .taskname = "SHGL",  
           .exit_shell = false,  
           .forever = true,  
           .errorlevel = -1,  
           .echo = false,  
           .cwd = "/",  
           .input = NULL,  
           .output = NULL,  
           .output_append = false,  
           .wake_on_end = RTEMS_ID_NONE,  
           .login_check = NULL
          };
          
          rtems_shell_env_t *rtems_current_shell_env = &rtems_global_shell_env;
          
          /*
           * Initialize the shell user/process environment information
           */
      64  rtems_shell_env_t *rtems_shell_init_env(  
           rtems_shell_env_t *shell_env_p
           )
          {
           rtems_shell_env_t *shell_env;
          
           shell_env = malloc(  sizeof(  rtems_shell_env_t ) );
           if (   !shell_env  )
           return NULL;
           if (   !shell_env_p  ) {
           *shell_env = rtems_global_shell_env;
           } else {
           *shell_env = *shell_env_p;
           }
           shell_env->taskname = NULL;
          
           return shell_env;
          }
          
          /*
           * Completely free a shell_env_t and all associated memory
           */
      86  void rtems_shell_env_free(  
           void *ptr
           )
          {
           rtems_shell_env_t *shell_env;
           shell_env = (  rtems_shell_env_t * ) ptr;
          
           if (   !ptr  )
           return;
          
           if (   shell_env->input  )
           free(  (  void * )shell_env->input );
           if (   shell_env->output  )
           free(  (  void * )shell_env->output );
           free(   ptr  );
          }
          
          /*
           * Get a line of user input with modest features
           */
     106  int rtems_shell_line_editor(  
           char *cmds[],  
           int count,  
           int size,  
           const char *prompt,  
           FILE *in,  
           FILE *out
           )
          {
           unsigned int extended_key;
           int c;
           int col;
           int last_col;
           int output;
           char line[size];
           char new_line[size];
           int up;
           int cmd = -1;
           int inserting = 1;
          
           output = (  out && isatty(  fileno(  in ) ) );
          
           col = last_col = 0;
          
           tcdrain(  fileno(  in ) );
           if (  out )
           tcdrain(  fileno(  out ) );
          
           if (  output && prompt )
           fprintf(  out,   "\r%s",   prompt );
          
           line[0] = 0;
           new_line[0] = 0;
          
           for (  ;; ) {
          
           if (  output )
           fflush(  out );
          
           extended_key = rtems_shell_getchar(  in );
          
           if (  extended_key == EOF )
           return -2;
          
           c = extended_key & RTEMS_SHELL_KEYS_NORMAL_MASK;
          
           /*
           * Make the extended_key usable as a boolean.
           */
           extended_key &= ~RTEMS_SHELL_KEYS_NORMAL_MASK;
          
           up = 0;
          
           if (  extended_key )
           {
           switch (  c )
           {
           case RTEMS_SHELL_KEYS_END:
           if (  output )
           fprintf(  out,   "%s",   line + col );
           col = (  int ) strlen (  line );
           break;
          
           case RTEMS_SHELL_KEYS_HOME:
           if (  output ) {
           if (  prompt )
           fprintf(  out,  "\r%s",   prompt );
           }
           col = 0;
           break;
          
           case RTEMS_SHELL_KEYS_LARROW:
           if (  col > 0 )
           {
           col--;
           if (  output )
           fputc(  '\b',   out );
           }
           break;
          
           case RTEMS_SHELL_KEYS_RARROW:
           if (  (  col < size ) && (  line[col] != '\0' ) )
           {
           if (  output )
           fprintf(  out,   "%c",   line[col] );
           col++;
           }
           break;
          
           case RTEMS_SHELL_KEYS_UARROW:
           if (  (  cmd >= (  count - 1 ) ) || (  strlen(  cmds[cmd + 1] ) == 0 ) ) {
           if (  output )
           fputc(  '\x7',   out );
           break;
           }
          
           up = 1;
          
           /* drop through */
           case RTEMS_SHELL_KEYS_DARROW:
          
           {
           int last_cmd = cmd;
           int clen = strlen (  line );
          
           if (  prompt )
           clen += strlen(  prompt );
          
           if (  up ) {
           cmd++;
           } else {
           if (  cmd < 0 ) {
           if (  output )
           fprintf(  out,   "\x7" );
           break;
           }
           else
           cmd--;
           }
          
           if (  (  last_cmd < 0 ) || (  strcmp(  cmds[last_cmd],   line ) != 0 ) )
           memcpy (  new_line,   line,   size );
          
           if (  cmd < 0 )
           memcpy (  line,   new_line,   size );
           else
           memcpy (  line,   cmds[cmd],   size );
          
           col = strlen (  line );
          
           if (  output ) {
           fprintf(  out,  "\r%*c",   clen,   ' ' );
           fprintf(  out,  "\r%s%s",   prompt,   line );
           }
           }
           break;
          
           case RTEMS_SHELL_KEYS_DEL:
           if (  line[col] != '\0' )
           {
           int end;
           int bs;
           strcpy (  &line[col],   &line[col + 1] );
           if (  output ) {
           fprintf(  out,  "\r%s%s ",   prompt,   line );
           end = (  int ) strlen (  line );
           for (  bs = 0; bs < (  (  end - col ) + 1 ); bs++ )
           fputc(  '\b',   out );
           }
           }
           break;
          
           case RTEMS_SHELL_KEYS_INS:
           inserting = inserting ? 0 : 1;
           break;
           }
           }
           else
           {
           switch (  c )
           {
           case 1:/*Control-a*/
           if (  output ) {
           if (  prompt )
           fprintf(  out,  "\r%s",   prompt );
           }
           col = 0;
           break;
          
           case 5:/*Control-e*/
           if (  output )
           fprintf(  out,   "%s",   line + col );
           col = (  int ) strlen (  line );
           break;
          
           case 11:/*Control-k*/
           if (  line[col] ) {
           if (  output ) {
           int end = strlen(  line );
           int bs;
           fprintf(  out,  "%*c",   end - col,   ' ' );
           for (  bs = 0; bs < (  end - col ); bs++ )
           fputc(  '\b',   out );
           }
           line[col] = '\0';
           }
           break;
          
           case 0x04:/*Control-d*/
           if (  strlen(  line ) )
           break;
           case EOF:
           if (  output )
           fputc(  '\n',   out );
           return -2;
          
           case '\f':
           if (  output ) {
           int end;
           int bs;
           fputc(  '\f',  out );
           fprintf(  out,  "\r%s%s",   prompt,   line );
           end = (  int ) strlen (  line );
           for (  bs = 0; bs < (  end - col ); bs++ )
           fputc(  '\b',   out );
           }
           break;
          
           case '\b':
           case '\x7f':
           if (  col > 0 )
           {
           int bs;
           col--;
           strcpy (  line + col,   line + col + 1 );
           if (  output ) {
           fprintf(  out,  "\b%s \b",   line + col );
           for (  bs = 0; bs < (  (  int ) strlen (  line ) - col ); bs++ )
           fputc(  '\b',   out );
           }
           }
           break;
          
           case '\n':
           case '\r':
           {
           /*
           * Process the command.
           */
           if (  output )
           fprintf(  out,  "\n" );
          
           /*
           * Only process the command if we have a command and it is not
           * repeated in the history.
           */
           if (  strlen(  line ) == 0 ) {
           cmd = -1;
           } else {
           if (  (  cmd < 0 ) || (  strcmp(  line,   cmds[cmd] ) != 0 ) ) {
           if (  count > 1 )
           memmove(  cmds[1],   cmds[0],   (  count - 1 ) * size );
           memmove (  cmds[0],   line,   size );
           cmd = 0;
           }
           }
           }
           return cmd;
          
           default:
           if (  (  col < (  size - 1 ) ) && (  c >= ' ' ) && (  c <= '~' ) ) {
           int end = strlen (  line );
           if (  inserting && (  col < end ) && (  end < size ) ) {
           int ch,   bs;
           for (  ch = end + 1; ch > col; ch-- )
           line[ch] = line[ch - 1];
           if (  output ) {
           fprintf(  out,   "%s",   line + col );
           for (  bs = 0; bs < (  end - col + 1 ); bs++ )
           fputc(  '\b',   out );
           }
           }
           line[col++] = c;
           if (  col > end )
           line[col] = '\0';
           if (  output )
           fputc(  c,   out );
           }
           break;
           }
           }
           }
           return -2;
          }
          
          /* ----------------------------------------------- *
           * - The shell TASK
           * Poor but enough..
           * TODO: Redirection. Tty Signals. ENVVARs. Shell language.
           * ----------------------------------------------- */
          
     387  void rtems_shell_init_issue(  void )
          {
           static bool issue_inited=false;
           struct stat buf;
          
           if (  issue_inited )
           return;
           issue_inited = true;
          
           /* dummy call to init /etc dir */
           getpwnam(  "root" );
          
           if (  stat(  "/etc/issue",  &buf ) ) {
           rtems_shell_write_file(  "/etc/issue",  
           "\n"
           "Welcome to @V\\n"
           "Login into @S\\n" );
           }
          
           if (  stat(  "/etc/issue.net",  &buf ) ) {
           rtems_shell_write_file(  "/etc/issue.net",  
           "\n"
           "Welcome to %v\n"
           "running on %m\n" );
           }
          }
          
     414  static bool rtems_shell_login(  FILE * in,  FILE * out ) {
           FILE *fd;
           int c;
           time_t t;
          
           rtems_shell_init_issue(   );
           setuid(  0 );
           setgid(  0 );
           rtems_current_user_env->euid =
           rtems_current_user_env->egid =0;
          
           if (  out ) {
           if (  (  rtems_current_shell_env->devname[5]!='p' )||
           (  rtems_current_shell_env->devname[6]!='t' )||
           (  rtems_current_shell_env->devname[7]!='y' ) ) {
           fd = fopen(  "/etc/issue",  "r" );
           if (  fd ) {
           while (  (  c=fgetc(  fd ) )!=EOF ) {
           if (  c=='@' ) {
           switch(  c=fgetc(  fd ) ) {
           case 'L':
           fprintf(  out,  "%s",  rtems_current_shell_env->devname );
           break;
           case 'B':
           fprintf(  out,  "0" );
           break;
           case 'T':
           case 'D':
           time(  &t );
           fprintf(  out,  "%s",  ctime(  &t ) );
           break;
           case 'S':
           fprintf(  out,  "RTEMS" );
           break;
           case 'V':
           fprintf(  out,  "%s\n%s",  _RTEMS_version,   _Copyright_Notice );
           break;
           case '@':
           fprintf(  out,  "@" );
           break;
           default :
           fprintf(  out,  "@%c",  c );
           break;
           }
           } else if (  c=='\\' ) {
           switch(  c=fgetc(  fd ) ) {
           case '\\': fprintf(  out,  "\\" ); break;
           case 'b': fprintf(  out,  "\b" ); break;
           case 'f': fprintf(  out,  "\f" ); break;
           case 'n': fprintf(  out,  "\n" ); break;
           case 'r': fprintf(  out,  "\r" ); break;
           case 's': fprintf(  out,  " " ); break;
           case 't': fprintf(  out,  "\t" ); break;
           case '@': fprintf(  out,  "@" ); break;
           }
           } else {
           fputc(  c,  out );
           }
           }
           fclose(  fd );
           }
           } else {
           fd = fopen(  "/etc/issue.net",  "r" );
           if (  fd ) {
           while (  (  c=fgetc(  fd ) )!=EOF ) {
           if (  c=='%' ) {
           switch(  c=fgetc(  fd ) ) {
           case 't':
           fprintf(  out,  "%s",  rtems_current_shell_env->devname );
           break;
           case 'h':
           fprintf(  out,  "0" );
           break;
           case 'D':
           fprintf(  out,  " " );
           break;
           case 'd':
           time(  &t );
           fprintf(  out,  "%s",  ctime(  &t ) );
           break;
           case 's':
           fprintf(  out,  "RTEMS" );
           break;
           case 'm':
           fprintf(  out,  "(  " CPU_NAME "/" CPU_MODEL_NAME " )" );
           break;
           case 'r':
           fprintf(  out,  _RTEMS_version );
           break;
           case 'v':
           fprintf(  out,  "%s\n%s",  _RTEMS_version,  _Copyright_Notice );
           break;
           case '%':fprintf(  out,  "%%" );
           break;
           default:
           fprintf(  out,  "%%%c",  c );
           break;
           }
           } else {
           fputc(  c,  out );
           }
           }
           fclose(  fd );
           }
           }
           }
          
           return rtems_shell_login_prompt(  
           in,  
           out,  
           rtems_current_shell_env->devname,  
           rtems_current_shell_env->login_check
            );
          }
          
          #if defined(  SHELL_DEBUG )
     530  void rtems_shell_print_env(  
           rtems_shell_env_t * shell_env
           )
          {
           if (   !shell_env  ) {
           printk(   "shell_env is NULL\n"  );
           return;
           }
           printk(   "shell_env=%p\n"
           "shell_env->magic=0x%08x\t"
           "shell_env->devname=%s\n"
           "shell_env->taskname=%s\t"
           "shell_env->exit_shell=%d\t"
           "shell_env->forever=%d\n",  
           shell_env->magic,  
           shell_env->devname,  
           (  (  shell_env->taskname ) ? shell_env->taskname : "NOT SET" ),  
           shell_env->exit_shell,  
           shell_env->forever
            );
          }
          #endif
          
     553  rtems_task rtems_shell_task(  rtems_task_argument task_argument )
          {
           rtems_shell_env_t *shell_env = (  rtems_shell_env_t* ) task_argument;
           rtems_id wake_on_end = shell_env->wake_on_end;
           rtems_shell_main_loop(   shell_env  );
           if (  wake_on_end != RTEMS_INVALID_ID )
           rtems_event_send (  wake_on_end,   RTEMS_EVENT_1 );
           rtems_task_delete(   RTEMS_SELF  );
          }
          
          #define RTEMS_SHELL_MAXIMUM_ARGUMENTS (  128 )
          #define RTEMS_SHELL_CMD_SIZE (  128 )
          #define RTEMS_SHELL_CMD_COUNT (  32 )
          #define RTEMS_SHELL_PROMPT_SIZE (  128 )
          
     568  bool rtems_shell_main_loop(  
           rtems_shell_env_t *shell_env_arg
           )
          {
           rtems_shell_env_t *shell_env;
           rtems_shell_cmd_t *shell_cmd;
           rtems_status_code sc;
           struct termios term;
           struct termios previous_term;
           char *prompt = NULL;
           int cmd;
           int cmd_count = 1; /* assume a script and so only 1 command line */
           char *cmds[RTEMS_SHELL_CMD_COUNT];
           char *cmd_argv;
           int argc;
           char *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS];
           bool result = true;
           bool input_file = false;
           int line = 0;
           FILE *stdinToClose = NULL;
           FILE *stdoutToClose = NULL;
          
           rtems_shell_initialize_command_set(   );
          
           shell_env =
           rtems_current_shell_env = rtems_shell_init_env(   shell_env_arg  );
          
           /*
           * @todo chrisj
           * Remove the use of task variables. Change to have a single
           * allocation per shell and then set into a notepad register
           * in the TCB. Provide a function to return the pointer.
           * Task variables are a virus to embedded systems software.
           */
           sc = rtems_task_variable_add(  
           RTEMS_SELF,  
           (  void* )&rtems_current_shell_env,  
           rtems_shell_env_free
            );
           if (  sc != RTEMS_SUCCESSFUL ) {
           rtems_error(  sc,  "rtems_task_variable_add(  current_shell_env ):" );
           return false;
           }
          
           setuid(  0 );
           setgid(  0 );
          
           rtems_current_user_env->euid = rtems_current_user_env->egid = 0;
          
           fileno(  stdout );
          
           /* fprintf(   stderr,  
           "-%s-%s-\n",   shell_env->input,   shell_env->output  );
           */
          
           if (  shell_env->output && strcmp(  shell_env->output,   "stdout" ) != 0 ) {
           if (  strcmp(  shell_env->output,   "stderr" ) == 0 ) {
           stdout = stderr;
           } else if (  strcmp(  shell_env->output,   "/dev/null" ) == 0 ) {
           fclose (  stdout );
           } else {
           FILE *output = fopen(  shell_env_arg->output,  
           shell_env_arg->output_append ? "a" : "w" );
           if (  !output ) {
           fprintf(  stderr,   "shell: open output %s failed: %s\n",  
           shell_env_arg->output,   strerror(  errno ) );
           return false;
           }
           stdout = output;
           stdoutToClose = output;
           }
           }
          
           if (  shell_env->input && strcmp(  shell_env_arg->input,   "stdin" ) != 0 ) {
           FILE *input = fopen(  shell_env_arg->input,   "r" );
           if (  !input ) {
           fprintf(  stderr,   "shell: open input %s failed: %s\n",  
           shell_env_arg->input,   strerror(  errno ) );
           return false;
           }
           stdin = input;
           stdinToClose = input;
           shell_env->forever = false;
           input_file =true;
           }
           else {
           /* make a raw terminal,  Linux Manuals */
           if (  tcgetattr(  fileno(  stdin ),   &previous_term ) >= 0 ) {
           term = previous_term;
           term.c_iflag &= ~(  IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON );
           term.c_oflag &= ~OPOST;
           term.c_oflag |= (  OPOST|ONLCR ); /* But with cr+nl on output */
           term.c_lflag &= ~(  ECHO|ECHONL|ICANON|ISIG|IEXTEN );
           term.c_cflag |= CLOCAL | CREAD;
           term.c_cc[VMIN] = 1;
           term.c_cc[VTIME] = 0;
           if (  tcsetattr (  fileno(  stdin ),   TCSADRAIN,   &term ) < 0 ) {
           fprintf(  stderr,  
           "shell:cannot set terminal attributes(  %s )\n",  shell_env->devname );
           }
           }
           cmd_count = RTEMS_SHELL_CMD_COUNT;
           prompt = malloc(  RTEMS_SHELL_PROMPT_SIZE );
           if (  !prompt )
           fprintf(  stderr,  
           "shell:cannot allocate prompt memory\n" );
           }
          
           setvbuf(  stdin,  NULL,  _IONBF,  0 ); /* Not buffered*/
           setvbuf(  stdout,  NULL,  _IONBF,  0 ); /* Not buffered*/
          
           rtems_shell_initialize_command_set(   );
          
           /*
           * Allocate the command line buffers.
           */
           cmd_argv = malloc (  RTEMS_SHELL_CMD_SIZE );
           if (  !cmd_argv ) {
           fprintf(  stderr,   "no memory for command line buffers\n"  );
           }
          
           cmds[0] = calloc (  cmd_count,   RTEMS_SHELL_CMD_SIZE );
           if (  !cmds[0] ) {
           fprintf(  stderr,   "no memory for command line buffers\n"  );
           }
          
           if (  cmd_argv && cmds[0] ) {
          
           memset (  cmds[0],   0,   cmd_count * RTEMS_SHELL_CMD_SIZE );
          
           for (  cmd = 1; cmd < cmd_count; cmd++ ) {
           cmds[cmd] = cmds[cmd - 1] + RTEMS_SHELL_CMD_SIZE;
           }
          
           do {
           /* Set again root user and root filesystem,   side effect of set_priv..*/
           sc = rtems_libio_set_private_env(   );
           if (  sc != RTEMS_SUCCESSFUL ) {
           rtems_error(  sc,  "rtems_libio_set_private_env(   ):" );
           result = false;
           break;
           }
          
           /*
           * By using result here,   we can fall to the bottom of the
           * loop when the connection is dropped during login and
           * keep on trucking.
           */
           if (  shell_env->login_check != NULL ) {
           result = rtems_shell_login(  stdin,  stdout );
           } else {
           result = true;
           }
          
           if (  result ) {
           const char *c;
           memset (  cmds[0],   0,   cmd_count * RTEMS_SHELL_CMD_SIZE );
           if (  !input_file ) {
           rtems_shell_cat_file(  stdout,  "/etc/motd" );
           fprintf(  stdout,   "\n"
           "RTEMS SHELL (  Ver.1.0-FRC ):%s. " \
           __DATE__". 'help' to list commands.\n",  
           shell_env->devname );
           }
          
           if (  input_file )
           chdir(  shell_env->cwd );
           else
           chdir(  "/" ); /* XXX: chdir to getpwent homedir */
          
           shell_env->exit_shell = false;
          
           for (  ;; ) {
           int cmd;
          
           /* Prompt section */
           if (  prompt ) {
           rtems_shell_get_prompt(  shell_env,   prompt,  
           RTEMS_SHELL_PROMPT_SIZE );
           }
          
           /* getcmd section */
           cmd = rtems_shell_line_editor(  cmds,   cmd_count,  
           RTEMS_SHELL_CMD_SIZE,   prompt,  
           stdin,   stdout );
          
           if (  cmd == -1 )
           continue; /* empty line */
          
           if (  cmd == -2 )
           break; /*EOF*/
          
           line++;
          
           if (  shell_env->echo )
           fprintf(  stdout,   "%d: %s\n",   line,   cmds[cmd] );
          
           /* evaluate cmd section */
           c = cmds[cmd];
           while (  *c ) {
           if (  !isblank(  (  unsigned char )*c ) )
           break;
           c++;
           }
          
           if (  *c == '\0' ) /* empty line */
           continue;
          
           if (  *c == '#' ) { /* comment character */
           cmds[cmd][0] = 0;
           continue;
           }
          
           if (  !strcmp(  cmds[cmd],  "bye" ) || !strcmp(  cmds[cmd],  "exit" ) ) {
           fprintf(  stdout,   "Shell exiting\n"  );
           break;
           } else if (  !strcmp(  cmds[cmd],  "shutdown" ) ) { /* exit application */
           fprintf(  stdout,   "System shutting down at user request\n"  );
           exit(  0 );
           }
          
           /* exec cmd section */
           /* TODO:
           * To avoid user crash catch the signals.
           * Open a new stdio files with posibility of redirection *
           * Run in a new shell task background. (  unix & )
           * Resuming. A little bash.
           */
           memcpy (  cmd_argv,   cmds[cmd],   RTEMS_SHELL_CMD_SIZE );
           if (  !rtems_shell_make_args(  cmd_argv,   &argc,   argv,  
           RTEMS_SHELL_MAXIMUM_ARGUMENTS ) ) {
           shell_cmd = rtems_shell_lookup_cmd(  argv[0] );
           if (   argv[0] == NULL  ) {
           shell_env->errorlevel = -1;
           } else if (   shell_cmd == NULL  ) {
           shell_env->errorlevel = rtems_shell_script_file(  argc,   argv );
           } else {
           shell_env->errorlevel = shell_cmd->command(  argc,   argv );
           }
           }
          
           /* end exec cmd section */
           if (  shell_env->exit_shell )
           break;
           }
          
           fflush(   stdout  );
           fflush(   stderr  );
           }
           } while (  result && shell_env->forever );
          
           }
          
           if (  cmds[0] )
           free (  cmds[0] );
           if (  cmd_argv )
           free (  cmd_argv );
           if (  prompt )
           free (  prompt );
          
           if (  stdinToClose ) {
           fclose(   stdinToClose  );
           } else {
           if (  tcsetattr(  fileno(  stdin ),   TCSADRAIN,   &previous_term ) < 0 ) {
           fprintf(  
           stderr,  
           "shell: cannot reset terminal attributes (  %s )\n",  
           shell_env->devname
            );
           }
           }
           if (   stdoutToClose  )
           fclose(   stdoutToClose  );
           return result;
          }
          
          /* ----------------------------------------------- */
     845  static rtems_status_code rtems_shell_run (  
           const char *task_name,  
           size_t task_stacksize,  
           rtems_task_priority task_priority,  
           const char *devname,  
           bool forever,  
           bool wait,  
           const char *input,  
           const char *output,  
           bool output_append,  
           rtems_id wake_on_end,  
           bool echo,  
           rtems_shell_login_check_t login_check
           )
          {
           rtems_id task_id;
           rtems_status_code sc;
           rtems_shell_env_t *shell_env;
           rtems_name name;
          
           if (   task_name && strlen(  task_name ) >= 4 )
           name = rtems_build_name(  
           task_name[0],   task_name[1],   task_name[2],   task_name[3] );
           else
           name = rtems_build_name(   'S',   'E',   'N',   'V'  );
          
           sc = rtems_task_create(  
           name,  
           task_priority,  
           task_stacksize,  
           RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,  
           RTEMS_LOCAL | RTEMS_FLOATING_POINT,  
           &task_id
            );
           if (  sc != RTEMS_SUCCESSFUL ) {
           rtems_error(  sc,  "creating task %s in shell_init(   )",  task_name );
           return sc;
           }
          
           shell_env = rtems_shell_init_env(   NULL  );
           if (   !shell_env  ) {
           rtems_error(  RTEMS_NO_MEMORY,  
           "allocating shell_env %s in shell_init(   )",  task_name );
           return RTEMS_NO_MEMORY;
           }
           shell_env->devname = devname;
           shell_env->taskname = task_name;
           shell_env->exit_shell = false;
           shell_env->forever = forever;
           shell_env->echo = echo;
           shell_env->input = strdup (  input );
           shell_env->output = strdup (  output );
           shell_env->output_append = output_append;
           shell_env->wake_on_end = wake_on_end;
           shell_env->login_check = login_check;
          
           getcwd(  shell_env->cwd,   sizeof(  shell_env->cwd ) );
          
           sc = rtems_task_start(  task_id,   rtems_shell_task,  
           (  rtems_task_argument ) shell_env );
           if (  sc != RTEMS_SUCCESSFUL ) {
           rtems_error(  sc,  "starting task %s in shell_init(   )",  task_name );
           return sc;
           }
          
           if (  wait ) {
           rtems_event_set out;
           sc = rtems_event_receive (  RTEMS_EVENT_1,   RTEMS_WAIT,   0,   &out );
           }
          
           return 0;
          }
          
     918  rtems_status_code rtems_shell_init(  
           const char *task_name,  
           size_t task_stacksize,  
           rtems_task_priority task_priority,  
           const char *devname,  
           bool forever,  
           bool wait,  
           rtems_shell_login_check_t login_check
           )
          {
           rtems_id to_wake = RTEMS_ID_NONE;
          
           if (   wait  )
           to_wake = rtems_task_self(   );
          
           return rtems_shell_run(  
           task_name,   /* task_name */
           task_stacksize,   /* task_stacksize */
           task_priority,   /* task_priority */
           devname,   /* devname */
           forever,   /* forever */
           wait,   /* wait */
           "stdin",   /* input */
           "stdout",   /* output */
           false,   /* output_append */
           to_wake,   /* wake_on_end */
           false,   /* echo */
           login_check /* login check */
            );
          }
          
     949  rtems_status_code rtems_shell_script (  
           const char *task_name,  
           size_t task_stacksize,  
           rtems_task_priority task_priority,  
           const char* input,  
           const char* output,  
           bool output_append,  
           bool wait,  
           bool echo
           )
          {
           rtems_id current_task = RTEMS_INVALID_ID;
           rtems_status_code sc;
          
           if (  wait ) {
           sc = rtems_task_ident (  RTEMS_SELF,   RTEMS_LOCAL,   &current_task );
           if (  sc != RTEMS_SUCCESSFUL )
           return sc;
           }
          
           sc = rtems_shell_run(  
           task_name,   /* task_name */
           task_stacksize,   /* task_stacksize */
           task_priority,   /* task_priority */
           NULL,   /* devname */
           0,   /* forever */
           wait,   /* wait */
           input,   /* input */
           output,   /* output */
           output_append,   /* output_append */
           current_task,   /* wake_on_end */
           echo,   /* echo */
           NULL /* login check */
            );
           if (  sc != RTEMS_SUCCESSFUL )
           return sc;
          
           return sc;
          }

libmisc/shell/shell_cmdset.c

       1  /*
           *
           * Shell Command Set Management
           *
           * Author:
           * WORK: fernando.ruiz@ctv.es
           * HOME: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: shell_cmdset.c,  v 1.6 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <time.h>
          #include <termios.h>
          #include <string.h>
          #include <stdlib.h>
          #include <ctype.h>
          #include <sys/stat.h>
          #include <unistd.h>
          #include <errno.h>
          
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          #include "internal.h"
          
          /*
           * Common linked list of shell commands.
           *
           * Because the help report is very long,   there is a topic for each command.
           *
           * Help list the topics
           * help [topic] list the commands for the topic
           * help [command] help for the command
           *
           */
          
          rtems_shell_cmd_t * rtems_shell_first_cmd;
          rtems_shell_topic_t * rtems_shell_first_topic;
          
          /*
           * Find the topic from the set of topics registered.
           */
      53  rtems_shell_topic_t * rtems_shell_lookup_topic(  const char * topic ) {
           rtems_shell_topic_t * shell_topic;
           shell_topic=rtems_shell_first_topic;
          
           while (  shell_topic ) {
           if (  !strcmp(  shell_topic->topic,  topic ) )
           return shell_topic;
           shell_topic=shell_topic->next;
           }
           return (  rtems_shell_topic_t * ) NULL;
          }
          
          /*
           * Add a new topic to the list of topics
           */
      68  rtems_shell_topic_t * rtems_shell_add_topic(  const char * topic ) {
           rtems_shell_topic_t * current,  *aux;
          
           if (  !rtems_shell_first_topic ) {
           aux = malloc(  sizeof(  rtems_shell_topic_t ) );
           aux->topic = topic;
           aux->next = (  rtems_shell_topic_t* )NULL;
           return rtems_shell_first_topic = aux;
           }
           current=rtems_shell_first_topic;
           if (  !strcmp(  topic,  current->topic ) )
           return current;
          
           while (  current->next ) {
           if (  !strcmp(  topic,  current->next->topic ) )
           return current->next;
           current=current->next;
           }
           aux = malloc(  sizeof(  rtems_shell_topic_t ) );
           aux->topic = topic;
           aux->next = (  rtems_shell_topic_t* )NULL;
           current->next = aux;
           return aux;
          }
          
          /*
           * Find the command in the set
           */
      96  rtems_shell_cmd_t * rtems_shell_lookup_cmd(  const char * cmd ) {
           rtems_shell_cmd_t * shell_cmd;
           shell_cmd=rtems_shell_first_cmd;
           while (  shell_cmd ) {
           if (  !strcmp(  shell_cmd->name,  cmd ) ) return shell_cmd;
           shell_cmd=shell_cmd->next;
           };
           return (  rtems_shell_cmd_t * ) NULL;
          }
          
          /*
           * Add a command structure to the set of known commands
           */
     109  rtems_shell_cmd_t *rtems_shell_add_cmd_struct(  
           rtems_shell_cmd_t *shell_cmd
           )
          {
           rtems_shell_cmd_t *shell_pvt;
          
           shell_pvt = rtems_shell_first_cmd;
           while (  shell_pvt ) {
           if (  strcmp(  shell_pvt->name,   shell_cmd->name ) == 0 )
           return NULL;
           shell_pvt = shell_pvt->next;
           }
          
           if (   !rtems_shell_first_cmd  ) {
           rtems_shell_first_cmd = shell_cmd;
           } else {
           shell_pvt = rtems_shell_first_cmd;
           while (  shell_pvt->next )
           shell_pvt = shell_pvt->next;
           shell_pvt->next = shell_cmd;
           }
           rtems_shell_add_topic(   shell_cmd->topic  );
           return shell_cmd;
          }
          
          /*
           * Add a command as a set of arguments to the set and
           * allocate the command structure on the fly.
           */
     138  rtems_shell_cmd_t * rtems_shell_add_cmd(  
           const char *name,  
           const char *topic,  
           const char *usage,  
           rtems_shell_command_t command
           )
          {
           rtems_shell_cmd_t *shell_cmd = NULL;
           char *my_name = NULL;
           char *my_topic = NULL;
           char *my_usage = NULL;
          
           /* Reject empty commands */
           if (  name == NULL || command == NULL ) {
           return NULL;
           }
          
           /* Allocate command stucture */
           shell_cmd = (  rtems_shell_cmd_t * ) malloc(  sizeof(  rtems_shell_cmd_t ) );
           if (  shell_cmd == NULL ) {
           return NULL;
           }
          
           /* Allocate strings */
           my_name = strdup(  name );
           my_topic = strdup(  topic );
           my_usage = strdup(  usage );
          
           /* Assign values */
           shell_cmd->name = my_name;
           shell_cmd->topic = my_topic;
           shell_cmd->usage = my_usage;
           shell_cmd->command = command;
           shell_cmd->alias = NULL;
           shell_cmd->next = NULL;
          
           if (  rtems_shell_add_cmd_struct(  shell_cmd ) == NULL ) {
           /* Something is wrong,   free allocated resources */
           free(  my_usage );
           free(  my_topic );
           free(  my_name );
           free(  shell_cmd );
          
           return NULL;
           }
          
           return shell_cmd;
          }
          
          
     188  void rtems_shell_initialize_command_set(  void )
          {
           rtems_shell_cmd_t **c;
           rtems_shell_alias_t **a;
          
           for (   c = rtems_shell_Initial_commands ; *c ; c++  ) {
           rtems_shell_add_cmd_struct(   *c  );
           }
          
           for (   a = rtems_shell_Initial_aliases ; *a ; a++  ) {
           rtems_shell_alias_cmd(   (  *a )->name,   (  *a )->alias  );
           }
          
           rtems_shell_register_monitor_commands(   );
          }
          
          /* ----------------------------------------------- *
           * you can make an alias for every command.
           * ----------------------------------------------- */
     207  rtems_shell_cmd_t *rtems_shell_alias_cmd(  
           const char *cmd,  
           const char *alias
           )
          {
           rtems_shell_cmd_t *shell_cmd,   *shell_aux;
          
           shell_aux = (  rtems_shell_cmd_t * ) NULL;
          
           if (  alias ) {
           shell_aux = rtems_shell_lookup_cmd(  alias );
           if (  shell_aux != NULL ) {
           return NULL;
           }
           shell_cmd = rtems_shell_lookup_cmd(  cmd );
           if (  shell_cmd != NULL ) {
           shell_aux = rtems_shell_add_cmd(  
           alias,  
           shell_cmd->topic,  
           shell_cmd->usage,  
           shell_cmd->command
            );
           if (  shell_aux )
           shell_aux->alias = shell_cmd;
           }
           }
           return shell_aux;
          }

libmisc/shell/shell_getchar.c

       1  /*
           *
           * Handle keys for the shell.
           *
           * Author:
           *
           * Chris Johns (  chrisj@rtems.org )
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: shell_getchar.c,  v 1.3 2008/12/18 15:25:27 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <time.h>
          
          #include <rtems.h>
          #include <rtems/error.h>
          #include <rtems/system.h>
          #include <rtems/shell.h>
          #include <rtems/shellconfig.h>
          #include "internal.h"
          
          /*
           * Taken from the monitor code.
           */
          
          /*
           * Translation tables. Not sure if this is the best way to
           * handle this,   how-ever I wish to avoid the overhead of
           * including a more complete and standard environment such
           * as ncurses.
           */
          
          struct translation_table
          {
           char expecting;
           const struct translation_table *branch;
           unsigned int key;
          };
          
          static const struct translation_table trans_one[] =
          {
           { '\x7e',   0,   RTEMS_SHELL_KEYS_HOME },  
           { 0,   0,   0 }
          };
          
          static const struct translation_table trans_two[] =
          {
           { '~',   0,   RTEMS_SHELL_KEYS_INS },  
           { 0,   0,   0 }
          };
          
          static const struct translation_table trans_three[] =
          {
           { '~',   0,   RTEMS_SHELL_KEYS_DEL },  
           { 0,   0,   0 }
          };
          
          static const struct translation_table trans_tab_csi[] =
          {
           { '1',   trans_one,   0 },  
           { '2',   trans_two,   0 },  
           { '3',   trans_three,   0 },  
           { 'A',   0,   RTEMS_SHELL_KEYS_UARROW },  
           { 'B',   0,   RTEMS_SHELL_KEYS_DARROW },  
           { 'D',   0,   RTEMS_SHELL_KEYS_LARROW },  
           { 'C',   0,   RTEMS_SHELL_KEYS_RARROW },  
           { 'F',   0,   RTEMS_SHELL_KEYS_END },  
           { 'H',   0,   RTEMS_SHELL_KEYS_HOME },  
           { 0,   0,   0 }
          };
          
          static const struct translation_table trans_tab_O[] =
          {
           { '1',   0,   RTEMS_SHELL_KEYS_F1 },  
           { '2',   0,   RTEMS_SHELL_KEYS_F2 },  
           { '3',   0,   RTEMS_SHELL_KEYS_F3 },  
           { '4',   0,   RTEMS_SHELL_KEYS_F4 },  
           { '5',   0,   RTEMS_SHELL_KEYS_F5 },  
           { '6',   0,   RTEMS_SHELL_KEYS_F6 },  
           { '7',   0,   RTEMS_SHELL_KEYS_F7 },  
           { '8',   0,   RTEMS_SHELL_KEYS_F8 },  
           { '9',   0,   RTEMS_SHELL_KEYS_F9 },  
           { ':',   0,   RTEMS_SHELL_KEYS_F10 },  
           { 'F',   0,   RTEMS_SHELL_KEYS_END },  
           { 'P',   0,   RTEMS_SHELL_KEYS_F1 },  
           { 'Q',   0,   RTEMS_SHELL_KEYS_F2 },  
           { 'R',   0,   RTEMS_SHELL_KEYS_F3 },  
           { 'S',   0,   RTEMS_SHELL_KEYS_F4 },  
           { 'T',   0,   RTEMS_SHELL_KEYS_F5 },  
           { 'U',   0,   RTEMS_SHELL_KEYS_F6 },  
           { 'V',   0,   RTEMS_SHELL_KEYS_F7 },  
           { 'W',   0,   RTEMS_SHELL_KEYS_F8 },  
           { 'X',   0,   RTEMS_SHELL_KEYS_F9 },  
           { 'Y',   0,   RTEMS_SHELL_KEYS_F10 },  
           { 0,   0,   0 }
          };
          
          static const struct translation_table trans_tab[] =
          {
           { '[',   trans_tab_csi,   0 },   /* CSI command sequences */
           { 'O',   trans_tab_O,   0 },   /* O are the fuction keys */
           { 0,   0,   0 }
          };
          
          /*
           * Perform a basic tranlation for some ANSI/VT100 key codes.
           * This code could do with a timeout on the ESC as it is
           * now lost from the input stream. It is not* used by the
           * line editor below so considiered not worth the effort.
           */
          
          unsigned int
     121  rtems_shell_getchar (  FILE *in )
          {
           const struct translation_table *translation = 0;
           for (  ;; )
           {
           int c = fgetc (  in );
           if (  c == EOF )
           return EOF;
           if (  c == 27 )
           translation = trans_tab;
           else
           {
           /*
           * If no translation happing just pass through
           * and return the key.
           */
           if (  translation )
           {
           /*
           * Scan the current table for the key,   and if found
           * see if this key is a fork. If so follow it and
           * wait else return the extended key.
           */
           int index = 0;
           int branched = 0;
           while (  (  translation[index].expecting != '\0' ) ||
           (  translation[index].key != '\0' ) )
           {
           if (  translation[index].expecting == c )
           {
           /*
           * A branch is take if more keys are to come.
           */
           if (  translation[index].branch == 0 )
           return RTEMS_SHELL_KEYS_EXTENDED | translation[index].key;
           else
           {
           translation = translation[index].branch;
           branched = 1;
           break;
           }
           }
           index++;
           }
           /*
           * Who knows what these keys are,   just drop them.
           */
           if (  !branched )
           translation = 0;
           }
           else
           return c;
           }
           }
          }
          

libmisc/shell/shell_getprompt.c

       1  /*
           * Dynamically build the shell prompt
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: shell_getprompt.c,  v 1.2 2009/11/29 12:12:39 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <time.h>
          
          #include <rtems.h>
          #include <rtems/error.h>
          #include <rtems/libio.h>
          #include <rtems/libio_.h>
          #include <rtems/system.h>
          #include <rtems/shell.h>
          #include "internal.h"
          
          #include <string.h>
          #include <stdlib.h>
          #include <ctype.h>
          #include <sys/stat.h>
          #include <unistd.h>
          #include <errno.h>
          #include <pwd.h>
          
      34  void rtems_shell_get_prompt(  
           rtems_shell_env_t *shell_env,  
           char *prompt,  
           size_t size
           )
          {
           char curdir[256];
          
           /* XXX: show_prompt user adjustable */
           getcwd(  curdir,  sizeof(  curdir ) );
           snprintf(  prompt,   size - 1,   "%s%s[%s] %c ",  
           (  (  shell_env->taskname ) ? shell_env->taskname : "" ),  
           (  (  shell_env->taskname ) ? " " : "" ),  
           curdir,  
           geteuid(   )?'$':'#' );
          }

libmisc/shell/shell_makeargs.c

       1  /*
           * Split string into argc/argv style argument list
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: shell_makeargs.c,  v 1.9 2010/03/16 14:05:55 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          #include <ctype.h>
          
      21  int rtems_shell_make_args(  
           char *commandLine,  
           int *argc_p,  
           char **argv_p,  
           int max_args
           )
          {
           int argc;
           char *ch;
           int status = 0;
          
           argc = 0;
           ch = commandLine;
          
           while (   *ch  ) {
          
           while (   isspace(  (  unsigned char )*ch )  ) ch++;
          
           if (   *ch == '\0'  )
           break;
          
           if (   *ch == '"'  ) {
           argv_p[ argc ] = ++ch;
           while (   (   *ch != '\0'  ) && (   *ch != '"'  )  ) ch++;
           } else {
           argv_p[ argc ] = ch;
           while (   (   *ch != '\0'  ) && (   !isspace(  (  unsigned char )*ch )  )  ) ch++;
           }
          
           argc++;
          
           if (   *ch == '\0'  )
           break;
          
           *ch++ = '\0';
          
           if (   argc == (  max_args-1 )  ) {
           status = -1;
           break;
           }
          
          
           }
           argv_p[ argc ] = NULL;
           *argc_p = argc;
           return status;
          }
          

libmisc/shell/shell_script.c

       1  /*
           * Shell Script Invocation
           *
           * Pseudo-code from Chris Johns,   implemented and debugged
           * by Joel Sherrill.
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: shell_script.c,  v 1.13 2010/02/28 20:14:10 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          #include <errno.h>
          #include <inttypes.h>
          #include <sys/types.h>
          #include <unistd.h>
          #define __need_getopt_newlib
          #include <getopt.h>
          
          #include <rtems.h>
          #include <rtems/shell.h>
          #include <rtems/stringto.h>
          #include "internal.h"
          
      36  static void rtems_shell_joel_usage(  void )
          {
           printf(  
           "joel [args] where args may be:\n"
           " -o FILE output file (  default=stdout )\n"
           " -p PRIORITY task priority\n"
           " -s SIZE task stack size\n"
           " -t NAME task name\n"
            );
          }
          
      47  static int findOnPATH(  
           const char *userScriptName,  
           char *scriptFile
           )
          {
           int sc;
          
           /*
           * If the user script name starts with a / assume it is a fully
           * qualified path name and just use it.
           */
           if (   userScriptName[0] == '/'  ) {
           strcpy(   scriptFile,   userScriptName  );
           } else {
           /*
           * For now,   the provided name is just turned into a fully
           * qualified path name and used. There is no attempt to
           * search along a path for it.
           */
          
           /* XXX should use strncat but what is the limit? */
           getcwd(   scriptFile,   PATH_MAX  );
           strcat(   scriptFile,   "/"  );
           strcat(  
           scriptFile,  
           (   (  userScriptName[0] == '.' && userScriptName[1] == '/' ) ?
           &userScriptName[2] : userScriptName )
            );
           }
          
           sc = access(   scriptFile,   R_OK  );
           if (   sc  ) {
           return -1;
           }
          
           return 0;
          
          #if 0
           /*
           * Does the command (  argv[0] ) contain a path ?,   i.e. starts with
           * '.' or contains a '/'?
           */
           /* TODO: Add concept of PATH */
           if (  !contains_path ) {
           /* check PATH environment variable */
           for (  path_part = PATH; path_part; skip to ':' )
           {
           }
           if (  not found )
           return -1;
           }
          #endif
          }
          
     101  int rtems_shell_main_joel(  
           int argc,  
           char **argv
           );
          
     106  int rtems_shell_main_joel(  
           int argc,  
           char **argv
           )
          {
           unsigned long tmp;
           int option;
           int sc;
           int verbose = 0;
           char *taskName = "JOEL";
           uint32_t stackSize = RTEMS_MINIMUM_STACK_SIZE * 10;
           rtems_task_priority taskPriority = 20;
           char *outputFile = "stdout";
           rtems_status_code result;
           char scriptFile[PATH_MAX];
           struct getopt_data getopt_reent;
          
           memset(  &getopt_reent,   0,   sizeof(  getopt_data ) );
           while (   (  option = getopt_r(   argc,   argv,   "o:p:s:t:v",   &getopt_reent ) ) != -1  ) {
           switch (  (  char )option ) {
           case 'o':
           outputFile = getopt_reent.optarg;
           break;
           case 'p': {
           const char *s = getopt_reent.optarg;
          
           if (   rtems_string_to_unsigned_long(   s,   &tmp,   NULL,   0 )  ) {
           printf(   "Task Priority argument (  %s ) is not a number\n",   s  );
           return -1;
           }
           taskPriority = (  rtems_task_priority ) tmp;
           break;
           }
           case 's': {
           const char *s = getopt_reent.optarg;
          
           if (   rtems_string_to_unsigned_long(   s,   &tmp,   NULL,   0 )  ) {
           printf(   "Stack size argument (  %s ) is not a number\n",   s  );
           return -1;
           }
           stackSize = (  uint32_t ) tmp;
           break;
           }
           case 't':
           taskName = getopt_reent.optarg;
           break;
           case 'v':
           verbose = 1;
           break;
           case '?':
           default:
           rtems_shell_joel_usage(   );
           return -1;
           }
           }
          
           if (   verbose  ) {
           fprintf(   stderr,  
           "outputFile: %s\n"
           "taskPriority: %" PRId32 "\n"
           "stackSize: %" PRId32 "\n"
           "taskName: %s\n",  
           outputFile,  
           taskPriority,  
           stackSize,  
           taskName
            );
           }
          
           /*
           * Verify there is a script name past the end of the arguments.
           * Preincrement to skip program name.
           */
           if (   getopt_reent.optind >= argc  ) {
           fprintf(   stderr,   "Shell: No script to execute\n"  );
           return -1;
           }
          
           /*
           * Find script on the path.
           *
           * NOTE: It is terrible that this is done twice but it
           * seems to be the most expedient thing.
           */
           sc = findOnPATH(   argv[getopt_reent.optind],   scriptFile  );
           if (   sc  ) {
           fprintf(   stderr,   "%s: command not found\n",   argv[0]  );
           return -1;
           }
          
           /* fprintf(   stderr,   "SCRIPT: -%s-\n",   scriptFile  ); */
          
           /*
           * I assume that argv[optind...] will have the arguments to
           * the shell script. But that remains to be implemented.
           */
          
           /*
           * Run the script
           */
           result = rtems_shell_script(  
           taskName,   /* the name of the task */
           stackSize,   /* stack size */
           taskPriority,   /* task priority */
           scriptFile,   /* the script file */
           outputFile,   /* where to redirect the script */
           0,   /* run once and exit */
           1,   /* we will wait */
           verbose /* do we echo */
            );
           if (  result )
           return -1;
           return 0;
          }
          
          rtems_shell_cmd_t rtems_shell_JOEL_Command = {
           "joel",   /* name */
           "joel [args] SCRIPT",   /* usage */
           "misc",   /* topic */
           rtems_shell_main_joel,   /* command */
           NULL,   /* alias */
           NULL /* next */
          };
          
          /*
           * This is a helper function which takes a command as arguments
           * which has not been located as a built-in command and attempts
           * to find something in the filesystem with the same name that
           * appears to be a shell script.
           */
     236  int rtems_shell_script_file(  
           int argc __attribute__(  (  unused ) ),  
           char *argv[]
           )
          {
           #define FIRST_LINE_LENGTH 128
           #define SCRIPT_ARGV_LIMIT 32
           char scriptFile[PATH_MAX];
           char *scriptHead;
           char scriptHeadBuffer[FIRST_LINE_LENGTH];
           int sc;
           FILE *script;
           size_t length;
           int scriptArgc;
           char *scriptArgv[SCRIPT_ARGV_LIMIT];
          
           /*
           * Clear argv pointer array
           */
           for (   scriptArgc=0 ; scriptArgc<SCRIPT_ARGV_LIMIT ; scriptArgc++  )
           scriptArgv[scriptArgc] = NULL;
          
           /*
           * Find argv[0] on the path
           */
           sc = findOnPATH(   argv[0],   scriptFile  );
           if (   sc  ) {
           fprintf(   stderr,   "%s: command not found\n",   argv[0]  );
           return -1;
           }
          
           /*
           * Open the file so we can see if it looks like a script.
           */
           script = fopen(   scriptFile,   "r"  );
           if (   !script  ) {
           fprintf(   stderr,   "%s: Unable to open %s\n",   argv[0],   scriptFile  );
           return -1;
           }
          
           /*
           * Is the script OK to run?
           * Verify the current user has permission to execute it.
           *
           * NOTE: May not work on all file systems
           */
           sc = access(   scriptFile,   X_OK  );
           if (   sc  ) {
           fprintf(   stderr,   "Unable to execute %s\n",   scriptFile  );
           fclose(   script  );
           return -1;
           }
          
           /*
           * Try to read the first line from the potential script file
           */
           scriptHead = fgets(  scriptHeadBuffer,   FIRST_LINE_LENGTH,   script );
           if (   !scriptHead  ) {
           fprintf(  
           stderr,   "%s: Unable to read first line of %s\n",   argv[0],   scriptFile  );
           fclose(   script  );
           return -1;
           }
          
           fclose(  script );
          
           length = strnlen(  scriptHead,   FIRST_LINE_LENGTH );
           scriptHead[length - 1] = '\0';
          
           /* fprintf(   stderr,   "FIRST LINE: -%s-\n",   scriptHead  ); */
          
           /*
           * Verify the name of the "shell" is joel. This means
           * the line starts with "#! joel".
           */
           if (  strncmp(  "#! joel",   scriptHead,   7 ) != 0 ) {
           fprintf(   stderr,   "%s: Not a joel script %s\n",   argv[0],   scriptFile  );
           return -1;
           }
          
           /*
           * Do not worry about search path further. We have found the
           * script,   it is executable,   and we have successfully read the
           * first line and found out it is a script.
           */
          
           /*
           * Check for arguments in the first line of the script. This changes
           * how the shell task is run.
           */
          
           sc = rtems_shell_make_args(  
           &scriptHead[3],  
           &scriptArgc,  
           scriptArgv,  
           SCRIPT_ARGV_LIMIT - 1
            );
           if (   sc  ) {
           fprintf(  
           stderr,   "%s: Error parsing joel arguments %s\n",   argv[0],   scriptFile  );
           return -1;
           }
          
           scriptArgv[ scriptArgc++ ] = scriptFile;
          
           /*
           * TODO: How do we pass arguments from here to the script?
           * At this point,   it doesn't matter because we don't
           * have any way for a shell script to access them.
           */
           return rtems_shell_main_joel(   scriptArgc,   scriptArgv  );
          
           return 0;
          }

libmisc/shell/shellconfig.c

       1  /*
           * RTEMS Shell Command Set -- DEFAULT Configuration
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: shellconfig.c,  v 1.3 2008/08/21 12:29:01 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define CONFIGURE_SHELL_COMMANDS_INIT
          #define CONFIGURE_SHELL_COMMANDS_ALL
          
          #include <rtems/shellconfig.h>

libmisc/shell/utils-cp.c

       1  /* $NetBSD: utils.c,  v 1.29 2005/10/15 18:22:18 christos Exp $ */
          
          /*-
           * Copyright (  c ) 1991,   1993,   1994
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/cdefs.h>
          #if 0
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )utils.c 8.3 (  Berkeley ) 4/1/94";
          #else
      42  __RCSID(  "$NetBSD: utils.c,  v 1.29 2005/10/15 18:22:18 christos Exp $" );
          #endif
          #endif /* not lint */
          #endif
          
          #if 0
          #include <sys/mman.h>
          #endif
          #include <sys/param.h>
          #include <sys/stat.h>
          #include <sys/time.h>
          #include <utime.h>
          
          #include <err.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <fts.h>
          #include <limits.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <unistd.h>
          
          #include "extern-cp.h"
          
          #define lchmod chmod
          #define lchown chown
          
          #define cp_pct(  x,   y ) (  (  y == 0 ) ? 0 : (  int )(  100.0 * (  x ) / (  y ) ) )
          
          int
      73  set_utimes(  const char *file,   struct stat *fs )
          {
           struct utimbuf tv;
          
           tv.actime = fs->st_atime;
           tv.modtime = fs->st_mtime;
          
           if (  utime(  file,   &tv ) ) {
           warn(  "lutimes: %s",   file );
           return (  1 );
           }
           return (  0 );
          }
          
          int
      88  copy_file(  rtems_shell_cp_globals* cp_globals __attribute__(  (  unused ) ),   FTSENT *entp,   int dne )
          {
          #define MAX_READ max_read
           int max_read;
           char* buf;
           struct stat *fs;
           ssize_t wcount;
           size_t wresid;
           off_t wtotal;
           int ch,   checkch,   from_fd = 0,   rcount,   rval,   to_fd = 0;
           char *bufp;
          #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
           char *p;
          #endif
          
           fs = entp->fts_statp;
          
           max_read = fs->st_blksize;
           if (  max_read < (  8 * 1024 ) )
           max_read = 8 * 1024;
           buf = malloc (  max_read );
           if (  !buf )
           {
           warn(  "no memory" );
           return (  1 );
           }
          
           if (  (  from_fd = open(  entp->fts_path,   O_RDONLY,   0 ) ) == -1 ) {
           warn(  "%s",   entp->fts_path );
           (  void )free(  buf );
           return (  1 );
           }
          
           /*
           * If the file exists and we're interactive,   verify with the user.
           * If the file DNE,   set the mode to be the from file,   minus setuid
           * bits,   modified by the umask; arguably wrong,   but it makes copying
           * executables work right and it's been that way forever. (  The
           * other choice is 666 or'ed with the execute bits on the from file
           * modified by the umask. )
           */
           if (  !dne ) {
          #define YESNO "(  y/n [n] ) "
           if (  nflag ) {
           if (  vflag )
           printf(  "%s not overwritten\n",   to.p_path );
           (  void )close(  from_fd );
           (  void )free(  buf );
           return (  0 );
           } else if (  iflag ) {
           (  void )fprintf(  stderr,   "overwrite %s? %s",  
           to.p_path,   YESNO );
           checkch = ch = getchar(   );
           while (  ch != '\n' && ch != EOF )
           ch = getchar(   );
           if (  checkch != 'y' && checkch != 'Y' ) {
           (  void )close(  from_fd );
           (  void )free(  buf );
           (  void )fprintf(  stderr,   "not overwritten\n" );
           return (  1 );
           }
           }
          
           if (  fflag ) {
           /* remove existing destination file name,  
           * create a new file */
           (  void )unlink(  to.p_path );
           if (  !lflag )
           to_fd = open(  to.p_path,   O_WRONLY | O_TRUNC | O_CREAT,  
           fs->st_mode & ~(  S_ISUID | S_ISGID ) );
           } else {
           if (  !lflag )
           /* overwrite existing destination file name */
           to_fd = open(  to.p_path,   O_WRONLY | O_TRUNC,   0 );
           }
           } else {
           if (  !lflag )
           to_fd = open(  to.p_path,   O_WRONLY | O_TRUNC | O_CREAT,  
           fs->st_mode & ~(  S_ISUID | S_ISGID ) );
           }
          
           if (  to_fd == -1 ) {
           warn(  "%s",   to.p_path );
           (  void )close(  from_fd );
           (  void )free(  buf );
           return (  1 );
           }
          
           rval = 0;
          
           if (  !lflag ) {
           /*
           * Mmap and write if less than 8M (  the limit is so we don't totally
           * trash memory on big files. This is really a minor hack,   but it
           * wins some CPU back.
           */
          #ifdef CCJ_REMOVED_VM_AND_BUFFER_CACHE_SYNCHRONIZED
           if (  S_ISREG(  fs->st_mode ) && fs->st_size > 0 &&
           fs->st_size <= 8 * 1048576 ) {
           if (  (  p = mmap(  NULL,   (  size_t )fs->st_size,   PROT_READ,  
           MAP_SHARED,   from_fd,   (  off_t )0 ) ) == MAP_FAILED ) {
           warn(  "%s",   entp->fts_path );
           rval = 1;
           } else {
           wtotal = 0;
           for (  bufp = p,   wresid = fs->st_size; ;
           bufp += wcount,   wresid -= (  size_t )wcount ) {
           wcount = write(  to_fd,   bufp,   wresid );
           if (  wcount <= 0 )
           break;
           wtotal += wcount;
           if (  info ) {
           info = 0;
           (  void )fprintf(  stderr,  
           "%s -> %s %3d%%\n",  
           entp->fts_path,   to.p_path,  
           cp_pct(  wtotal,   fs->st_size ) );
           }
           if (  wcount >= (  ssize_t )wresid )
           break;
           }
           if (  wcount != (  ssize_t )wresid ) {
           warn(  "%s",   to.p_path );
           rval = 1;
           }
           /* Some systems don't unmap on close(  2 ). */
           if (  munmap(  p,   fs->st_size ) < 0 ) {
           warn(  "%s",   entp->fts_path );
           rval = 1;
           }
           }
           } else
          #endif
           {
           wtotal = 0;
           while (  (  rcount = read(  from_fd,   buf,   MAX_READ ) ) > 0 ) {
           for (  bufp = buf,   wresid = rcount; ;
           bufp += wcount,   wresid -= wcount ) {
           wcount = write(  to_fd,   bufp,   wresid );
           if (  wcount <= 0 )
           break;
           wtotal += wcount;
           if (  info ) {
           info = 0;
           (  void )fprintf(  stderr,  
           "%s -> %s %3d%%\n",  
           entp->fts_path,   to.p_path,  
           cp_pct(  wtotal,   fs->st_size ) );
           }
           if (  wcount >= (  ssize_t )wresid )
           break;
           }
           if (  wcount != (  ssize_t )wresid ) {
           warn(  "%s",   to.p_path );
           rval = 1;
           break;
           }
           }
           if (  rcount < 0 ) {
           warn(  "%s",   entp->fts_path );
           rval = 1;
           }
           }
           } else {
           if (  link(  entp->fts_path,   to.p_path ) ) {
           warn(  "%s",   to.p_path );
           rval = 1;
           }
           }
           (  void )close(  from_fd );
          
           /*
           * Don't remove the target even after an error. The target might
           * not be a regular file,   or its attributes might be important,  
           * or its contents might be irreplaceable. It would only be safe
           * to remove it if we created it and its length is 0.
           */
          
           if (  !lflag ) {
           if (  pflag && setfile(  cp_globals,   fs,   to_fd ) )
           rval = 1;
           if (  pflag && preserve_fd_acls(  from_fd,   to_fd ) != 0 )
           rval = 1;
           (  void )close(  from_fd );
           if (  close(  to_fd ) ) {
           warn(  "%s",   to.p_path );
           rval = 1;
           }
           }
           (  void )free(  buf );
           return (  rval );
          }
          
          int
     282  copy_link(  rtems_shell_cp_globals* cp_globals,   FTSENT *p,   int exists )
          {
           ssize_t len;
           char llink[PATH_MAX];
          
           if (  (  len = readlink(  p->fts_path,   llink,   sizeof(  llink ) - 1 ) ) == -1 ) {
           warn(  "readlink: %s",   p->fts_path );
           return (  1 );
           }
           llink[len] = '\0';
           if (  exists && unlink(  to.p_path ) ) {
           warn(  "unlink: %s",   to.p_path );
           return (  1 );
           }
           if (  symlink(  llink,   to.p_path ) ) {
           warn(  "symlink: %s",   llink );
           return (  1 );
           }
           return (  pflag ? setfile(  cp_globals,   p->fts_statp,   -1 ) : 0 );
          }
          
          int
     304  copy_fifo(  rtems_shell_cp_globals* cp_globals,   struct stat *from_stat,   int exists )
          {
           if (  exists && unlink(  to.p_path ) ) {
           warn(  "unlink: %s",   to.p_path );
           return (  1 );
           }
           if (  mkfifo(  to.p_path,   from_stat->st_mode ) ) {
           warn(  "mkfifo: %s",   to.p_path );
           return (  1 );
           }
           return (  pflag ? setfile(  cp_globals,   from_stat,   -1 ) : 0 );
          }
          
          int
     318  copy_special(  rtems_shell_cp_globals* cp_globals,   struct stat *from_stat,   int exists )
          {
           if (  exists && unlink(  to.p_path ) ) {
           warn(  "unlink: %s",   to.p_path );
           return (  1 );
           }
           if (  mknod(  to.p_path,   from_stat->st_mode,   from_stat->st_rdev ) ) {
           warn(  "mknod: %s",   to.p_path );
           return (  1 );
           }
           return (  pflag ? setfile(  cp_globals,   from_stat,   -1 ) : 0 );
          }
          
          #define TIMESPEC_TO_TIMEVAL(  tv,   ts ) { \
           (  tv )->tv_sec = *(  ts ); \
           (  tv )->tv_usec = 0; \
          }
          
          #define st_atimespec st_atime
          #define st_mtimespec st_mtime
     338  #define lutimes utimes
          
          int
          setfile(  rtems_shell_cp_globals* cp_globals,   struct stat *fs,   int fd )
          {
           static struct timeval tv[2];
           struct stat ts;
           int rval,   gotstat,   islink,   fdval;
          
           rval = 0;
           fdval = fd != -1;
           islink = !fdval && S_ISLNK(  fs->st_mode );
           fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX |
           S_IRWXU | S_IRWXG | S_IRWXO;
          
           TIMESPEC_TO_TIMEVAL(  &tv[0],   &fs->st_atimespec );
           TIMESPEC_TO_TIMEVAL(  &tv[1],   &fs->st_mtimespec );
          #if 0
           if (  islink ? lutimes(  to.p_path,   tv ) : utimes(  to.p_path,   tv ) ) {
           warn(  "%sutimes: %s",   islink ? "l" : "",   to.p_path );
           rval = 1;
           }
          #endif
           if (  fdval ? fstat(  fd,   &ts ) :
           (  islink ? lstat(  to.p_path,   &ts ) : stat(  to.p_path,   &ts ) ) )
           gotstat = 0;
           else {
           gotstat = 1;
           ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX |
           S_IRWXU | S_IRWXG | S_IRWXO;
           }
           /*
           * Changing the ownership probably won't succeed,   unless we're root
           * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting
           * the mode; current BSD behavior is to remove all setuid bits on
           * chown. If chown fails,   lose setuid/setgid bits.
           */
           if (  !gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid )
           if (  fdval ? fchown(  fd,   fs->st_uid,   fs->st_gid ) :
           (  islink ? lchown(  to.p_path,   fs->st_uid,   fs->st_gid ) :
           chown(  to.p_path,   fs->st_uid,   fs->st_gid ) ) ) {
           if (  errno != EPERM ) {
           warn(  "chown: %s",   to.p_path );
           rval = 1;
           }
           fs->st_mode &= ~(  S_ISUID | S_ISGID );
           }
          
           if (  !gotstat || fs->st_mode != ts.st_mode )
           if (  fdval ? fchmod(  fd,   fs->st_mode ) :
           (  islink ? lchmod(  to.p_path,   fs->st_mode ) :
           chmod(  to.p_path,   fs->st_mode ) ) ) {
           warn(  "chmod: %s",   to.p_path );
           rval = 1;
           }
          
          #if 0
           if (  !gotstat || fs->st_flags != ts.st_flags )
           if (  fdval ?
           fchflags(  fd,   fs->st_flags ) :
           (  islink ? (  errno = ENOSYS ) :
           chflags(  to.p_path,   fs->st_flags ) ) ) {
           warn(  "chflags: %s",   to.p_path );
           rval = 1;
           }
          #endif
          
           return (  rval );
     406  }
          
          int
          preserve_fd_acls(  int source_fd __attribute__(  (  unused ) ),   int dest_fd __attribute__(  (  unused ) ) )
          {
          #if 0
           struct acl *aclp;
           acl_t acl;
          
           if (  fpathconf(  source_fd,   _PC_ACL_EXTENDED ) != 1 ||
           fpathconf(  dest_fd,   _PC_ACL_EXTENDED ) != 1 )
           return (  0 );
           acl = acl_get_fd(  source_fd );
           if (  acl == NULL ) {
           warn(  "failed to get acl entries while setting %s",   to.p_path );
           return (  1 );
           }
           aclp = &acl->ats_acl;
           if (  aclp->acl_cnt == 3 )
           return (  0 );
           if (  acl_set_fd(  dest_fd,   acl ) < 0 ) {
           warn(  "failed to set acl entries for %s",   to.p_path );
           return (  1 );
           }
          #endif
           return (  0 );
     432  }
          
          int
          preserve_dir_acls(  struct stat *fs __attribute__(  (  unused ) ),   char *source_dir __attribute__(  (  unused ) ),   char *dest_dir __attribute__(  (  unused ) ) )
          {
          #if 0
           acl_t (  *aclgetf )(  const char *,   acl_type_t );
           int (  *aclsetf )(  const char *,   acl_type_t,   acl_t );
           struct acl *aclp;
           acl_t acl;
          
           if (  pathconf(  source_dir,   _PC_ACL_EXTENDED ) != 1 ||
           pathconf(  dest_dir,   _PC_ACL_EXTENDED ) != 1 )
           return (  0 );
           /*
           * If the file is a link we will not follow it
           */
           if (  S_ISLNK(  fs->st_mode ) ) {
           aclgetf = acl_get_link_np;
           aclsetf = acl_set_link_np;
           } else {
           aclgetf = acl_get_file;
           aclsetf = acl_set_file;
           }
           /*
           * Even if there is no ACL_TYPE_DEFAULT entry here,   a zero
           * size ACL will be returned. So it is not safe to simply
           * check the pointer to see if the default ACL is present.
           */
           acl = aclgetf(  source_dir,   ACL_TYPE_DEFAULT );
           if (  acl == NULL ) {
           warn(  "failed to get default acl entries on %s",  
           source_dir );
           return (  1 );
           }
           aclp = &acl->ats_acl;
           if (  aclp->acl_cnt != 0 && aclsetf(  dest_dir,  
           ACL_TYPE_DEFAULT,   acl ) < 0 ) {
           warn(  "failed to set default acl entries on %s",  
           dest_dir );
           return (  1 );
           }
           acl = aclgetf(  source_dir,   ACL_TYPE_ACCESS );
           if (  acl == NULL ) {
           warn(  "failed to get acl entries on %s",   source_dir );
           return (  1 );
           }
           aclp = &acl->ats_acl;
           if (  aclsetf(  dest_dir,   ACL_TYPE_ACCESS,   acl ) < 0 ) {
           warn(  "failed to set acl entries on %s",   dest_dir );
           return (  1 );
           }
          #endif
           return (  0 );
     486  }
          
          void
          usage(  rtems_shell_cp_globals* cp_globals )
          {
           (  void )fprintf(  stderr,   "%s\n%s\n",  
          "usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file target_file",  
          " cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file ... "
          "target_directory" );
           longjmp (  cp_globals->exit_jmp,   1 );
          }

libmisc/shell/utils-ls.c

       1  /* $NetBSD: util.c,  v 1.28 2005/06/17 14:36:16 hira Exp $ */
          
          /*
           * Copyright (  c ) 1989,   1993,   1994
           * The Regents of the University of California. All rights reserved.
           *
           * This code is derived from software contributed to Berkeley by
           * Michael Fischbein.
           *
           * 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. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if 0
          #include <sys/cdefs.h>
          #ifndef lint
          #if 0
          static char sccsid[] = "@(  # )util.c 8.5 (  Berkeley ) 4/28/95";
          #else
      45  __RCSID(  "$NetBSD: util.c,  v 1.28 2005/06/17 14:36:16 hira Exp $" );
          #endif
          #endif /* not lint */
          #endif
          
          #include <sys/types.h>
          #include <sys/stat.h>
          
          #include <ctype.h>
          #include <err.h>
          #include <fts.h>
          #include <limits.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <vis.h>
          
          #include "extern-ls.h"
          
          #define SIZE_T_MAX 255
          
          int
      67  safe_print(  rtems_shell_ls_globals* globals,   const char *src )
          {
           size_t len;
           char *name;
           int flags;
          
           flags = VIS_NL | VIS_OCTAL;
           if (  f_octal_escape )
           flags |= VIS_CSTYLE;
          
           len = strlen(  src );
           if (  len != 0 && SIZE_T_MAX/len <= 4 ) {
           errx(  exit_jump,   EXIT_FAILURE,   "%s: name too long",   src );
           /* NOTREACHED */
           }
          
           name = (  char * )malloc(  4*len+1 );
           if (  name != NULL ) {
           len = strvis(  name,   src,   flags );
           printf(  "%s",   name );
           free(  name );
           return len;
           } else
           errx(  exit_jump,   EXIT_FAILURE,   "out of memory!" );
           /* NOTREACHED */
          }
          
          int
      95  printescaped(  rtems_shell_ls_globals* globals __attribute__(  (  unused ) ),   const char *src )
          {
           unsigned char c;
           int n;
          
           for (  n = 0; (  c = *src ) != '\0'; ++src,   ++n )
           if (  isprint(  c ) )
           (  void )putchar(  c );
           else
           (  void )putchar(  '?' );
           return n;
          }
          
          void
     109  usage(  rtems_shell_ls_globals* globals )
          {
          
           (  void )fprintf(  stderr,  
           "usage: %s [-AaBbCcdFfghikLlmnopqRrSsTtuWwx1] [file ...]\n",  
           "ls" );
           exit(  EXIT_FAILURE );
           /* NOTREACHED */
          }

libmisc/shell/verr.c

       1  /* $NetBSD: verr.c,  v 1.13 2005/09/13 01:44:09 christos Exp $ */
          
          /*-
           * Copyright (  c ) 1993
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_NBTOOL_CONFIG_H
          #include "nbtool_config.h"
          #endif
          
          #include <sys/cdefs.h>
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          #if 0
          static char sccsid[] = "@(  # )err.c 8.1 (  Berkeley ) 6/4/93";
          #else
      45  __RCSID(  "$NetBSD: verr.c,  v 1.13 2005/09/13 01:44:09 christos Exp $" );
          #endif
          #endif /* LIBC_SCCS and not lint */
          
          #include <err.h>
          #include <errno.h>
          #include <stdarg.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          
          #ifdef __weak_alias
      57  __weak_alias(  verr,   _verr )
          #endif
          
          __dead void
          verr(  jmp_buf* exit_jmp,   int eval __attribute__(  (  unused ) ),   const char *fmt,   _BSD_VA_LIST_ ap )
          {
           int sverrno;
          
           sverrno = errno;
          #if 0
           (  void )fprintf(  stderr,   "%s: ",   getprogname(   ) );
          #endif
           if (  fmt != NULL ) {
           (  void )vfprintf(  stdout,   fmt,   ap );
           (  void )fprintf(  stdout,   ": " );
           }
           (  void )fprintf(  stdout,   "%s\n",   strerror(  sverrno ) );
           longjmp (  *exit_jmp,   1 );
          }

libmisc/shell/verrx.c

       1  /* $NetBSD: verrx.c,  v 1.13 2005/09/13 01:44:09 christos Exp $ */
          
          /*-
           * Copyright (  c ) 1993
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_NBTOOL_CONFIG_H
          #include "nbtool_config.h"
          #endif
          
          #include <sys/cdefs.h>
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          #if 0
          static char sccsid[] = "@(  # )err.c 8.1 (  Berkeley ) 6/4/93";
          #else
      45  __RCSID(  "$NetBSD: verrx.c,  v 1.13 2005/09/13 01:44:09 christos Exp $" );
          #endif
          #endif /* LIBC_SCCS and not lint */
          
          #include <err.h>
          #include <stdarg.h>
          #include <stdio.h>
          #include <stdlib.h>
          
          #ifdef __weak_alias
      55  __weak_alias(  verrx,   _verrx )
          #endif
          
          __dead void
          verrx(  jmp_buf* exit_jmp,   int eval __attribute__(  (  unused ) ),   const char *fmt,   _BSD_VA_LIST_ ap )
          {
          #if 0
           (  void )fprintf(  stderr,   "%s: ",   getprogname(   ) );
          #endif
           if (  fmt != NULL )
           (  void )vfprintf(  stdout,   fmt,   ap );
           (  void )fprintf(  stdout,   "\n" );
           longjmp (  *exit_jmp,   1 );
          }

libmisc/shell/vis.c

          /* $NetBSD: vis.c,  v 1.33 2005/05/28 13:11:14 lukem Exp $ */
          
          /*-
           * Copyright (  c ) 1989,   1993
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          /*-
           * Copyright (  c ) 1999,   2005 The NetBSD Foundation,   Inc.
           * 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.
           * 3. All advertising materials mentioning features or use of this software
           * must display the following acknowledgement:
           * This product includes software developed by the NetBSD
           * Foundation,   Inc. and its contributors.
           * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION,   INC. 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 FOUNDATION 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #define _DIAGASSERT(  a )
          
          #if 0
          #include <sys/cdefs.h>
          #if defined(  LIBC_SCCS ) && !defined(  lint )
      74  __RCSID(  "$NetBSD: vis.c,  v 1.33 2005/05/28 13:11:14 lukem Exp $" );
          #endif /* LIBC_SCCS and not lint */
          #endif
          
          #include <sys/types.h>
          
          #include <vis.h>
          #include <stdlib.h>
          
          #if !HAVE_VIS || !HAVE_SVIS
          #include <ctype.h>
          #include <limits.h>
          #include <stdio.h>
          #include <string.h>
          
          #undef BELL
          #define BELL '\a'
          
          #define isoctal(  c ) (  (  (  u_char )(  c ) ) >= '0' && (  (  u_char )(  c ) ) <= '7' )
          #define iswhite(  c ) (  c == ' ' || c == '\t' || c == '\n' )
          #define issafe(  c ) (  c == '\b' || c == BELL || c == '\r' )
          #define xtoa(  c ) "0123456789abcdef"[c]
          
          #define MAXEXTRAS 5
          
          
          #define MAKEEXTRALIST(  flag,   extra,   orig ) \
          do { \
           const char *o = orig; \
           char *e; \
           while (  *o++ ) \
           continue; \
           extra = malloc(  (  size_t )(  (  o - orig ) + MAXEXTRAS ) ); \
           if (  !extra ) break; \
           for (  o = orig,   e = extra; (  *e++ = *o++ ) != '\0'; ) \
           continue; \
           e--; \
           if (  flag & VIS_SP ) *e++ = ' '; \
           if (  flag & VIS_TAB ) *e++ = '\t'; \
           if (  flag & VIS_NL ) *e++ = '\n'; \
           if (  (  flag & VIS_NOSLASH ) == 0 ) *e++ = '\\'; \
           *e = '\0'; \
          } while (  /*CONSTCOND*/0 )
          
          
          /*
           * This is HVIS,   the macro of vis used to HTTP style (  RFC 1808 )
           */
          #define HVIS(  dst,   c,   flag,   nextc,   extra ) \
          do \
           if (  !isascii(  c ) || !isalnum(  c ) || strchr(  "$-_.+!*'(   ),  ",   c ) != NULL ) { \
           *dst++ = '%'; \
           *dst++ = xtoa(  (  (  unsigned int )c >> 4 ) & 0xf ); \
           *dst++ = xtoa(  (  unsigned int )c & 0xf ); \
           } else { \
           SVIS(  dst,   c,   flag,   nextc,   extra ); \
           } \
          while (  /*CONSTCOND*/0 )
          
          /*
           * This is SVIS,   the central macro of vis.
           * dst: Pointer to the destination buffer
           * c: Character to encode
           * flag: Flag word
           * nextc: The character following 'c'
           * extra: Pointer to the list of extra characters to be
           * backslash-protected.
           */
          #define SVIS(  dst,   c,   flag,   nextc,   extra ) \
          do { \
           int isextra; \
           isextra = strchr(  extra,   c ) != NULL; \
           if (  !isextra && isascii(  c ) && (  isgraph(  c ) || iswhite(  c ) || \
           (  (  flag & VIS_SAFE ) && issafe(  c ) ) ) ) { \
           *dst++ = c; \
           break; \
           } \
           if (  flag & VIS_CSTYLE ) { \
           switch (  c ) { \
           case '\n': \
           *dst++ = '\\'; *dst++ = 'n'; \
           continue; \
           case '\r': \
           *dst++ = '\\'; *dst++ = 'r'; \
           continue; \
           case '\b': \
           *dst++ = '\\'; *dst++ = 'b'; \
           continue; \
           case BELL: \
           *dst++ = '\\'; *dst++ = 'a'; \
           continue; \
           case '\v': \
           *dst++ = '\\'; *dst++ = 'v'; \
           continue; \
           case '\t': \
           *dst++ = '\\'; *dst++ = 't'; \
           continue; \
           case '\f': \
           *dst++ = '\\'; *dst++ = 'f'; \
           continue; \
           case ' ': \
           *dst++ = '\\'; *dst++ = 's'; \
           continue; \
           case '\0': \
           *dst++ = '\\'; *dst++ = '0'; \
           if (  isoctal(  nextc ) ) { \
           *dst++ = '0'; \
           *dst++ = '0'; \
           } \
           continue; \
           default: \
           if (  isgraph(  c ) ) { \
           *dst++ = '\\'; *dst++ = c; \
           continue; \
           } \
           } \
           } \
           if (  isextra || (  (  c & 0177 ) == ' ' ) || (  flag & VIS_OCTAL ) ) { \
           *dst++ = '\\'; \
           *dst++ = (  u_char )(  (  (  u_int32_t )(  u_char )c >> 6 ) & 03 ) + '0'; \
           *dst++ = (  u_char )(  (  (  u_int32_t )(  u_char )c >> 3 ) & 07 ) + '0'; \
           *dst++ = (  c & 07 ) + '0'; \
           } else { \
           if (  (  flag & VIS_NOSLASH ) == 0 ) *dst++ = '\\'; \
           if (  c & 0200 ) { \
           c &= 0177; *dst++ = 'M'; \
           } \
           if (  iscntrl(  c ) ) { \
           *dst++ = '^'; \
           if (  c == 0177 ) \
           *dst++ = '?'; \
           else \
           *dst++ = c + '@'; \
           } else { \
           *dst++ = '-'; *dst++ = c; \
           } \
           } \
          } while (  /*CONSTCOND*/0 )
          
          
          /*
           * svis - visually encode characters,   also encoding the characters
           * pointed to by `extra'
           */
          char *
          svis(  char *dst,   int c,   int flag,   int nextc,   const char *extra )
          {
           char *nextra = NULL;
          
           _DIAGASSERT(  dst != NULL );
           _DIAGASSERT(  extra != NULL );
           MAKEEXTRALIST(  flag,   nextra,   extra );
           if (  !nextra ) {
           *dst = '\0'; /* can't create nextra,   return "" */
           return dst;
           }
           if (  flag & VIS_HTTPSTYLE )
           HVIS(  dst,   c,   flag,   nextc,   nextra );
           else
           SVIS(  dst,   c,   flag,   nextc,   nextra );
           free(  nextra );
           *dst = '\0';
           return dst;
          }
          
          
          /*
           * strsvis,   strsvisx - visually encode characters from src into dst
           *
           * Extra is a pointer to a \0-terminated list of characters to
           * be encoded,   too. These functions are useful e. g. to
           * encode strings in such a way so that they are not interpreted
           * by a shell.
           *
           * Dst must be 4 times the size of src to account for possible
           * expansion. The length of dst,   not including the trailing NULL,  
           * is returned.
           *
           * Strsvisx encodes exactly len bytes from src into dst.
           * This is useful for encoding a block of data.
           */
          int
          strsvis(  char *dst,   const char *csrc,   int flag,   const char *extra )
          {
           int c;
           char *start;
           char *nextra = NULL;
           const unsigned char *src = (  const unsigned char * )csrc;
          
           _DIAGASSERT(  dst != NULL );
           _DIAGASSERT(  src != NULL );
           _DIAGASSERT(  extra != NULL );
           MAKEEXTRALIST(  flag,   nextra,   extra );
           if (  !nextra ) {
           *dst = '\0'; /* can't create nextra,   return "" */
           return 0;
           }
           if (  flag & VIS_HTTPSTYLE ) {
           for (  start = dst; (  c = *src++ ) != '\0'; /* empty */ )
           HVIS(  dst,   c,   flag,   *src,   nextra );
           } else {
           for (  start = dst; (  c = *src++ ) != '\0'; /* empty */ )
           SVIS(  dst,   c,   flag,   *src,   nextra );
           }
           free(  nextra );
           *dst = '\0';
           return (  dst - start );
          }
          
          
          int
          strsvisx(  char *dst,   const char *csrc,   size_t len,   int flag,   const char *extra )
          {
           unsigned char c;
           char *start;
           char *nextra = NULL;
           const unsigned char *src = (  const unsigned char * )csrc;
          
           _DIAGASSERT(  dst != NULL );
           _DIAGASSERT(  src != NULL );
           _DIAGASSERT(  extra != NULL );
           MAKEEXTRALIST(  flag,   nextra,   extra );
           if (  ! nextra ) {
           *dst = '\0'; /* can't create nextra,   return "" */
           return 0;
           }
          
           if (  flag & VIS_HTTPSTYLE ) {
           for (  start = dst; len > 0; len-- ) {
           c = *src++;
           HVIS(  dst,   c,   flag,   len ? *src : '\0',   nextra );
           }
           } else {
           for (  start = dst; len > 0; len-- ) {
           c = *src++;
           SVIS(  dst,   c,   flag,   len ? *src : '\0',   nextra );
           }
           }
           free(  nextra );
           *dst = '\0';
           return (  dst - start );
          }
          #endif
          
          #if !HAVE_VIS
          /*
           * vis - visually encode characters
           */
          char *
          vis(  char *dst,   int c,   int flag,   int nextc )
          {
           char *extra = NULL;
           unsigned char uc = (  unsigned char )c;
          
           _DIAGASSERT(  dst != NULL );
          
           MAKEEXTRALIST(  flag,   extra,   "" );
           if (  ! extra ) {
           *dst = '\0'; /* can't create extra,   return "" */
           return dst;
           }
           if (  flag & VIS_HTTPSTYLE )
           HVIS(  dst,   uc,   flag,   nextc,   extra );
           else
           SVIS(  dst,   uc,   flag,   nextc,   extra );
           free(  extra );
           *dst = '\0';
           return dst;
          }
          
          
          /*
           * strvis,   strvisx - visually encode characters from src into dst
           *
           * Dst must be 4 times the size of src to account for possible
           * expansion. The length of dst,   not including the trailing NULL,  
           * is returned.
           *
           * Strvisx encodes exactly len bytes from src into dst.
           * This is useful for encoding a block of data.
           */
          int
          strvis(  char *dst,   const char *src,   int flag )
          {
           char *extra = NULL;
           int rv;
          
           MAKEEXTRALIST(  flag,   extra,   "" );
           if (  !extra ) {
           *dst = '\0'; /* can't create extra,   return "" */
           return 0;
           }
           rv = strsvis(  dst,   src,   flag,   extra );
           free(  extra );
           return rv;
          }
          
          
          int
          strvisx(  char *dst,   const char *src,   size_t len,   int flag )
          {
           char *extra = NULL;
           int rv;
          
           MAKEEXTRALIST(  flag,   extra,   "" );
           if (  !extra ) {
           *dst = '\0'; /* can't create extra,   return "" */
           return 0;
           }
           rv = strsvisx(  dst,   src,   len,   flag,   extra );
           free(  extra );
           return rv;
          }
          #endif

libmisc/shell/vwarn.c

       1  /* $NetBSD: vwarn.c,  v 1.13 2005/09/13 01:44:09 christos Exp $ */
          
          /*-
           * Copyright (  c ) 1993
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_NBTOOL_CONFIG_H
          #include "nbtool_config.h"
          #endif
          
          #include <sys/cdefs.h>
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          #if 0
          static char sccsid[] = "@(  # )err.c 8.1 (  Berkeley ) 6/4/93";
          #else
      45  __RCSID(  "$NetBSD: vwarn.c,  v 1.13 2005/09/13 01:44:09 christos Exp $" );
          #endif
          #endif /* LIBC_SCCS and not lint */
          
          #include <err.h>
          #include <errno.h>
          #include <stdarg.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          
          #ifdef __weak_alias
      57  __weak_alias(  vwarn,   _vwarn )
          #endif
          
          void
          vwarn(  const char *fmt,   _BSD_VA_LIST_ ap )
          {
           int sverrno;
          
           sverrno = errno;
          #if 0
           (  void )fprintf(  stderr,   "%s: ",   getprogname(   ) );
          #endif
           if (  fmt != NULL ) {
           (  void )vfprintf(  stdout,   fmt,   ap );
           (  void )fprintf(  stdout,   ": " );
           }
           (  void )fprintf(  stdout,   "%s\n",   strerror(  sverrno ) );
          }

libmisc/shell/vwarnx.c

       1  /* $NetBSD: vwarnx.c,  v 1.13 2005/09/13 01:44:09 christos Exp $ */
          
          /*-
           * Copyright (  c ) 1993
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_NBTOOL_CONFIG_H
          #include "nbtool_config.h"
          #endif
          
          #include <sys/cdefs.h>
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          #if 0
          static char sccsid[] = "@(  # )err.c 8.1 (  Berkeley ) 6/4/93";
          #else
      45  __RCSID(  "$NetBSD: vwarnx.c,  v 1.13 2005/09/13 01:44:09 christos Exp $" );
          #endif
          #endif /* LIBC_SCCS and not lint */
          
          #include <err.h>
          #include <stdarg.h>
          #include <stdio.h>
          #include <stdlib.h>
          
          #ifdef __weak_alias
      55  __weak_alias(  vwarnx,   _vwarnx )
          #endif
          
          void
          vwarnx(  const char *fmt,   _BSD_VA_LIST_ ap )
          {
          #if 0
           (  void )fprintf(  stderr,   "%s: ",   getprogname(   ) );
          #endif
           if (  fmt != NULL )
           (  void )vfprintf(  stdout,   fmt,   ap );
           (  void )fprintf(  stdout,   "\n" );
          }

libmisc/shell/warn.c

       1  /* $NetBSD: warn.c,  v 1.13 2005/09/13 13:51:50 christos Exp $ */
          
          /*-
           * Copyright (  c ) 1993
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_NBTOOL_CONFIG_H
          #include "nbtool_config.h"
          #endif
          
          #include <sys/cdefs.h>
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          #if 0
          static char sccsid[] = "@(  # )err.c 8.1 (  Berkeley ) 6/4/93";
          #else
      45  __RCSID(  "$NetBSD: warn.c,  v 1.13 2005/09/13 13:51:50 christos Exp $" );
          #endif
          #endif /* LIBC_SCCS and not lint */
          
          #include <err.h>
          #include <stdarg.h>
          
          #ifdef __weak_alias
      53  __weak_alias(  warn,   _warn )
          #endif
          
          void
          warn(  const char *fmt,   ... )
          {
           va_list ap;
          
           va_start(  ap,   fmt );
           vwarn(  fmt,   ap );
           va_end(  ap );
          }

libmisc/shell/warnx.c

       1  /* $NetBSD: warnx.c,  v 1.13 2005/09/13 13:51:50 christos Exp $ */
          
          /*-
           * Copyright (  c ) 1993
           * The Regents of the University of California. 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.
           * 3. 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.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_NBTOOL_CONFIG_H
          #include "nbtool_config.h"
          #endif
          
          #include <sys/cdefs.h>
          #if defined(  LIBC_SCCS ) && !defined(  lint )
          #if 0
          static char sccsid[] = "@(  # )err.c 8.1 (  Berkeley ) 6/4/93";
          #else
      45  __RCSID(  "$NetBSD: warnx.c,  v 1.13 2005/09/13 13:51:50 christos Exp $" );
          #endif
          #endif /* LIBC_SCCS and not lint */
          
          #include <err.h>
          #include <stdarg.h>
          
          #ifdef __weak_alias
      53  __weak_alias(  warnx,   _warnx )
          #endif
          
          void
          warnx(  const char *fmt,   ... )
          {
           va_list ap;
          
           va_start(  ap,   fmt );
           vwarnx(  fmt,   ap );
           va_end(  ap );
          }

libmisc/shell/write_file.c

       1  /*
           *
           * Write buffer to a file
           *
           * Author:
           *
           * WORK: fernando.ruiz@ctv.es
           * HOME: correo@fernando-ruiz.com
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: write_file.c,  v 1.3 2008/03/05 02:49:35 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <unistd.h>
          #include <string.h>
          
      25  void rtems_shell_write_file(  
           const char *name,  
           const char *content
           )
          {
           FILE * fd;
          
           fd = fopen(  name,  "w" );
           if (   !fd  ) {
           fprintf(   stderr,   "Unable to write %s\n",   name  );
           }
          
           if (  fd ) {
           fwrite(  content,  1,  strlen(  content ),  fd );
           fclose(  fd );
           }
          }
          
          

libmisc/stackchk/check.c

       1  /*
           * Stack Overflow Check User Extension Set
           *
           * NOTE: This extension set automatically determines at
           * initialization time whether the stack for this
           * CPU grows up or down and installs the correct
           * extension routines for that direction.
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: check.c,  v 1.72 2010/08/25 20:29:41 joel Exp $
           *
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <inttypes.h>
          
          /*
           * The stack dump information may be printed by a "fatal" extension.
           * Fatal extensions only get called via rtems_fatal_error_occurred(   )
           * and not when rtems_shutdown_executive(   ) is called.
           * When that happens,   this #define should be deleted and all the code
           * it marks.
           */
          #define DONT_USE_FATAL_EXTENSION
          
          #include <string.h>
          #include <stdlib.h>
          
          #include <rtems/bspIo.h>
          #include <rtems/stackchk.h>
          #include "internal.h"
          
          /*
           * Variable to indicate when the stack checker has been initialized.
           */
          static int Stack_check_Initialized = 0;
          
          /*
           * The "magic pattern" used to mark the end of the stack.
           */
          Stack_check_Control Stack_check_Pattern;
          
          /*
           * Helper function to report if the actual stack pointer is in range.
           *
           * NOTE: This uses a GCC specific method.
           */
      58  static inline bool Stack_check_Frame_pointer_in_range(  
           Stack_Control *the_stack
           )
          {
           #if defined(  __GNUC__ )
           void *sp = __builtin_frame_address(  0 );
          
           if (   sp < the_stack->area  ) {
           return false;
           }
           if (   sp > (  the_stack->area + the_stack->size )  ) {
           return false;
           }
           #else
           #error "How do I check stack bounds on a non-GNU compiler?"
           #endif
           return true;
          }
          
          /*
           * Where the pattern goes in the stack area is dependent upon
           * whether the stack grow to the high or low area of the memory.
           */
          #if (  CPU_STACK_GROWS_UP == TRUE )
           #define Stack_check_Get_pattern_area(   _the_stack  ) \
           (  (  Stack_check_Control * ) (  (  char * )(  _the_stack )->area + \
           (  _the_stack )->size - sizeof(   Stack_check_Control  )  ) )
          
           #define Stack_check_Calculate_used(   _low,   _size,   _high_water  ) \
           (  (  char * )(  _high_water ) - (  char * )(  _low ) )
          
           #define Stack_check_usable_stack_start(  _the_stack ) \
           (  (  _the_stack )->area )
          
          #else
           /*
           * We need this magic offset because during a task delete the task stack will
           * be freed before we enter the task switch extension which checks the stack.
           * The task stack free operation will write the next and previous pointers
           * for the free list into this area.
           */
           #define Stack_check_Get_pattern_area(   _the_stack  ) \
           (  (  Stack_check_Control * ) (  (  char * )(  _the_stack )->area \
           + sizeof(  Heap_Block ) - HEAP_BLOCK_HEADER_SIZE ) )
          
           #define Stack_check_Calculate_used(   _low,   _size,   _high_water ) \
           (   (  (  char * )(  _low ) + (  _size ) ) - (  char * )(  _high_water )  )
          
           #define Stack_check_usable_stack_start(  _the_stack ) \
           (  (  char * )(  _the_stack )->area + sizeof(  Stack_check_Control ) )
          
          #endif
          
          /*
           * The assumption is that if the pattern gets overwritten,   the task
           * is too close. This defines the usable stack memory.
           */
          #define Stack_check_usable_stack_size(  _the_stack ) \
           (  (  _the_stack )->size - sizeof(  Stack_check_Control ) )
          
          #if (  CPU_ALLOCATE_INTERRUPT_STACK == TRUE )
           /*
           * Did RTEMS allocate the interrupt stack? If so,   put it in
           * Stack_Control format.
           */
           Stack_Control Stack_check_Interrupt_stack;
          #endif
          
     126  /*
           * Fill an entire stack area with BYTE_PATTERN. This will be used
           * to check for amount of actual stack used.
           */
          #define Stack_check_Dope_stack(  _stack ) \
           memset(  (  _stack )->area,   BYTE_PATTERN,   (  _stack )->size )
          
          /*
           * Stack_check_Initialize
           */
          void Stack_check_Initialize(   void  )
          {
           int i;
           uint32_t *p;
           static uint32_t pattern[ 4 ] = {
           0xFEEDF00D,   0x0BAD0D06,   /* FEED FOOD to BAD DOG */
           0xDEADF00D,   0x600D0D06 /* DEAD FOOD but GOOD DOG */
           };
          
           if (   Stack_check_Initialized  )
           return;
          
           /*
           * Dope the pattern and fill areas
           */
           p = Stack_check_Pattern.pattern;
           for (   i = 0; i < PATTERN_SIZE_WORDS; i++  ) {
           p[i] = pattern[ i%4 ];
           }
          
           /*
           * If appropriate,   setup the interrupt stack for high water testing
           * also.
           */
           #if (  CPU_ALLOCATE_INTERRUPT_STACK == TRUE )
           if (  _CPU_Interrupt_stack_low && _CPU_Interrupt_stack_high ) {
           Stack_check_Interrupt_stack.area = _CPU_Interrupt_stack_low;
           Stack_check_Interrupt_stack.size = (  char * ) _CPU_Interrupt_stack_high -
           (  char * ) _CPU_Interrupt_stack_low;
     165   Stack_check_Dope_stack(  &Stack_check_Interrupt_stack );
           }
           #endif
          
           Stack_check_Initialized = 1;
          }
          
          /*
           * rtems_stack_checker_create_extension
           */
          bool rtems_stack_checker_create_extension(  
           Thread_Control *running __attribute__(  (  unused ) ),  
           Thread_Control *the_thread
           )
          {
           Stack_check_Initialize(   );
     181  
           if (  the_thread )
           Stack_check_Dope_stack(  &the_thread->Start.Initial_stack );
          
           return true;
          }
          
          /*
           * rtems_stack_checker_Begin_extension
           */
          void rtems_stack_checker_begin_extension(  
           Thread_Control *the_thread
           )
          {
           Stack_check_Control *the_pattern;
          
           if (   the_thread->Object.id == 0  ) /* skip system tasks */
           return;
          
           the_pattern = Stack_check_Get_pattern_area(  &the_thread->Start.Initial_stack );
          
           *the_pattern = Stack_check_Pattern;
          }
     204  
          /*
           * Stack_check_report_blown_task
           *
           * Report a blown stack. Needs to be a separate routine
     209   * so that interrupt handlers can use this too.
           *
           * NOTE: The system is in a questionable state... we may not get
           * the following message out.
           */
          void Stack_check_report_blown_task(  
           Thread_Control *running,  
           bool pattern_ok
           ) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
          
          void Stack_check_report_blown_task(  Thread_Control *running,   bool pattern_ok )
          {
           Stack_Control *stack = &running->Start.Initial_stack;
           void *pattern_area = Stack_check_Get_pattern_area(  stack );
           char name [32];
          
           printk(  "BLOWN STACK!!!\n" );
           printk(  "task control block: 0x%08" PRIxPTR "\n",   running );
           printk(  "task ID: 0x%08lx\n",   (  unsigned long ) running->Object.id );
           printk(  
           "task name: 0x%08" PRIx32 "\n",  
           running->Object.name.name_u32
            );
           printk(  
           "task name string: %s\n",  
           rtems_object_get_name(  running->Object.id,   sizeof(  name ),   name )
            );
           printk(  
           "task stack area (  %lu Bytes ): 0x%08" PRIxPTR " .. 0x%08" PRIxPTR "\n",  
           (  unsigned long ) stack->size,  
           stack->area,  
           (  (  char * ) stack->area + stack->size )
            );
           if (  !pattern_ok ) {
           printk(  
           "damaged pattern area (  %lu Bytes ): 0x%08" PRIxPTR " .. 0x%08" PRIxPTR "\n",  
           (  unsigned long ) PATTERN_SIZE_BYTES,  
           pattern_area,  
           (  pattern_area + PATTERN_SIZE_BYTES )
            );
           }
          
           #if defined(  RTEMS_MULTIPROCESSING )
           if (  rtems_configuration_get_user_multiprocessing_table(   ) ) {
           printk(  
           "node: 0x%08" PRIxPTR "\n",  
           rtems_configuration_get_user_multiprocessing_table(   )->node
     256    );
           }
           #endif
          
           rtems_fatal_error_occurred(  0x81 );
          }
          
          /*
           * rtems_stack_checker_switch_extension
           */
          void rtems_stack_checker_switch_extension(  
           Thread_Control *running __attribute__(  (  unused ) ),  
           Thread_Control *heir __attribute__(  (  unused ) )
           )
          {
           Stack_Control *the_stack = &running->Start.Initial_stack;
           void *pattern;
           bool sp_ok;
           bool pattern_ok = true;
          
           pattern = (  void * ) Stack_check_Get_pattern_area(  the_stack )->pattern;
          
           /*
           * Check for an out of bounds stack pointer or an overwrite
           */
           sp_ok = Stack_check_Frame_pointer_in_range(   the_stack  );
          
           pattern_ok = (  !memcmp(   pattern,  
     284   (  void * ) Stack_check_Pattern.pattern,   PATTERN_SIZE_BYTES ) );
          
           if (   !sp_ok || !pattern_ok  ) {
           Stack_check_report_blown_task(   running,   pattern_ok  );
           }
          }
          
          /*
           * Check if blown
           */
          bool rtems_stack_checker_is_blown(   void  )
          {
           Stack_Control *the_stack = &_Thread_Executing->Start.Initial_stack;
           bool sp_ok;
           bool pattern_ok = true;
          
           /*
           * Check for an out of bounds stack pointer
           */
          
           sp_ok = Stack_check_Frame_pointer_in_range(   the_stack  );
          
           /*
           * The stack checker must be initialized before the pattern is there
           * to check.
           */
           if (   Stack_check_Initialized  ) {
           pattern_ok = (  !memcmp(  
           (  void * ) Stack_check_Get_pattern_area(  the_stack )->pattern,  
           (  void * ) Stack_check_Pattern.pattern,  
           PATTERN_SIZE_BYTES
            ) );
           }
          
          
           /*
           * Let's report as much as we can.
           */
           if (   !sp_ok || !pattern_ok  ) {
           Stack_check_report_blown_task(   _Thread_Executing,   pattern_ok  );
           /* DOES NOT RETURN */
           }
     326  
           /*
           * The Stack Pointer and the Pattern Area are OK so return false.
           */
           return false;
          }
          
          /*
           * Stack_check_find_high_water_mark
           */
          static inline void *Stack_check_find_high_water_mark(  
           const void *s,  
           size_t n
           )
          {
           const uint32_t *base,   *ebase;
           uint32_t length;
          
           base = s;
           length = n/4;
          
           #if (   CPU_STACK_GROWS_UP == TRUE  )
           /*
           * start at higher memory and find first word that does not
           * match pattern
           */
          
           base += length - 1;
           for (  ebase = s; base > ebase; base-- )
           if (  *base != U32_PATTERN )
           return (  void * ) base;
           #else
           /*
           * start at lower memory and find first word that does not
           * match pattern
           */
          
           base += PATTERN_SIZE_WORDS;
           for (  ebase = base + length; base < ebase; base++ )
           if (  *base != U32_PATTERN )
           return (  void * ) base;
           #endif
          
           return (  void * )0;
     370  }
          
          /*
           * Stack_check_Dump_threads_usage
           *
           * Try to print out how much stack was actually used by the task.
           */
          static void *print_context;
          static rtems_printk_plugin_t print_handler;
          
          void Stack_check_Dump_threads_usage(  
           Thread_Control *the_thread
           )
          {
           uint32_t size,   used;
           void *low;
           void *high_water_mark;
           void *current;
           Stack_Control *stack;
           char name[5];
          
           /*
           * The pointer passed in for the_thread is guaranteed to be non-NULL from
           * rtems_iterate_over_all_threads(   ) so no need to check it here.
           */
          
           /*
           * Obtain interrupt stack information
           */
           #if (  CPU_ALLOCATE_INTERRUPT_STACK == TRUE )
           if (  the_thread == (  Thread_Control * ) -1 ) {
           if (  !Stack_check_Interrupt_stack.area )
           return;
           stack = &Stack_check_Interrupt_stack;
           the_thread = 0;
           current = 0;
           } else
           #endif
           {
           stack = &the_thread->Start.Initial_stack;
           current = (  void * )_CPU_Context_Get_SP(   &the_thread->Registers  );
           }
          
           low = Stack_check_usable_stack_start(  stack );
           size = Stack_check_usable_stack_size(  stack );
          
           high_water_mark = Stack_check_find_high_water_mark(  low,   size );
          
           if (   high_water_mark  )
           used = Stack_check_Calculate_used(   low,   size,   high_water_mark  );
           else
           used = 0;
          
          
           #if (  CPU_ALLOCATE_INTERRUPT_STACK == TRUE )
           if (   the_thread  )
           #endif
           {
           (  *print_handler )(  
           print_context,  
           "0x%08" PRIx32 " %4s",  
           the_thread->Object.id,  
           rtems_object_get_name(   the_thread->Object.id,   sizeof(  name ),   name  )
            );
           }
           #if (  CPU_ALLOCATE_INTERRUPT_STACK == TRUE )
           else {
           (  *print_handler )(   print_context,   "0x%08" PRIx32 " INTR",   ~0  );
           }
           #endif
          
           (  *print_handler )(  
           print_context,  
           " %010p - %010p %010p %8" PRId32 " ",  
           stack->area,  
           stack->area + stack->size - 1,  
           current,  
           size
            );
          
           if (  Stack_check_Initialized == 0 ) {
           (  *print_handler )(   print_context,   "Unavailable\n"  );
           } else {
     453   (  *print_handler )(   print_context,   "%8" PRId32 "\n",   used  );
           }
          
          
          }
          
          /*
           * rtems_stack_checker_fatal_extension
           */
          #ifndef DONT_USE_FATAL_EXTENSION
           void rtems_stack_checker_fatal_extension(  
           Internal_errors_Source source,  
           bool is_internal,  
           uint32_t status
            )
           {
     469   if (  status == 0 )
           rtems_stack_checker_report_usage(   );
           }
          #endif
          
          /*PAGE
           *
           * rtems_stack_checker_report_usage
           */
          
          void rtems_stack_checker_report_usage_with_plugin(  
           void *context,  
           rtems_printk_plugin_t print
           )
          {
           if (   !print  )
           return;
          
           print_context = context;
           print_handler = print;
          
           (  *print )(   context,   "Stack usage by thread\n" );
           (  *print )(   context,  
          " ID NAME LOW HIGH CURRENT AVAILABLE USED\n"
            );
          
           /* iterate over all threads and dump the usage */
           rtems_iterate_over_all_threads(   Stack_check_Dump_threads_usage  );
     497  
           #if (  CPU_ALLOCATE_INTERRUPT_STACK == TRUE )
           /* dump interrupt stack info if any */
           Stack_check_Dump_threads_usage(  (  Thread_Control * ) -1 );
           #endif
          
           print_context = NULL;
           print_handler = NULL;
          }
          
          void rtems_stack_checker_report_usage(   void  )
          {
           rtems_stack_checker_report_usage_with_plugin(   NULL,   printk_plugin  );
          }

libmisc/stringto/stringtodouble.c

       1  /*
           * COPYRIGHT (  c ) 2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: stringtodouble.c,  v 1.2 2010/03/28 15:20:32 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Instantiate an error checking wrapper for strtod (  double )
           */
          #define STRING_TO_FLOAT
          #define STRING_TO_TYPE double
          #define STRING_TO_NAME rtems_string_to_double
          #define STRING_TO_METHOD strtod
          #define STRING_TO_MAX HUGE_VAL
          #include "stringto_template.h"
          

libmisc/stringto/stringtofloat.c

       1  /*
           * COPYRIGHT (  c ) 2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: stringtofloat.c,  v 1.2 2010/03/28 15:20:32 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Instantiate an error checking wrapper for strtof (  float )
           */
          #define STRING_TO_FLOAT
          #define STRING_TO_TYPE float
          #define STRING_TO_NAME rtems_string_to_float
          #define STRING_TO_METHOD strtof
          #define STRING_TO_MAX HUGE_VALF
          #include "stringto_template.h"

libmisc/stringto/stringtoint.c

       1  /*
           * COPYRIGHT (  c ) 2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: stringtoint.c,  v 1.2 2010/03/28 15:20:32 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Instantiate an error checking wrapper for strtol (  int )
           */
          #define STRING_TO_INTEGER
          #define STRING_TO_TYPE int
          #define STRING_TO_NAME rtems_string_to_int
          #define STRING_TO_METHOD strtol
          #define STRING_TO_MAX LONG_MAX
          #include "stringto_template.h"

libmisc/stringto/stringtolong.c

       1  /*
           * COPYRIGHT (  c ) 2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: stringtolong.c,  v 1.2 2010/03/28 15:20:32 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Instantiate an error checking wrapper for strtol (  long )
           */
          #define STRING_TO_INTEGER
          #define STRING_TO_TYPE long int
          #define STRING_TO_NAME rtems_string_to_long
          #define STRING_TO_METHOD strtol
          #define STRING_TO_MIN LONG_MIN
          #define STRING_TO_MAX LONG_MAX
          #include "stringto_template.h"

libmisc/stringto/stringtolonglong.c

       1  /*
           * COPYRIGHT (  c ) 2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: stringtolonglong.c,  v 1.2 2010/03/28 15:20:32 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Instantiate an error checking wrapper for strtoll (  long long )
           */
          #define STRING_TO_INTEGER
          #define STRING_TO_TYPE long long
          #define STRING_TO_NAME rtems_string_to_long_long
          #define STRING_TO_METHOD strtoll
          #define STRING_TO_MIN LONG_LONG_MIN
          #define STRING_TO_MAX LONG_LONG_MAX
          #include "stringto_template.h"

libmisc/stringto/stringtopointer.c

       1  /*
           * COPYRIGHT (  c ) 2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: stringtopointer.c,  v 1.2 2010/03/28 15:20:32 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Instantiate an error checking wrapper for strtoul which is
           * used to input a (  void * )
           *
           * NOTE: This is only an appropriate implementation when unsigned long
           * can represent a void *
           */
          #define STRING_TO_POINTER
          #define STRING_TO_TYPE void *
          #define STRING_TO_INPUT_TYPE unsigned long
          #define STRING_TO_NAME rtems_string_to_pointer
          #define STRING_TO_METHOD strtoul
          #define STRING_TO_MAX ULONG_MAX
          #include "stringto_template.h"

libmisc/stringto/stringtounsignedchar.c

       1  /*
           * COPYRIGHT (  c ) 2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: stringtounsignedchar.c,  v 1.2 2010/03/28 15:20:32 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Instantiate an error checking wrapper for strtol (  unsigned char )
           */
          #define STRING_TO_INTEGER
          #define STRING_TO_TYPE unsigned char
          #define STRING_TO_NAME rtems_string_to_unsigned_char
          #define STRING_TO_METHOD strtoul
          #define STRING_TO_MAX ULONG_MAX
          #include "stringto_template.h"

libmisc/stringto/stringtounsignedint.c

       1  /*
           * COPYRIGHT (  c ) 2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: stringtounsignedint.c,  v 1.2 2010/03/28 15:20:32 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Instantiate an error checking wrapper for strtoul (  unsigned int )
           */
          #define STRING_TO_INTEGER
          #define STRING_TO_TYPE unsigned int
          #define STRING_TO_NAME rtems_string_to_unsigned_int
          #define STRING_TO_METHOD strtoul
          #define STRING_TO_MAX ULONG_MAX
          #include "stringto_template.h"

libmisc/stringto/stringtounsignedlong.c

       1  /*
           * COPYRIGHT (  c ) 2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: stringtounsignedlong.c,  v 1.2 2010/03/28 15:20:32 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Instantiate an error checking wrapper for strtoul (  unsigned long )
           */
          #define STRING_TO_INTEGER
          #define STRING_TO_TYPE unsigned long int
          #define STRING_TO_NAME rtems_string_to_unsigned_long
          #define STRING_TO_METHOD strtoul
          #define STRING_TO_MAX ULONG_MAX
          #include "stringto_template.h"

libmisc/stringto/stringtounsignedlonglong.c

       1  /*
           * COPYRIGHT (  c ) 2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: stringtounsignedlonglong.c,  v 1.2 2010/03/28 15:20:32 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Instantiate an error checking wrapper for strtoull (  unsigned long long )
           */
          #define STRING_TO_INTEGER
          #define STRING_TO_TYPE unsigned long long
          #define STRING_TO_NAME rtems_string_to_unsigned_long_long
          #define STRING_TO_METHOD strtoull
          #define STRING_TO_MAX ULONG_LONG_MAX
          #include "stringto_template.h"

libmisc/untar/untar.c

       1  /* FIXME:
           * 1. Symbolic links are not created.
           * 2. Untar_FromMemory uses FILE *fp.
           * 3. How to determine end of archive?
           *
           * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: untar.c,  v 1.14 2010/08/24 13:06:24 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          #include <string.h>
          #include <stdlib.h>
          #include <unistd.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <rtems/untar.h>
          #include <rtems/bspIo.h>
          
          
          /**************************************************************************
           * TAR file format:
           *
           * Offset Length Contents
           * 0 100 bytes File name (  '\0' terminated,   99 maxmum length )
           * 100 8 bytes File mode (  in octal ascii )
           * 108 8 bytes User ID (  in octal ascii )
           * 116 8 bytes Group ID (  in octal ascii )
           * 124 12 bytes File size (  s ) (  in octal ascii )
           * 136 12 bytes Modify time (  in octal ascii )
           * 148 8 bytes Header checksum (  in octal ascii )
           * 156 1 bytes Link flag
           * 157 100 bytes Linkname (  '\0' terminated,   99 maxmum length )
           * 257 8 bytes Magic PAX (  "ustar\0" + 2 bytes padding )
           * 257 8 bytes Magic GNU tar (  "ustar \0" )
           * 265 32 bytes User name (  '\0' terminated,   31 maxmum length )
           * 297 32 bytes Group name (  '\0' terminated,   31 maxmum length )
           * 329 8 bytes Major device ID (  in octal ascii )
           * 337 8 bytes Minor device ID (  in octal ascii )
           * 345 155 bytes Prefix
           * 512 (  s+p )bytes File contents (  s+p ) := (  (  (  s ) + 511 ) & ~511 ),  
           * round up to 512 bytes
           *
           * Checksum:
           * int i,   sum;
           * char* header = tar_header_pointer;
           * sum = 0;
           * for(  i = 0; i < 512; i++ )
           * sum += 0xFF & header[i];
           *************************************************************************/
          
          #define MAX_NAME_FIELD_SIZE 99
          
          #define MIN(  a,  b ) (  (  a )>(  b )?(  b ):(  a ) )
          
          
          /**************************************************************************
           * This converts octal ASCII number representations into an
           * unsigned long. Only support 32-bit numbers for now.
           *************************************************************************/
          unsigned long
      70  _rtems_octal2ulong(  
           const char *octascii,  
           size_t len
           )
          {
           size_t i;
           unsigned long num;
          
           num = 0;
           for (  i=0; i < len; i++ )
           {
           if (  (  octascii[i] < '0' ) || (  octascii[i] > '9' ) )
           {
           continue;
           }
           num = num * 8 + (  (  unsigned long )(  octascii[i] - '0' ) );
           }
           return(  num );
          }
          
          
          /**************************************************************************
           * Function: Untar_FromMemory *
           **************************************************************************
           * Description: *
           * *
           * This is a simple subroutine used to rip links,   directories,   and *
           * files out of a block of memory. *
           * *
           * *
           * Inputs: *
           * *
           * void * tar_buf - Pointer to TAR buffer. *
           * size_t size - Length of TAR buffer. *
           * *
           * *
           * Output: *
           * *
           * int - UNTAR_SUCCESSFUL (  0 ) on successful completion. *
           * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
           * UNTAR_INVALID_HEADER for an invalid header. *
           * *
           **************************************************************************/
          int
     114  Untar_FromMemory(  
           void *tar_buf,  
           size_t size
           )
          {
           FILE *fp;
           const char *tar_ptr = (  const char * )tar_buf;
           const char *bufr;
           size_t n;
           char fname[100];
           char linkname[100];
           int sum;
           int hdr_chksum;
           int retval;
           unsigned long ptr;
           unsigned long i;
           unsigned long nblocks;
           unsigned long file_size;
           unsigned char linkflag;
          
          
           ptr = 0;
           while (  1 )
           {
           if (  ptr + 512 > size )
           {
           retval = UNTAR_SUCCESSFUL;
           break;
           }
          
           /* Read the header */
           bufr = &tar_ptr[ptr];
           ptr += 512;
           if (  strncmp(  &bufr[257],   "ustar",   5 ) )
           {
           retval = UNTAR_SUCCESSFUL;
           break;
           }
          
           strncpy(  fname,   bufr,   MAX_NAME_FIELD_SIZE );
           fname[MAX_NAME_FIELD_SIZE] = '\0';
          
           linkflag = bufr[156];
           file_size = _rtems_octal2ulong(  &bufr[124],   12 );
          
           /******************************************************************
           * Compute the TAR checksum and check with the value in
           * the archive. The checksum is computed over the entire
           * header,   but the checksum field is substituted with blanks.
           ******************************************************************/
           hdr_chksum = _rtems_octal2ulong(  &bufr[148],   8 );
           sum = _rtems_tar_header_checksum(  bufr );
          
           if (  sum != hdr_chksum )
           {
           retval = UNTAR_INVALID_CHECKSUM;
           break;
           }
          
          
           /******************************************************************
           * We've decoded the header,   now figure out what it contains and
           * do something with it.
           *****************************************************************/
           if (  linkflag == SYMTYPE )
           {
           strncpy(  linkname,   &bufr[157],   MAX_NAME_FIELD_SIZE );
           linkname[MAX_NAME_FIELD_SIZE] = '\0';
           symlink(  linkname,   fname );
           }
           else if (  linkflag == REGTYPE )
           {
           nblocks = (  (  (  file_size ) + 511 ) & ~511 ) / 512;
           if (  (  fp = fopen(  fname,   "w" ) ) == NULL )
           {
           printk(  "Untar: failed to create file %s\n",   fname );
           ptr += 512 * nblocks;
           }
           else
           {
           unsigned long sizeToGo = file_size;
           size_t len;
          
           /***************************************************************
           * Read out the data. There are nblocks of data where nblocks
           * is the file_size rounded to the nearest 512-byte boundary.
           **************************************************************/
           for (  i=0; i<nblocks; i++ )
           {
           len = (  (  sizeToGo < 512L )?(  sizeToGo ):(  512L ) );
           n = fwrite(  &tar_ptr[ptr],   1,   len,   fp );
           if (  n != len )
           {
           printk(  "untar: Error during write\n" );
           break;
           }
           ptr += 512;
           sizeToGo -= n;
           }
           fclose(  fp );
           }
           }
           else if (  linkflag == DIRTYPE )
           {
           mkdir(  fname,   S_IRWXU | S_IRWXG | S_IRWXO );
           }
           }
          
           return(  retval );
          }
          
          
          /**************************************************************************
           * Function: Untar_FromFile *
           **************************************************************************
           * Description: *
           * *
           * This is a simple subroutine used to rip links,   directories,   and *
           * files out of a TAR file. *
           * *
           * *
           * Inputs: *
           * *
           * const char *tar_name - TAR filename. *
           * *
           * *
           * Output: *
           * *
           * int - UNTAR_SUCCESSFUL (  0 ) on successful completion. *
           * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
           * UNTAR_INVALID_HEADER for an invalid header. *
           * *
           **************************************************************************
           * Change History: *
           * 12/30/1998 - Creation (  JWJ ) *
           *************************************************************************/
          int
     251  Untar_FromFile(  
           const char *tar_name
           )
          {
           int fd;
           char *bufr;
           ssize_t n;
           char fname[100];
           char linkname[100];
           int sum;
           int hdr_chksum;
           int retval;
           unsigned long i;
           unsigned long nblocks;
           unsigned long size;
           unsigned char linkflag;
          
           retval = UNTAR_SUCCESSFUL;
          
           if (  (  fd = open(  tar_name,   O_RDONLY ) ) < 0 ) {
           return UNTAR_FAIL;
           }
          
           bufr = (  char * )malloc(  512 );
           if (  bufr == NULL ) {
           return(  UNTAR_FAIL );
           }
          
           while (  1 )
           {
           /* Read the header */
           /* If the header read fails,   we just consider it the end
           of the tarfile. */
           if (  (  n = read(  fd,   bufr,   512 ) ) != 512 )
           {
           break;
           }
          
           if (  strncmp(  &bufr[257],   "ustar",   5 ) )
           {
           break;
           }
          
           strncpy(  fname,   bufr,   MAX_NAME_FIELD_SIZE );
           fname[MAX_NAME_FIELD_SIZE] = '\0';
          
           linkflag = bufr[156];
           size = _rtems_octal2ulong(  &bufr[124],   12 );
          
           /******************************************************************
           * Compute the TAR checksum and check with the value in
           * the archive. The checksum is computed over the entire
           * header,   but the checksum field is substituted with blanks.
           ******************************************************************/
           hdr_chksum = _rtems_octal2ulong(  &bufr[148],   8 );
           sum = _rtems_tar_header_checksum(  bufr );
          
           if (  sum != hdr_chksum )
           {
           retval = UNTAR_INVALID_CHECKSUM;
           break;
           }
          
           /******************************************************************
           * We've decoded the header,   now figure out what it contains and
           * do something with it.
           *****************************************************************/
           if (  linkflag == SYMTYPE )
           {
           strncpy(  linkname,   &bufr[157],   MAX_NAME_FIELD_SIZE );
           linkname[MAX_NAME_FIELD_SIZE] = '\0';
           symlink(  linkname,  fname );
           }
           else if (  linkflag == REGTYPE )
           {
           int out_fd;
          
           /******************************************************************
           * Read out the data. There are nblocks of data where nblocks
           * is the size rounded to the nearest 512-byte boundary.
           *****************************************************************/
           nblocks = (  (  (  size ) + 511 ) & ~511 ) / 512;
          
           if (  (  out_fd = creat(  fname,   0644 ) ) == -1 )
           {
           for (  i=0; i<nblocks; i++ )
           {
           n = read(  fd,   bufr,   512 );
           }
           }
           else
           {
           for (  i=0; i<nblocks; i++ )
           {
           n = read(  fd,   bufr,   512 );
           n = MIN(  n,   size - i*512 );
           write(  out_fd,   bufr,   n );
           }
           close(  out_fd );
           }
           }
           else if (  linkflag == DIRTYPE )
           {
           mkdir(  fname,   S_IRWXU | S_IRWXG | S_IRWXO );
           }
           }
           free(  bufr );
           close(  fd );
          
           return(  retval );
          }
          
          /************************************************************************
           * Compute the TAR checksum and check with the value in
           * the archive. The checksum is computed over the entire
           * header,   but the checksum field is substituted with blanks.
           ************************************************************************/
          int
     369  _rtems_tar_header_checksum(  
           const char *bufr
           )
          {
           int i,   sum;
          
           sum = 0;
           for (  i=0; i<512; i++ )
           {
           if (  (  i >= 148 ) && (  i < 156 ) )
           sum += 0xff & ' ';
           else
           sum += 0xff & bufr[i];
           }
           return(  sum );
          }

libmisc/uuid/clear.c

       1  /*
           * clear.c -- Clear a UUID
           *
           * Copyright (  C ) 1996,   1997 Theodore Ts'o.
           *
           * %Begin-Header%
           * 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,   and the entire permission notice in its entirety,  
           * including the disclaimer of warranties.
           * 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. The name of the author may not be used to endorse or promote
           * products derived from this software without specific prior
           * written permission.
           *
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
           * WARRANTIES,   INCLUDING,   BUT NOT LIMITED TO,   THE IMPLIED WARRANTIES
           * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,   ALL OF
           * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
           * DAMAGE.
           * %End-Header%
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          
          #include "uuidP.h"
          
      43  void uuid_clear(  uuid_t uu )
          {
           memset(  uu,   0,   16 );
          }
          

libmisc/uuid/compare.c

       1  /*
           * compare.c --- compare whether or not two UUID's are the same
           *
           * Returns 0 if the two UUID's are different,   and 1 if they are the same.
           *
           * Copyright (  C ) 1996,   1997 Theodore Ts'o.
           *
           * %Begin-Header%
           * 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,   and the entire permission notice in its entirety,  
           * including the disclaimer of warranties.
           * 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. The name of the author may not be used to endorse or promote
           * products derived from this software without specific prior
           * written permission.
           *
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
           * WARRANTIES,   INCLUDING,   BUT NOT LIMITED TO,   THE IMPLIED WARRANTIES
           * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,   ALL OF
           * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
           * DAMAGE.
           * %End-Header%
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          #include "uuidP.h"
          
          #define UUCMP(  u1,  u2 ) if (  u1 != u2 ) return(  (  u1 < u2 ) ? -1 : 1 );
          
      46  int uuid_compare(  const uuid_t uu1,   const uuid_t uu2 )
          {
           struct uuid uuid1,   uuid2;
          
           uuid_unpack(  uu1,   &uuid1 );
           uuid_unpack(  uu2,   &uuid2 );
          
           UUCMP(  uuid1.time_low,   uuid2.time_low );
           UUCMP(  uuid1.time_mid,   uuid2.time_mid );
           UUCMP(  uuid1.time_hi_and_version,   uuid2.time_hi_and_version );
           UUCMP(  uuid1.clock_seq,   uuid2.clock_seq );
           return memcmp(  uuid1.node,   uuid2.node,   6 );
          }
          

libmisc/uuid/copy.c

       1  /*
           * copy.c --- copy UUIDs
           *
           * Copyright (  C ) 1996,   1997 Theodore Ts'o.
           *
           * %Begin-Header%
           * 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,   and the entire permission notice in its entirety,  
           * including the disclaimer of warranties.
           * 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. The name of the author may not be used to endorse or promote
           * products derived from this software without specific prior
           * written permission.
           *
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
           * WARRANTIES,   INCLUDING,   BUT NOT LIMITED TO,   THE IMPLIED WARRANTIES
           * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,   ALL OF
           * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
           * DAMAGE.
           * %End-Header%
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include "uuidP.h"
          
      41  void uuid_copy(  uuid_t dst,   const uuid_t src )
          {
           unsigned char *cp1;
           const unsigned char *cp2;
           int i;
          
           for (  i=0,   cp1 = dst,   cp2 = src; i < 16; i++ )
           *cp1++ = *cp2++;
          }

libmisc/uuid/gen_uuid.c

       1  /*
           * gen_uuid.c --- generate a DCE-compatible uuid
           *
           * Copyright (  C ) 1996,   1997,   1998,   1999 Theodore Ts'o.
           *
           * %Begin-Header%
           * 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,   and the entire permission notice in its entirety,  
           * including the disclaimer of warranties.
           * 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. The name of the author may not be used to endorse or promote
           * products derived from this software without specific prior
           * written permission.
           *
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
           * WARRANTIES,   INCLUDING,   BUT NOT LIMITED TO,   THE IMPLIED WARRANTIES
           * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,   ALL OF
           * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
           * DAMAGE.
           * %End-Header%
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * Force inclusion of SVID stuff since we need it if we're compiling in
           * gcc-wall wall mode
           */
          #define _SVID_SOURCE
          
          #ifdef _WIN32
          #define _WIN32_WINNT 0x0500
          #include <windows.h>
          #define UUID MYUUID
          #endif
          #include <stdio.h>
          #include <limits.h> /* for CHAR_BIT */
          #ifdef HAVE_UNISTD_H
          #include <unistd.h>
          #endif
          #ifdef HAVE_STDLIB_H
          #include <stdlib.h>
          #endif
          #include <string.h>
          #include <fcntl.h>
          #include <errno.h>
          #include <sys/types.h>
          #ifdef HAVE_SYS_TIME_H
          #include <sys/time.h>
          #endif
          #include <sys/wait.h>
          #include <sys/stat.h>
          #ifdef HAVE_SYS_FILE_H
          #include <sys/file.h>
          #endif
          #ifdef HAVE_SYS_IOCTL_H
          #include <sys/ioctl.h>
          #endif
          #ifdef HAVE_SYS_SOCKET_H
          #include <sys/socket.h>
          #endif
          #ifdef HAVE_SYS_UN_H
          #include <sys/un.h>
          #endif
          #ifdef HAVE_SYS_SOCKIO_H
          #include <sys/sockio.h>
          #endif
          #ifdef HAVE_NET_IF_H
          #include <net/if.h>
          #endif
          #ifdef HAVE_NETINET_IN_H
          #include <netinet/in.h>
          #endif
          #ifdef HAVE_NET_IF_DL_H
          #include <net/if_dl.h>
          #endif
          #if defined(  __linux__ ) && defined(  HAVE_SYS_SYSCALL_H )
          #include <sys/syscall.h>
          #endif
          #ifdef HAVE_SYS_RESOURCE_H
          #include <sys/resource.h>
          #endif
          
          #include "uuidP.h"
          #include "uuidd.h"
          
          #ifdef HAVE_SRANDOM
          #define srand(  x ) srandom(  x )
          #define rand(   ) random(   )
          #endif
          
          #ifdef TLS
          #define THREAD_LOCAL static TLS
          #else
          #define THREAD_LOCAL static
          #endif
          
          #if defined(  __linux__ ) && defined(  __NR_gettid ) && defined(  HAVE_JRAND48 )
          #define DO_JRAND_MIX
     114  THREAD_LOCAL unsigned short jrand_seed[3];
          #endif
          
          #ifdef _WIN32
     118  static void gettimeofday (  struct timeval *tv,   void *dummy )
          {
           FILETIME ftime;
           uint64_t n;
          
           GetSystemTimeAsFileTime (  &ftime );
           n = (  (  (  uint64_t ) ftime.dwHighDateTime << 32 )
           + (  uint64_t ) ftime.dwLowDateTime );
           if (  n ) {
           n /= 10;
           n -= (  (  369 * 365 + 89 ) * (  uint64_t ) 86400 ) * 1000000;
           }
          
           tv->tv_sec = n / 1000000;
           tv->tv_usec = n % 1000000;
          }
          
     135  static int getuid (  void )
          {
           return 1;
          }
          #endif
          
     141  static int get_random_fd(  void )
          {
           struct timeval tv;
           static int fd = -2;
           int i;
          
           if (  fd == -2 ) {
           gettimeofday(  &tv,   0 );
          #ifndef _WIN32
           fd = open(  "/dev/urandom",   O_RDONLY );
           if (  fd == -1 )
           fd = open(  "/dev/random",   O_RDONLY | O_NONBLOCK );
           if (  fd >= 0 ) {
           i = fcntl(  fd,   F_GETFD );
           if (  i >= 0 )
           fcntl(  fd,   F_SETFD,   i | FD_CLOEXEC );
           }
          #endif
           srand(  (  getpid(   ) << (  (  sizeof(  pid_t )*CHAR_BIT )>>1 ) ) ^ getuid(   ) ^ tv.tv_sec ^ tv.tv_usec );
          #ifdef DO_JRAND_MIX
           jrand_seed[0] = getpid(   ) ^ (  tv.tv_sec & 0xFFFF );
           jrand_seed[1] = getppid(   ) ^ (  tv.tv_usec & 0xFFFF );
           jrand_seed[2] = (  tv.tv_sec ^ tv.tv_usec ) >> 16;
          #endif
           }
           /* Crank the random number generator a few times */
           gettimeofday(  &tv,   0 );
           for (  i = (  tv.tv_sec ^ tv.tv_usec ) & 0x1F; i > 0; i-- )
           rand(   );
           return fd;
          }
          
          
          /*
           * Generate a series of random bytes. Use /dev/urandom if possible,  
           * and if not,   use srandom/random.
           */
     178  static void get_random_bytes(  void *buf,   int nbytes )
          {
           int i,   n = nbytes,   fd = get_random_fd(   );
           int lose_counter = 0;
           unsigned char *cp = (  unsigned char * ) buf;
          #ifdef DO_JRAND_MIX
           unsigned short tmp_seed[3];
          #endif
          
           if (  fd >= 0 ) {
           while (  n > 0 ) {
           i = read(  fd,   cp,   n );
           if (  i <= 0 ) {
           if (  lose_counter++ > 16 )
           break;
           continue;
           }
           n -= i;
           cp += i;
           lose_counter = 0;
           }
           }
          
           /*
           * We do this all the time,   but this is the only source of
           * randomness if /dev/random/urandom is out to lunch.
           */
           for (  cp = buf,   i = 0; i < nbytes; i++ )
           *cp++ ^= (  rand(   ) >> 7 ) & 0xFF;
          #ifdef DO_JRAND_MIX
           memcpy(  tmp_seed,   jrand_seed,   sizeof(  tmp_seed ) );
           jrand_seed[2] = jrand_seed[2] ^ syscall(  __NR_gettid );
           for (  cp = buf,   i = 0; i < nbytes; i++ )
           *cp++ ^= (  jrand48(  tmp_seed ) >> 7 ) & 0xFF;
           memcpy(  jrand_seed,   tmp_seed,  
           sizeof(  jrand_seed )-sizeof(  unsigned short ) );
          #endif
          
           return;
          }
          
          /*
           * Get the ethernet hardware address,   if we can find it...
           *
           * XXX for a windows version,   probably should use GetAdaptersInfo:
           * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451
           * commenting out get_node_id just to get gen_uuid to compile under windows
           * is not the right way to go!
           */
     227  static int get_node_id(  unsigned char *node_id )
          {
          #ifdef HAVE_NET_IF_H
           int sd;
           struct ifreq ifr,   *ifrp;
           struct ifconf ifc;
           char buf[1024];
           int n,   i;
           unsigned char *a;
          #ifdef HAVE_NET_IF_DL_H
           struct sockaddr_dl *sdlp;
          #endif
          
          /*
           * BSD 4.4 defines the size of an ifreq to be
           * max(  sizeof(  ifreq ),   sizeof(  ifreq.ifr_name )+ifreq.ifr_addr.sa_len
           * However,   under earlier systems,   sa_len isn't present,   so the size is
           * just sizeof(  struct ifreq )
           */
          #ifdef HAVE_SA_LEN
          #ifndef max
          #define max(  a,  b ) (  (  a ) > (  b ) ? (  a ) : (  b ) )
          #endif
          #define ifreq_size(  i ) max(  sizeof(  struct ifreq ),  \
           sizeof(  (  i ).ifr_name )+(  i ).ifr_addr.sa_len )
          #else
          #define ifreq_size(  i ) sizeof(  struct ifreq )
          #endif /* HAVE_SA_LEN*/
          
           sd = socket(  AF_INET,   SOCK_DGRAM,   IPPROTO_IP );
           if (  sd < 0 ) {
           return -1;
           }
           memset(  buf,   0,   sizeof(  buf ) );
           ifc.ifc_len = sizeof(  buf );
           ifc.ifc_buf = buf;
           if (  ioctl (  sd,   SIOCGIFCONF,   (  char * )&ifc ) < 0 ) {
           close(  sd );
           return -1;
           }
           n = ifc.ifc_len;
           for (  i = 0; i < n; i+= ifreq_size(  *ifrp )  ) {
           ifrp = (  struct ifreq * )(  (  char * ) ifc.ifc_buf+i );
           strncpy(  ifr.ifr_name,   ifrp->ifr_name,   IFNAMSIZ );
          #ifdef SIOCGIFHWADDR
           if (  ioctl(  sd,   SIOCGIFHWADDR,   &ifr ) < 0 )
           continue;
           a = (  unsigned char * ) &ifr.ifr_hwaddr.sa_data;
          #else
          #ifdef SIOCGENADDR
           if (  ioctl(  sd,   SIOCGENADDR,   &ifr ) < 0 )
           continue;
           a = (  unsigned char * ) ifr.ifr_enaddr;
          #else
          #ifdef HAVE_NET_IF_DL_H
           sdlp = (  struct sockaddr_dl * ) &ifrp->ifr_addr;
           if (  (  sdlp->sdl_family != AF_LINK ) || (  sdlp->sdl_alen != 6 ) )
           continue;
           a = (  unsigned char * ) &sdlp->sdl_data[sdlp->sdl_nlen];
          #else
           /*
           * XXX we don't have a way of getting the hardware
           * address
           */
           close(  sd );
           return 0;
          #endif /* HAVE_NET_IF_DL_H */
          #endif /* SIOCGENADDR */
          #endif /* SIOCGIFHWADDR */
           if (  !a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5] )
           continue;
           if (  node_id ) {
           memcpy(  node_id,   a,   6 );
           close(  sd );
           return 1;
           }
           }
           close(  sd );
          #endif
           return 0;
          }
          
          /* Assume that the gettimeofday(   ) has microsecond granularity */
          #define MAX_ADJUSTMENT 10
     311  
          static int get_clock(  uint32_t *clock_high,   uint32_t *clock_low,  
           uint16_t *ret_clock_seq,   int *num )
          {
           THREAD_LOCAL int adjustment = 0;
           THREAD_LOCAL struct timeval last = {0,   0};
           THREAD_LOCAL int state_fd = -2;
           THREAD_LOCAL FILE *state_f;
           THREAD_LOCAL uint16_t clock_seq;
           struct timeval tv;
           struct flock fl;
           uint64_t clock_reg;
           mode_t save_umask;
           int len;
          
           if (  state_fd == -2 ) {
           save_umask = umask(  0 );
           state_fd = open(  "/var/lib/libuuid/clock.txt",  
           O_RDWR|O_CREAT,   0660 );
           (  void ) umask(  save_umask );
           state_f = fdopen(  state_fd,   "r+" );
           if (  !state_f ) {
           close(  state_fd );
           state_fd = -1;
           }
           }
           fl.l_type = F_WRLCK;
           fl.l_whence = SEEK_SET;
           fl.l_start = 0;
           fl.l_len = 0;
           fl.l_pid = 0;
           if (  state_fd >= 0 ) {
           rewind(  state_f );
           while (  fcntl(  state_fd,   F_SETLKW,   &fl ) < 0 ) {
           if (  (  errno == EAGAIN ) || (  errno == EINTR ) )
           continue;
           fclose(  state_f );
           close(  state_fd );
           state_fd = -1;
           break;
           }
           }
           if (  state_fd >= 0 ) {
           unsigned int cl;
           unsigned long tv1,   tv2;
           int a;
          
           if (  fscanf(  state_f,   "clock: %04x tv: %lu %lu adj: %d\n",  
           &cl,   &tv1,   &tv2,   &a ) == 4 ) {
           clock_seq = cl & 0x3FFF;
           last.tv_sec = tv1;
           last.tv_usec = tv2;
           adjustment = a;
           }
           }
          
           if (  (  last.tv_sec == 0 ) && (  last.tv_usec == 0 ) ) {
           get_random_bytes(  &clock_seq,   sizeof(  clock_seq ) );
           clock_seq &= 0x3FFF;
           gettimeofday(  &last,   0 );
           last.tv_sec--;
           }
          
          try_again:
           gettimeofday(  &tv,   0 );
           if (  (  tv.tv_sec < last.tv_sec ) ||
           (  (  tv.tv_sec == last.tv_sec ) &&
           (  tv.tv_usec < last.tv_usec ) ) ) {
           clock_seq = (  clock_seq+1 ) & 0x3FFF;
           adjustment = 0;
           last = tv;
           } else if (  (  tv.tv_sec == last.tv_sec ) &&
           (  tv.tv_usec == last.tv_usec ) ) {
           if (  adjustment >= MAX_ADJUSTMENT )
           goto try_again;
           adjustment++;
           } else {
           adjustment = 0;
           last = tv;
           }
          
           clock_reg = tv.tv_usec*10 + adjustment;
           clock_reg += (  (  uint64_t ) tv.tv_sec )*10000000;
           clock_reg += (  (  (  uint64_t ) 0x01B21DD2 ) << 32 ) + 0x13814000;
          
           if (  num && (  *num > 1 ) ) {
           adjustment += *num - 1;
           last.tv_usec += adjustment / 10;
           adjustment = adjustment % 10;
           last.tv_sec += last.tv_usec / 1000000;
           last.tv_usec = last.tv_usec % 1000000;
           }
          
           if (  state_fd > 0 ) {
           rewind(  state_f );
           len = fprintf(  state_f,  
           "clock: %04x tv: %016lu %08lu adj: %08d\n",  
           clock_seq,   last.tv_sec,   last.tv_usec,   adjustment );
           fflush(  state_f );
           if (  ftruncate(  state_fd,   len ) < 0 ) {
           fprintf(  state_f,   " \n" );
           fflush(  state_f );
           }
           rewind(  state_f );
           fl.l_type = F_UNLCK;
           fcntl(  state_fd,   F_SETLK,   &fl );
           }
          
           *clock_high = clock_reg >> 32;
           *clock_low = clock_reg;
           *ret_clock_seq = clock_seq;
           return 0;
          }
          
          /* unused */
     426  #if defined(  USE_UUIDD ) && defined(  HAVE_SYS_UN_H )
          static ssize_t read_all(  int fd,   char *buf,   size_t count )
          {
           ssize_t ret;
           ssize_t c = 0;
          
           memset(  buf,   0,   count );
           while (  count > 0 ) {
           ret = read(  fd,   buf,   count );
           if (  ret < 0 ) {
           if (  (  errno == EAGAIN ) || (  errno == EINTR ) )
           continue;
           return -1;
           }
           count -= ret;
           buf += ret;
           c += ret;
           }
           return c;
          }
          #endif
          
          #if defined(  USE_UUIDD ) && defined(  HAVE_SYS_UN_H )
          
          /*
           * Close all file descriptors
     452   */
          static void close_all_fds(  void )
          {
           int i,   max;
          
          #if defined(  HAVE_SYSCONF ) && defined(  _SC_OPEN_MAX )
           max = sysconf(  _SC_OPEN_MAX );
          #elif defined(  HAVE_GETDTABLESIZE )
           max = getdtablesize(   );
          #elif defined(  HAVE_GETRLIMIT ) && defined(  RLIMIT_NOFILE )
           struct rlimit rl;
          
           getrlimit(  RLIMIT_NOFILE,   &rl );
           max = rl.rlim_cur;
          #else
           max = OPEN_MAX;
          #endif
          
           for (  i=0; i < max; i++ )
           close(  i );
          }
          
          #endif
          
          
          /*
           * Try using the uuidd daemon to generate the UUID
           *
           * Returns 0 on success,   non-zero on failure.
     481   */
          static int get_uuid_via_daemon(  int op,   uuid_t out,   int *num )
          {
          #if defined(  USE_UUIDD ) && defined(  HAVE_SYS_UN_H )
           char op_buf[64];
           int op_len;
           int s;
           ssize_t ret;
           int32_t reply_len = 0,   expected = 16;
           struct sockaddr_un srv_addr;
           pid_t pid;
           static const char *uuidd_path = UUIDD_PATH;
           static int access_ret = -2;
           static int start_attempts = 0;
          
           if (  (  s = socket(  AF_UNIX,   SOCK_STREAM,   0 ) ) < 0 )
           return -1;
          
           srv_addr.sun_family = AF_UNIX;
           strcpy(  srv_addr.sun_path,   UUIDD_SOCKET_PATH );
          
           if (  connect(  s,   (  const struct sockaddr * ) &srv_addr,  
           sizeof(  struct sockaddr_un ) ) < 0 ) {
           if (  access_ret == -2 )
           access_ret = access(  uuidd_path,   X_OK );
           if (  access_ret == 0 && start_attempts++ < 5 ) {
           if (  (  pid = fork(   ) ) == 0 ) {
           close_all_fds(   );
           execl(  uuidd_path,   "uuidd",   "-qT",   "300",  
           (  char * ) NULL );
           exit(  1 );
           }
           (  void ) waitpid(  pid,   0,   0 );
           if (  connect(  s,   (  const struct sockaddr * ) &srv_addr,  
           sizeof(  struct sockaddr_un ) ) < 0 )
           goto fail;
           } else
           goto fail;
           }
           op_buf[0] = op;
           op_len = 1;
           if (  op == UUIDD_OP_BULK_TIME_UUID ) {
           memcpy(  op_buf+1,   num,   sizeof(  *num ) );
           op_len += sizeof(  *num );
           expected += sizeof(  *num );
           }
          
           ret = write(  s,   op_buf,   op_len );
           if (  ret < 1 )
           goto fail;
          
           ret = read_all(  s,   (  char * ) &reply_len,   sizeof(  reply_len ) );
           if (  ret < 0 )
           goto fail;
          
           if (  reply_len != expected )
           goto fail;
          
           ret = read_all(  s,   op_buf,   reply_len );
          
           if (  op == UUIDD_OP_BULK_TIME_UUID )
           memcpy(  op_buf+16,   num,   sizeof(  int ) );
          
           memcpy(  out,   op_buf,   16 );
          
           close(  s );
           return (  (  ret == expected ) ? 0 : -1 );
          
          fail:
           close(  s );
          #endif
           return -1;
          }
     554  
          void uuid__generate_time(  uuid_t out,   int *num )
          {
           static unsigned char node_id[6];
           static int has_init = 0;
           struct uuid uu;
           uint32_t clock_mid;
          
           if (  !has_init ) {
           if (  get_node_id(  node_id ) <= 0 ) {
           get_random_bytes(  node_id,   6 );
           /*
           * Set multicast bit,   to prevent conflicts
           * with IEEE 802 addresses obtained from
           * network cards
           */
           node_id[0] |= 0x01;
           }
           has_init = 1;
           }
           get_clock(  &clock_mid,   &uu.time_low,   &uu.clock_seq,   num );
           uu.clock_seq |= 0x8000;
           uu.time_mid = (  uint16_t ) clock_mid;
           uu.time_hi_and_version = (  (  clock_mid >> 16 ) & 0x0FFF ) | 0x1000;
           memcpy(  uu.node,   node_id,   6 );
           uuid_pack(  &uu,   out );
          }
     581  
          void uuid_generate_time(  uuid_t out )
          {
          #ifdef TLS
           THREAD_LOCAL int num = 0;
           THREAD_LOCAL struct uuid uu;
           THREAD_LOCAL time_t last_time = 0;
           time_t now;
          
           if (  num > 0 ) {
           now = time(  0 );
           if (  now > last_time+1 )
           num = 0;
           }
           if (  num <= 0 ) {
           num = 1000;
           if (  get_uuid_via_daemon(  UUIDD_OP_BULK_TIME_UUID,  
           out,   &num ) == 0 ) {
           last_time = time(  0 );
           uuid_unpack(  out,   &uu );
           num--;
           return;
           }
           num = 0;
           }
           if (  num > 0 ) {
           uu.time_low++;
           if (  uu.time_low == 0 ) {
           uu.time_mid++;
           if (  uu.time_mid == 0 )
           uu.time_hi_and_version++;
           }
           num--;
           uuid_pack(  &uu,   out );
           return;
           }
          #else
           if (  get_uuid_via_daemon(  UUIDD_OP_TIME_UUID,   out,   0 ) == 0 )
           return;
          #endif
          
           uuid__generate_time(  out,   0 );
          }
          
     625  
          void uuid__generate_random(  uuid_t out,   int *num )
          {
           uuid_t buf;
           struct uuid uu;
           int i,   n;
          
           if (  !num || !*num )
           n = 1;
           else
           n = *num;
          
           for (  i = 0; i < n; i++ ) {
           get_random_bytes(  buf,   sizeof(  buf ) );
           uuid_unpack(  buf,   &uu );
          
           uu.clock_seq = (  uu.clock_seq & 0x3FFF ) | 0x8000;
           uu.time_hi_and_version = (  uu.time_hi_and_version & 0x0FFF )
           | 0x4000;
           uuid_pack(  &uu,   out );
           out += sizeof(  uuid_t );
           }
          }
     648  
          void uuid_generate_random(  uuid_t out )
          {
           int num = 1;
           /* No real reason to use the daemon for random uuid's -- yet */
          
           uuid__generate_random(  out,   &num );
          }
          
          
          /*
           * This is the generic front-end to uuid_generate_random and
           * uuid_generate_time. It uses uuid_generate_random only if
           * /dev/urandom is available,   since otherwise we won't have
           * high-quality randomness.
     663   */
          void uuid_generate(  uuid_t out )
          {
           if (  get_random_fd(   ) >= 0 )
           uuid_generate_random(  out );
           else
           uuid_generate_time(  out );
          }

libmisc/uuid/isnull.c

       1  /*
           * isnull.c --- Check whether or not the UUID is null
           *
           * Copyright (  C ) 1996,   1997 Theodore Ts'o.
           *
           * %Begin-Header%
           * 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,   and the entire permission notice in its entirety,  
           * including the disclaimer of warranties.
           * 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. The name of the author may not be used to endorse or promote
           * products derived from this software without specific prior
           * written permission.
           *
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
           * WARRANTIES,   INCLUDING,   BUT NOT LIMITED TO,   THE IMPLIED WARRANTIES
           * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,   ALL OF
           * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
           * DAMAGE.
           * %End-Header%
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include "uuidP.h"
          
          /* Returns 1 if the uuid is the NULL uuid */
      42  int uuid_is_null(  const uuid_t uu )
          {
           const unsigned char *cp;
           int i;
          
           for (  i=0,   cp = uu; i < 16; i++ )
           if (  *cp++ )
           return 0;
           return 1;
          }
          

libmisc/uuid/pack.c

       1  /*
           * Internal routine for packing UUID's
           *
           * Copyright (  C ) 1996,   1997 Theodore Ts'o.
           *
           * %Begin-Header%
           * 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,   and the entire permission notice in its entirety,  
           * including the disclaimer of warranties.
           * 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. The name of the author may not be used to endorse or promote
           * products derived from this software without specific prior
           * written permission.
           *
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
           * WARRANTIES,   INCLUDING,   BUT NOT LIMITED TO,   THE IMPLIED WARRANTIES
           * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,   ALL OF
           * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
           * DAMAGE.
           * %End-Header%
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          #include "uuidP.h"
          
      42  void uuid_pack(  const struct uuid *uu,   uuid_t ptr )
          {
           uint32_t tmp;
           unsigned char *out = ptr;
          
           tmp = uu->time_low;
           out[3] = (  unsigned char ) tmp;
           tmp >>= 8;
           out[2] = (  unsigned char ) tmp;
           tmp >>= 8;
           out[1] = (  unsigned char ) tmp;
           tmp >>= 8;
           out[0] = (  unsigned char ) tmp;
          
           tmp = uu->time_mid;
           out[5] = (  unsigned char ) tmp;
           tmp >>= 8;
           out[4] = (  unsigned char ) tmp;
          
           tmp = uu->time_hi_and_version;
           out[7] = (  unsigned char ) tmp;
           tmp >>= 8;
           out[6] = (  unsigned char ) tmp;
          
           tmp = uu->clock_seq;
           out[9] = (  unsigned char ) tmp;
           tmp >>= 8;
           out[8] = (  unsigned char ) tmp;
          
           memcpy(  out+10,   uu->node,   6 );
          }
          

libmisc/uuid/parse.c

       1  /*
           * parse.c --- UUID parsing
           *
           * Copyright (  C ) 1996,   1997 Theodore Ts'o.
           *
           * %Begin-Header%
           * 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,   and the entire permission notice in its entirety,  
           * including the disclaimer of warranties.
           * 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. The name of the author may not be used to endorse or promote
           * products derived from this software without specific prior
           * written permission.
           *
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
           * WARRANTIES,   INCLUDING,   BUT NOT LIMITED TO,   THE IMPLIED WARRANTIES
           * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,   ALL OF
           * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
           * DAMAGE.
           * %End-Header%
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdlib.h>
          #include <stdio.h>
          #include <ctype.h>
          #include <string.h>
          
          #include "uuidP.h"
          
      46  int uuid_parse(  const char *in,   uuid_t uu )
          {
           struct uuid uuid;
           int i;
           const char *cp;
           char buf[3];
          
           if (  strlen(  in ) != 36 )
           return -1;
           for (  i=0,   cp = in; i <= 36; i++,  cp++ ) {
           if (  (  i == 8 ) || (  i == 13 ) || (  i == 18 ) ||
           (  i == 23 ) ) {
           if (  *cp == '-' )
           continue;
           else
           return -1;
           }
           if (  i== 36 )
           if (  *cp == 0 )
           continue;
           if (  !isxdigit(  (  unsigned char )*cp ) )
           return -1;
           }
           uuid.time_low = strtoul(  in,   NULL,   16 );
           uuid.time_mid = strtoul(  in+9,   NULL,   16 );
           uuid.time_hi_and_version = strtoul(  in+14,   NULL,   16 );
           uuid.clock_seq = strtoul(  in+19,   NULL,   16 );
           cp = in+24;
           buf[2] = 0;
           for (  i=0; i < 6; i++ ) {
           buf[0] = *cp++;
           buf[1] = *cp++;
           uuid.node[i] = strtoul(  buf,   NULL,   16 );
           }
          
           uuid_pack(  &uuid,   uu );
           return 0;
          }

libmisc/uuid/unpack.c

       1  /*
           * Internal routine for unpacking UUID
           *
           * Copyright (  C ) 1996,   1997 Theodore Ts'o.
           *
           * %Begin-Header%
           * 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,   and the entire permission notice in its entirety,  
           * including the disclaimer of warranties.
           * 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. The name of the author may not be used to endorse or promote
           * products derived from this software without specific prior
           * written permission.
           *
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
           * WARRANTIES,   INCLUDING,   BUT NOT LIMITED TO,   THE IMPLIED WARRANTIES
           * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,   ALL OF
           * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
           * DAMAGE.
           * %End-Header%
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          #include "uuidP.h"
          
      42  void uuid_unpack(  const uuid_t in,   struct uuid *uu )
          {
           const uint8_t *ptr = in;
           uint32_t tmp;
          
           tmp = *ptr++;
           tmp = (  tmp << 8 ) | *ptr++;
           tmp = (  tmp << 8 ) | *ptr++;
           tmp = (  tmp << 8 ) | *ptr++;
           uu->time_low = tmp;
          
           tmp = *ptr++;
           tmp = (  tmp << 8 ) | *ptr++;
           uu->time_mid = tmp;
          
           tmp = *ptr++;
           tmp = (  tmp << 8 ) | *ptr++;
           uu->time_hi_and_version = tmp;
          
           tmp = *ptr++;
           tmp = (  tmp << 8 ) | *ptr++;
           uu->clock_seq = tmp;
          
           memcpy(  uu->node,   ptr,   6 );
          }
          

libmisc/uuid/unparse.c

       1  /*
           * unparse.c -- convert a UUID to string
           *
           * Copyright (  C ) 1996,   1997 Theodore Ts'o.
           *
           * %Begin-Header%
           * 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,   and the entire permission notice in its entirety,  
           * including the disclaimer of warranties.
           * 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. The name of the author may not be used to endorse or promote
           * products derived from this software without specific prior
           * written permission.
           *
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
           * WARRANTIES,   INCLUDING,   BUT NOT LIMITED TO,   THE IMPLIED WARRANTIES
           * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,   ALL OF
           * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
           * DAMAGE.
           * %End-Header%
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdio.h>
          
          #include "uuidP.h"
          
          static const char *fmt_lower =
           "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
          
          static const char *fmt_upper =
           "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X";
          
          #ifdef UUID_UNPARSE_DEFAULT_UPPER
          #define FMT_DEFAULT fmt_upper
          #else
          #define FMT_DEFAULT fmt_lower
          #endif
          
      55  static void uuid_unparse_x(  const uuid_t uu,   char *out,   const char *fmt )
          {
           struct uuid uuid;
          
           uuid_unpack(  uu,   &uuid );
           sprintf(  out,   fmt,  
           uuid.time_low,   uuid.time_mid,   uuid.time_hi_and_version,  
           uuid.clock_seq >> 8,   uuid.clock_seq & 0xFF,  
           uuid.node[0],   uuid.node[1],   uuid.node[2],  
           uuid.node[3],   uuid.node[4],   uuid.node[5] );
          }
          
      67  void uuid_unparse_lower(  const uuid_t uu,   char *out )
          {
           uuid_unparse_x(  uu,   out,   fmt_lower );
          }
          
      72  void uuid_unparse_upper(  const uuid_t uu,   char *out )
          {
           uuid_unparse_x(  uu,   out,   fmt_upper );
          }
          
      77  void uuid_unparse(  const uuid_t uu,   char *out )
          {
           uuid_unparse_x(  uu,   out,   FMT_DEFAULT );
          }

libmisc/uuid/uuid_time.c

       1  /*
           * uuid_time.c --- Interpret the time field from a uuid. This program
           * violates the UUID abstraction barrier by reaching into the guts
           * of a UUID and interpreting it.
           *
           * Copyright (  C ) 1998,   1999 Theodore Ts'o.
           *
           * %Begin-Header%
           * 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,   and the entire permission notice in its entirety,  
           * including the disclaimer of warranties.
           * 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. The name of the author may not be used to endorse or promote
           * products derived from this software without specific prior
           * written permission.
           *
           * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
           * WARRANTIES,   INCLUDING,   BUT NOT LIMITED TO,   THE IMPLIED WARRANTIES
           * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,   ALL OF
           * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
           * DAMAGE.
           * %End-Header%
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef _WIN32
          #define _WIN32_WINNT 0x0500
          #include <windows.h>
          #define UUID MYUUID
          #endif
          
          #include <stdio.h>
          #ifdef HAVE_UNISTD_H
          #include <unistd.h>
          #endif
          #include <stdlib.h>
          #include <sys/types.h>
          #ifdef HAVE_SYS_TIME_H
          #include <sys/time.h>
          #endif
          #include <time.h>
          
          #include "uuidP.h"
          
      60  time_t uuid_time(  const uuid_t uu,   struct timeval *ret_tv )
          {
           struct timeval tv;
           struct uuid uuid;
           uint32_t high;
           uint64_t clock_reg;
          
           uuid_unpack(  uu,   &uuid );
          
           high = uuid.time_mid | (  (  uint32_t )(  uuid.time_hi_and_version & 0xFFF ) << 16 );
           clock_reg = uuid.time_low | (  (  uint64_t ) high << 32 );
          
           clock_reg -= (  (  (  uint64_t ) 0x01B21DD2 ) << 32 ) + 0x13814000;
           tv.tv_sec = clock_reg / 10000000;
           tv.tv_usec = (  clock_reg % 10000000 ) / 10;
          
           if (  ret_tv )
           *ret_tv = tv;
          
           return tv.tv_sec;
          }
          
      82  int uuid_type(  const uuid_t uu )
          {
           struct uuid uuid;
          
           uuid_unpack(  uu,   &uuid );
           return (  (  uuid.time_hi_and_version >> 12 ) & 0xF );
          }
          
      90  int uuid_variant(  const uuid_t uu )
          {
           struct uuid uuid;
           int var;
          
           uuid_unpack(  uu,   &uuid );
           var = uuid.clock_seq;
          
           if (  (  var & 0x8000 ) == 0 )
           return UUID_VARIANT_NCS;
           if (  (  var & 0x4000 ) == 0 )
           return UUID_VARIANT_DCE;
           if (  (  var & 0x2000 ) == 0 )
           return UUID_VARIANT_MICROSOFT;
           return UUID_VARIANT_OTHER;
          }
          
          #ifdef DEBUG
     108  static const char *variant_string(  int variant )
          {
           switch (  variant ) {
           case UUID_VARIANT_NCS:
           return "NCS";
           case UUID_VARIANT_DCE:
           return "DCE";
           case UUID_VARIANT_MICROSOFT:
           return "Microsoft";
           default:
           return "Other";
           }
          }
          
          
          int
     124  main(  int argc,   char **argv )
          {
           uuid_t buf;
           time_t time_reg;
           struct timeval tv;
           int type,   variant;
          
           if (  argc != 2 ) {
           fprintf(  stderr,   "Usage: %s uuid\n",   argv[0] );
           exit(  1 );
           }
           if (  uuid_parse(  argv[1],   buf ) ) {
           fprintf(  stderr,   "Invalid UUID: %s\n",   argv[1] );
           exit(  1 );
           }
           variant = uuid_variant(  buf );
           type = uuid_type(  buf );
           time_reg = uuid_time(  buf,   &tv );
          
           printf(  "UUID variant is %d (  %s )\n",   variant,   variant_string(  variant ) );
           if (  variant != UUID_VARIANT_DCE ) {
           printf(  "Warning: This program only knows how to interpret "
           "DCE UUIDs.\n\tThe rest of the output is likely "
           "to be incorrect!!\n" );
           }
           printf(  "UUID type is %d",   type );
           switch (  type ) {
           case 1:
           printf(  " (  time based )\n" );
           break;
           case 2:
           printf(  " (  DCE )\n" );
           break;
           case 3:
           printf(  " (  name-based )\n" );
           break;
           case 4:
           printf(  " (  random )\n" );
           break;
           default:
           printf(  "\n" );
           }
           if (  type != 1 ) {
           printf(  "Warning: not a time-based UUID,   so UUID time "
           "decoding will likely not work!\n" );
           }
           printf(  "UUID time is: (  %ld,   %ld ): %s\n",   tv.tv_sec,   tv.tv_usec,  
           ctime(  &time_reg ) );
          
           return 0;
          }
          #endif

posix/src/_execve.c

       1  /*
           * execve(   ) - POSIX 1003.1b 3.1.2
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: _execve.c,  v 1.2 2009/01/02 10:04:23 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <rtems/seterr.h>
          
      21  int _execve(  
           const char *path __attribute__(  (  unused ) ),  
           char *const argv[] __attribute__(  (  unused ) ),  
           char *const envp[] __attribute__(  (  unused ) )
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/adjtime.c

       1  /*
           * adjime(   ) function
           *
           * This method was initially added as part of porting NTP to RTEMS.
           * It is a BSD compatability function and now is available on
           * GNU/Linux.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: adjtime.c,  v 1.5 2008/12/16 17:35:58 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <sys/time.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/seterr.h>
          #include <rtems/score/tod.h>
          #include <rtems/posix/time.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/timespec.h>
          
          /*
           * At one point there was a static variable named adjustment
           * used by this implementation. I don't see any reason for it
           * to be here based upon the GNU/Linux documentation.
           */
          
      42  int adjtime(  
           struct timeval *delta,  
           struct timeval *olddelta
           )
          {
           struct timespec ts;
           long adjustment;
          
           /*
           * Simple validations
           */
           if (   !delta  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   delta->tv_usec >= TOD_MICROSECONDS_PER_SECOND  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   olddelta  ) {
           olddelta->tv_sec = 0;
           olddelta->tv_usec = 0;
           }
          
           /* convert delta to microseconds */
           adjustment = (  delta->tv_sec * TOD_MICROSECONDS_PER_SECOND );
           adjustment += delta->tv_usec;
          
           /* too small to account for */
           if (   adjustment < rtems_configuration_get_microseconds_per_tick(   )  )
           return 0;
          
           /*
           * This prevents context switches while we are adjusting the TOD
           */
          
           _Thread_Disable_dispatch(   );
          
           _TOD_Get(   &ts  );
          
           ts.tv_sec += delta->tv_sec;
           ts.tv_nsec += delta->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND;
          
           /* if adjustment is too much positive */
           while (   ts.tv_nsec >= TOD_NANOSECONDS_PER_SECOND  ) {
           ts.tv_nsec -= TOD_NANOSECONDS_PER_SECOND;
           ts.tv_sec++;
           }
          
           /* if adjustment is too much negative */
           while (   ts.tv_nsec <= (  -1 * TOD_NANOSECONDS_PER_SECOND )  ) {
           ts.tv_nsec += TOD_NANOSECONDS_PER_SECOND;
           ts.tv_sec--;
           }
          
           _TOD_Set(   &ts  );
          
           _Thread_Enable_dispatch(   );
          
           /* set the user's output */
           if (   olddelta  )
           *olddelta = *delta;
          
           return 0;
          }

posix/src/aio_cancel.c

       1  /*
           * Copyright 2010,   Alin Rus <alin.codejunkie@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: aio_cancel.c,  v 1.4 2010/08/24 12:04:43 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <aio.h>
          #include <rtems/posix/aio_misc.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          
          /*
           * aio_cancel
           *
           * Cancel an asynchronous I/O request
           *
           * Input parameters:
           * fildes - file descriptor
           * aiocbp - asynchronous I/O control block
           *
           * Output parameters:
           * AIO_CANCELED - if the requested operation(  s )
           * were canceled
           * AIO_NOTCANCELED - if at least one of the requested
           * operation(  s ) cannot be canceled
           */
          
          
      39  int aio_cancel(  int fildes,   struct aiocb *aiocbp )
          {
           rtems_aio_request_chain *r_chain;
           int result;
          
           pthread_mutex_lock (  &aio_request_queue.mutex );
          
           if (  aiocbp == NULL )
           {
           if (  fcntl (  fildes,   F_GETFL ) < 0 ) {
           pthread_mutex_unlock(  &aio_request_queue.mutex );
           rtems_set_errno_and_return_minus_one (  EBADF );
           }
          
           r_chain = rtems_aio_search_fd (  &aio_request_queue.work_req,  
           fildes,  
           0 );
           if (  r_chain == NULL )
           {
           if (  !rtems_chain_is_empty (  &aio_request_queue.idle_req ) )
           {
           r_chain = rtems_aio_search_fd (  &aio_request_queue.idle_req,  
           fildes,  
           0 );
           if (  r_chain == NULL ) {
           pthread_mutex_unlock(  &aio_request_queue.mutex );
           return AIO_ALLDONE;
           }
          
           rtems_chain_extract (  &r_chain->next_fd );
           rtems_aio_remove_fd (  r_chain );
           pthread_mutex_destroy (  &r_chain->mutex );
           pthread_cond_destroy (  &r_chain->mutex );
           free (  r_chain );
          
           pthread_mutex_unlock (  &aio_request_queue.mutex );
           return AIO_CANCELED;
           }
          
           pthread_mutex_unlock (  &aio_request_queue.mutex );
           return AIO_ALLDONE;
           }
          
           pthread_mutex_lock (  &r_chain->mutex );
           rtems_chain_extract (  &r_chain->next_fd );
           rtems_aio_remove_fd (  r_chain );
           pthread_mutex_unlock (  &r_chain->mutex );
           pthread_mutex_unlock (  &aio_request_queue.mutex );
           return AIO_CANCELED;
           }
           else
           {
           if (  aiocbp->aio_fildes != fildes ) {
           pthread_mutex_unlock (  &aio_request_queue.mutex );
           rtems_set_errno_and_return_minus_one (  EINVAL );
           }
          
           r_chain = rtems_aio_search_fd (  &aio_request_queue.work_req,  
           fildes,  
           0 );
           if (  r_chain == NULL )
           if (  !rtems_chain_is_empty (  &aio_request_queue.idle_req ) )
           {
           r_chain = rtems_aio_search_fd (  &aio_request_queue.idle_req,  
           fildes,  
           0 );
           if (  r_chain == NULL )
           {
           pthread_mutex_unlock (  &aio_request_queue.mutex );
           rtems_set_errno_and_return_minus_one (  EINVAL );
           }
          
           result = rtems_aio_remove_req (  &r_chain->next_fd,   aiocbp );
           pthread_mutex_unlock (  &aio_request_queue.mutex );
           return result;
          
           }
          
           pthread_mutex_lock (  &r_chain->mutex );
           result = rtems_aio_remove_req (  &r_chain->next_fd,   aiocbp );
           pthread_mutex_unlock (  &r_chain->mutex );
           pthread_mutex_unlock (  &aio_request_queue.mutex );
           return result;
          
           }
          
           return AIO_ALLDONE;
          }

posix/src/aio_error.c

       1  /*
           * Copyright 2010,   Alin Rus <alin.codejunkie@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: aio_error.c,  v 1.3 2010/08/16 05:46:09 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <aio.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          
          /*
           * aio_error
           *
           * Retrieve errors status for an asynchronous I/O operation
           *
           * Input parameters:
           * aiocbp - asynchronous I/O control block
           *
           * Output parameters:
           * aiocbp->error_code
           */
          
          
          int
      35  aio_error (  const struct aiocb *aiocbp )
          {
           return aiocbp->error_code;
          }

posix/src/aio_fsync.c

       1  /*
           * Copyright 2010,   Alin Rus <alin.codejunkie@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: aio_fsync.c,  v 1.3 2010/08/20 09:08:05 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <aio.h>
          #include <errno.h>
          #include <stdlib.h>
          #include <rtems/posix/aio_misc.h>
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          
          /*
           * aio_fsync
           *
           * Asynchronous file synchronization
           *
           * Input parameters:
           * op - O_SYNC
           * aiocbp - asynchronous I/O control block
           *
           * Output parameters:
           * -1 - request could not pe enqueued
           * - FD not opened for write
           * - not enough memory
           * - op is not O_SYNC
           * 0 - otherwise
           */
          
      39  int aio_fsync(  
           int op,  
           struct aiocb *aiocbp
           )
          {
           rtems_aio_request *req;
           int mode;
          
           if (  op != O_SYNC )
           rtems_aio_set_errno_return_minus_one (  EINVAL,   aiocbp );
          
           mode = fcntl (  aiocbp->aio_fildes,   F_GETFL );
           if (  !(  (  (  mode & O_ACCMODE ) == O_WRONLY ) || (  (  mode & O_ACCMODE ) == O_RDWR ) ) )
           rtems_aio_set_errno_return_minus_one (  EBADF,   aiocbp );
          
           req = malloc (  sizeof (  rtems_aio_request ) );
           if (  req == NULL )
           rtems_aio_set_errno_return_minus_one (  EAGAIN,   aiocbp );
          
           req->aiocbp = aiocbp;
           req->aiocbp->aio_lio_opcode = LIO_SYNC;
          
           return rtems_aio_enqueue (  req );
          
          }

posix/src/aio_misc.c

       1  /*
           * Copyright 2010,   Alin Rus <alin.codejunkie@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: aio_misc.c,  v 1.4 2010/08/20 14:37:08 ralf Exp $
           */
          
          #include <pthread.h>
          #include <stdlib.h>
          #include <unistd.h>
          #include <time.h>
          #include <rtems/posix/aio_misc.h>
          
      17  static void *rtems_aio_handle (  void *arg );
          
          rtems_aio_queue aio_request_queue;
          
          /*
           * rtems_aio_init
           *
           * Initialize the request queue for aio
           *
           * Input parameters:
           * NONE
           *
           * Output parameters:
           * 0 - if initialization succeeded
           */
          
          int
      34  rtems_aio_init (  void )
          {
           int result = 0;
          
           result = pthread_attr_init (  &aio_request_queue.attr );
           if (  result != 0 )
           return result;
          
           result =
           pthread_attr_setdetachstate (  &aio_request_queue.attr,  
           PTHREAD_CREATE_DETACHED );
           if (  result != 0 )
           pthread_attr_destroy (  &aio_request_queue.attr );
          
          
           result = pthread_mutex_init (  &aio_request_queue.mutex,   NULL );
           if (  result != 0 )
           pthread_attr_destroy (  &aio_request_queue.attr );
          
          
           result = pthread_cond_init (  &aio_request_queue.new_req,   NULL );
           if (  result != 0 ) {
           pthread_mutex_destroy (  &aio_request_queue.mutex );
           pthread_attr_destroy (  &aio_request_queue.attr );
           }
          
           rtems_chain_initialize_empty (  &aio_request_queue.work_req );
           rtems_chain_initialize_empty (  &aio_request_queue.idle_req );
          
           aio_request_queue.active_threads = 0;
           aio_request_queue.idle_threads = 0;
           aio_request_queue.initialized = AIO_QUEUE_INITIALIZED;
          
           return result;
          }
          
          /*
           * rtems_aio_search_fd
           *
           * Search and create chain of requests for given FD
           *
           * Input parameters:
           * chain - chain of FD chains
           * fildes - file descriptor to search
           * create - if 1 search and create
           * - if 0 just search
           *
           * Output parameters:
           * r_chain - NULL if create == 0 and there is
           * no chain for given fildes
           * - pointer to chain is there exists
           * a chain for given fildes
           * - pointer to newly create chain if
           * create == 1
           *
           */
          
          rtems_aio_request_chain *
      92  rtems_aio_search_fd (  rtems_chain_control *chain,   int fildes,   int create )
          {
           rtems_aio_request_chain *r_chain;
           rtems_chain_node *node;
          
           node = chain->first;
           r_chain = (  rtems_aio_request_chain * ) node;
          
           while (  r_chain->fildes < fildes && !rtems_chain_is_tail (  chain,   node ) ) {
           node = node->next;
           r_chain = (  rtems_aio_request_chain * ) node;
           }
          
           if (  r_chain->fildes == fildes )
           r_chain->new_fd = 0;
           else {
           if (  create == 0 )
           r_chain = NULL;
           else {
           r_chain = malloc (  sizeof (  rtems_aio_request_chain ) );
           rtems_chain_initialize_empty (  &r_chain->perfd );
          
           if (  rtems_chain_is_empty (  chain ) )
           rtems_chain_prepend (  chain,   &r_chain->next_fd );
           else
           rtems_chain_insert (  node->previous,   &r_chain->next_fd );
          
           r_chain->new_fd = 1;
           }
           }
           return r_chain;
          }
          
          /*
           * rtems_aio_insert_prio
           *
           * Add request to given FD chain. The chain is ordered
           * by priority
           *
           * Input parameters:
           * chain - chain of requests for a given FD
           * req - request (  see aio_misc.h )
           *
           * Output parameters:
           * NONE
           */
          
          void
     140  rtems_aio_insert_prio (  rtems_chain_control *chain,   rtems_aio_request *req )
          {
           rtems_chain_node *node;
          
           AIO_printf (  "FD exists \n" );
           node = chain->first;
          
           if (  rtems_chain_is_empty (  chain ) ) {
           AIO_printf (  "First in chain \n" );
           rtems_chain_prepend (  chain,   &req->next_prio );
           } else {
           AIO_printf (  "Add by priority \n" );
           int prio = (  (  rtems_aio_request * ) node )->aiocbp->aio_reqprio;
          
           while (  req->aiocbp->aio_reqprio > prio &&
           !rtems_chain_is_tail (  chain,   node ) ) {
           node = node->next;
           prio = (  (  rtems_aio_request * ) node )->aiocbp->aio_reqprio;
           }
          
           rtems_chain_insert (  node->previous,   &req->next_prio );
          
           }
          }
          
          /*
           * rtems_aio_remove_fd
           *
           * Removes all the requests in a fd chain
           *
           * Input parameters:
           * r_chain - pointer to the fd chain request
           *
           * Output parameters:
           * NONE
           */
          
     177  void rtems_aio_remove_fd (  rtems_aio_request_chain *r_chain )
          {
           rtems_chain_control *chain;
           rtems_chain_node *node;
          
           chain = &r_chain->perfd;
           node = chain->first;
          
           while (  !rtems_chain_is_tail (  chain,   node ) )
           {
           rtems_chain_extract (  node );
           rtems_aio_request *req = (  rtems_aio_request * ) node;
           req->aiocbp->error_code = ECANCELED;
           req->aiocbp->return_value = -1;
           free (  req );
           }
          }
          
          /*
           * rtems_aio_remove_req
           *
           * Removes request from given chain
           *
           * Input parameters:
           * chain - pointer to fd chain which may contain
           * the request
           * aiocbp - pointer to request that needs to be
           * canceled
           *
           * Output parameters:
           * AIO_NOTCANCELED - if request was not canceled
           * AIO_CANCELED - if request was canceled
           */
          
     211  int rtems_aio_remove_req (  rtems_chain_control *chain,   struct aiocb *aiocbp )
          {
           rtems_chain_node *node = chain->first;
           rtems_aio_request *current;
          
           current = (  rtems_aio_request * ) node;
          
           while (  !rtems_chain_is_tail (  chain,   node ) && current->aiocbp != aiocbp ) {
           node = node->next;
           current = (  rtems_aio_request * ) node;
           }
          
           if (  rtems_chain_is_tail (  chain,   node ) )
           return AIO_NOTCANCELED;
           else
           {
           rtems_chain_extract (  node );
           current->aiocbp->error_code = ECANCELED;
           current->aiocbp->return_value = -1;
           free (  current );
           }
          
           return AIO_CANCELED;
          }
          
          /*
           * rtems_aio_enqueue
           *
           * Enqueue requests,   and creates threads to process them
           *
           * Input parameters:
           * req - see aio_misc.h
           *
           * Output parameters:
           * 0 - if request was added to queue
           * errno - otherwise
           */
          
          int
     250  rtems_aio_enqueue (  rtems_aio_request *req )
          {
          
           rtems_aio_request_chain *r_chain;
           rtems_chain_control *chain;
           pthread_t thid;
           int result,   policy;
           struct sched_param param;
          
           /* The queue should be initialized */
           AIO_assert (  aio_request_queue.initialized != AIO_QUEUE_INITIALIZED );
          
           result = pthread_mutex_lock (  &aio_request_queue.mutex );
           if (  result != 0 ) {
           free (  req );
           return result;
           }
          
           /* _POSIX_PRIORITIZED_IO and _POSIX_PRIORITY_SCHEDULING are defined,  
           we can use aio_reqprio to lower the priority of the request */
           pthread_getschedparam (  pthread_self(   ),   &policy,   &param );
          
           req->caller_thread = pthread_self (   );
           req->priority = param.sched_priority - req->aiocbp->aio_reqprio;
           req->policy = policy;
           req->aiocbp->error_code = EINPROGRESS;
           req->aiocbp->return_value = 0;
          
           if (  (  aio_request_queue.idle_threads == 0 ) &&
           aio_request_queue.active_threads < AIO_MAX_THREADS )
           /* we still have empty places on the active_threads chain */
           {
           chain = &aio_request_queue.work_req;
           r_chain = rtems_aio_search_fd (  chain,   req->aiocbp->aio_fildes,   1 );
          
           if (  r_chain->new_fd == 1 ) {
           rtems_chain_prepend (  &r_chain->perfd,   &req->next_prio );
           r_chain->new_fd = 0;
           pthread_mutex_init (  &r_chain->mutex,   NULL );
           pthread_cond_init (  &r_chain->cond,   NULL );
          
           AIO_printf (  "New thread" );
           result = pthread_create (  &thid,   &aio_request_queue.attr,  
           rtems_aio_handle,   (  void * ) r_chain );
           if (  result != 0 ) {
           pthread_mutex_unlock (  &aio_request_queue.mutex );
           return result;
           }
           ++aio_request_queue.active_threads;
           }
           else {
           /* put request in the fd chain it belongs to */
           pthread_mutex_lock (  &r_chain->mutex );
           rtems_aio_insert_prio (  &r_chain->perfd,   req );
           pthread_cond_signal (  &r_chain->cond );
           pthread_mutex_unlock (  &r_chain->mutex );
           }
           }
           else
           {
           /* the maximum number of threads has been already created
           even though some of them might be idle.
           The request belongs to one of the active fd chain */
           r_chain = rtems_aio_search_fd (  &aio_request_queue.work_req,  
           req->aiocbp->aio_fildes,   0 );
           if (  r_chain != NULL )
           {
           pthread_mutex_lock (  &r_chain->mutex );
           rtems_aio_insert_prio (  &r_chain->perfd,   req );
           pthread_cond_signal (  &r_chain->cond );
           pthread_mutex_unlock (  &r_chain->mutex );
          
           } else {
          
           /* or to the idle chain */
           chain = &aio_request_queue.idle_req;
           r_chain = rtems_aio_search_fd (  chain,   req->aiocbp->aio_fildes,   1 );
          
           if (  r_chain->new_fd == 1 ) {
           /* If this is a new fd chain we signal the idle threads that
           might be waiting for requests */
           rtems_chain_prepend (  &r_chain->perfd,   &req->next_prio );
           r_chain->new_fd = 0;
           pthread_mutex_init (  &r_chain->mutex,   NULL );
           pthread_cond_init (  &r_chain->cond,   NULL );
           pthread_cond_signal (  &aio_request_queue.new_req );
           } else
           /* just insert the request in the existing fd chain */
           rtems_aio_insert_prio (  &r_chain->perfd,   req );
           }
           }
          
           pthread_mutex_unlock (  &aio_request_queue.mutex );
           return 0;
          }
          
          /*
           * rtems_aio_handle
           *
           * Thread processing requests
           *
           * Input parameters:
           * arg - the chain for the fd to be worked on
           *
           * Output parameters:
           * NULL - if error
           */
          
          static void *
     359  rtems_aio_handle (  void *arg )
          {
          
           rtems_aio_request_chain *r_chain = arg;
           rtems_aio_request *req;
           rtems_chain_control *chain;
           rtems_chain_node *node;
           int result,   policy;
           struct sched_param param;
          
           AIO_printf (  "Thread started\n" );
          
           while (  1 ) {
          
           /* acquire the mutex of the current fd chain.
           we don't need to lock the queue mutex since we can
           add requests to idle fd chains or even active ones
           if the working request has been extracted from the
           chain */
           result = pthread_mutex_lock (  &r_chain->mutex );
           if (  result != 0 )
           return NULL;
          
           chain = &r_chain->perfd;
          
           /* If the locked chain is not empty,   take the first
           request extract it,   unlock the chain and process
           the request,   in this way the user can supply more
           requests to this fd chain */
           if (  !rtems_chain_is_empty (  chain ) ) {
          
           node = chain->first;
           req = (  rtems_aio_request * ) node;
          
           /* See _POSIX_PRIORITIZE_IO and _POSIX_PRIORITY_SCHEDULING
           discussion in rtems_aio_enqueue (   ) */
           pthread_getschedparam (  pthread_self(   ),   &policy,   &param );
           param.sched_priority = req->priority;
           pthread_setschedparam (  pthread_self(   ),   req->policy,   &param );
          
           rtems_chain_extract (  node );
          
           pthread_mutex_unlock (  &r_chain->mutex );
          
           switch (  req->aiocbp->aio_lio_opcode ) {
           case LIO_READ:
           result = pread (  req->aiocbp->aio_fildes,  
           (  void * ) req->aiocbp->aio_buf,  
           req->aiocbp->aio_nbytes,   req->aiocbp->aio_offset );
           break;
          
           case LIO_WRITE:
           result = pwrite (  req->aiocbp->aio_fildes,  
           (  void * ) req->aiocbp->aio_buf,  
           req->aiocbp->aio_nbytes,   req->aiocbp->aio_offset );
           break;
          
           case LIO_SYNC:
           result = fsync (  req->aiocbp->aio_fildes );
           break;
          
           default:
           result = -1;
           }
           if (  result == -1 ) {
           req->aiocbp->return_value = -1;
           req->aiocbp->error_code = errno;
           } else {
           req->aiocbp->return_value = result;
           req->aiocbp->error_code = 0;
           }
          
           // notification needed for lio
          
           } else {
           /* If the fd chain is empty we unlock the fd chain
           and we lock the queue chain,   this will ensure that
           we have at most one request comming to our fd chain
           when we check.
          
           If there was no request added sleep for 3 seconds and
           wait for a signal on chain,   this will unlock the queue.
           The fd chain is already unlocked */
          
           struct timespec timeout;
          
           pthread_mutex_unlock (  &r_chain->mutex );
           pthread_mutex_lock (  &aio_request_queue.mutex );
           if (  rtems_chain_is_empty (  chain ) )
           {
           clock_gettime (  CLOCK_REALTIME,   &timeout );
           timeout.tv_sec += 3;
           timeout.tv_nsec = 0;
           result = pthread_cond_timedwait (  &r_chain->cond,  
           &aio_request_queue.mutex,   &timeout );
          
           /* If no requests were added to the chain we delete the fd chain from
           the queue and start working with idle fd chains */
           if (  result == ETIMEDOUT ) {
           rtems_chain_extract (  &r_chain->next_fd );
           pthread_mutex_destroy (  &r_chain->mutex );
           pthread_cond_destroy (  &r_chain->cond );
           free (  r_chain );
          
           /* If the idle chain is empty sleep for 3 seconds and wait for a
           signal. The thread now becomes idle. */
           if (  rtems_chain_is_empty (  &aio_request_queue.idle_req ) ) {
           ++aio_request_queue.idle_threads;
           clock_gettime (  CLOCK_REALTIME,   &timeout );
           timeout.tv_sec += 3;
           timeout.tv_nsec = 0;
           result = pthread_cond_timedwait (  &aio_request_queue.new_req,  
           &aio_request_queue.mutex,  
           &timeout );
          
           /* If no new fd chain was added in the idle requests
           then this thread is finished */
           if (  result == ETIMEDOUT ) {
           pthread_mutex_unlock (  &aio_request_queue.mutex );
           return NULL;
           }
          
           /* Otherwise move this chain to the working chain and
           start the loop all over again */
           --aio_request_queue.idle_threads;
           node = aio_request_queue.idle_req.first;
           rtems_chain_extract (  node );
           r_chain = rtems_aio_search_fd (  &aio_request_queue.work_req,  
           (  (  rtems_aio_request_chain * )node )->fildes,  
           1 );
           r_chain->new_fd = 0;
           pthread_mutex_init (  &r_chain->mutex,   NULL );
           pthread_cond_init (  &r_chain->cond,   NULL );
          
           r_chain->perfd = (  (  rtems_aio_request_chain * )node )->perfd;
           }
           else
           /* If there was a request added in the initial fd chain then release
           the mutex and process it */
           pthread_mutex_unlock (  &aio_request_queue.mutex );
           }
           }
           }
           }
          
          
           AIO_printf (  "Thread finished\n" );
           return NULL;
          }

posix/src/aio_read.c

       1  /*
           * Copyright 2010,   Alin Rus <alin.codejunkie@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: aio_read.c,  v 1.4 2010/08/24 11:50:35 ralf Exp $
           */
          
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <aio.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <rtems/posix/aio_misc.h>
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <stdlib.h>
          
          /*
           * aio_read
           *
           * Asynchronous write to a file
           *
           * Input parameters:
           * aiocbp - asynchronous I/O control block
           *
           * Output parameters:
           * -1 - request could not pe enqueued
           * - FD not opened for write
           * - invalid aio_reqprio or aio_offset or
           * aio_nbytes
           * - not enough memory
           * 0 - otherwise
           */
          
          int
      42  aio_read (  struct aiocb *aiocbp )
          {
           rtems_aio_request *req;
           int mode;
          
           mode = fcntl (  aiocbp->aio_fildes,   F_GETFL );
           if (  !(  (  (  mode & O_ACCMODE ) == O_RDONLY ) || (  (  mode & O_ACCMODE ) == O_RDWR ) ) )
           rtems_aio_set_errno_return_minus_one (  EBADF,   aiocbp );
          
           if (  aiocbp->aio_reqprio < 0 || aiocbp->aio_reqprio > AIO_PRIO_DELTA_MAX )
           rtems_aio_set_errno_return_minus_one (  EINVAL,   aiocbp );
          
           if (  aiocbp->aio_offset < 0 )
           rtems_aio_set_errno_return_minus_one (  EINVAL,   aiocbp );
          
           req = malloc (  sizeof (  rtems_aio_request ) );
           if (  req == NULL )
           rtems_aio_set_errno_return_minus_one (  EAGAIN,   aiocbp );
          
           req->aiocbp = aiocbp;
           req->aiocbp->aio_lio_opcode = LIO_READ;
          
           return rtems_aio_enqueue (  req );
          }

posix/src/aio_return.c

       1  /*
           * Copyright 2010,   Alin Rus <alin.codejunkie@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: aio_return.c,  v 1.4 2010/08/16 05:46:09 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <aio.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          
          /*
           * aio_return
           *
           * Retrieve return status of an asynchronous I/O operation
           *
           * Input parameters:
           * aiocbp - asynchronous I/O control block
           *
           * Output parameters:
           * aiocbp->return_value
           */
          
          ssize_t
      34  aio_return (  const struct aiocb *aiocbp )
          {
           return aiocbp->return_value;
          }

posix/src/aio_suspend.c

       1  /*
           * 6.7.7 Wait for Asynchronous I/O Request,   P1003.1b-1993,   p. 164
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: aio_suspend.c,  v 1.3 2009/01/02 10:04:23 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <aio.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          
      24  int aio_suspend(  
           const struct aiocb * const list[] __attribute__(  (  unused ) ),  
           int nent __attribute__(  (  unused ) ),  
           const struct timespec *timeout __attribute__(  (  unused ) )
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/aio_write.c

       1  /*
           * Copyright 2010,   Alin Rus <alin.codejunkie@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: aio_write.c,  v 1.4 2010/08/24 06:46:29 ralf Exp $
           */
          
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <aio.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <rtems/posix/aio_misc.h>
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <stdlib.h>
          
          /*
           * aio_write
           *
           * Asynchronous write to a file
           *
           * Input parameters:
           * aiocbp - asynchronous I/O control block
           *
           * Output parameters:
           * -1 - request could not be enqueued
           * - FD not opened for write
           * - invalid aio_reqprio or aio_offset or
           * aio_nbytes
           * - not enough memory
           * 0 - otherwise
           */
          
          int
      42  aio_write (  struct aiocb *aiocbp )
          {
           rtems_aio_request *req;
           int mode;
          
           mode = fcntl (  aiocbp->aio_fildes,   F_GETFL );
           if (  !(  (  (  mode & O_ACCMODE ) == O_WRONLY ) || (  (  mode & O_ACCMODE ) == O_RDWR ) ) )
           rtems_aio_set_errno_return_minus_one (  EBADF,   aiocbp );
          
           if (  aiocbp->aio_reqprio < 0 || aiocbp->aio_reqprio > AIO_PRIO_DELTA_MAX )
           rtems_aio_set_errno_return_minus_one (  EINVAL,   aiocbp );
          
           if (  aiocbp->aio_offset < 0 )
           rtems_aio_set_errno_return_minus_one (  EINVAL,   aiocbp );
          
           req = malloc (  sizeof (  rtems_aio_request ) );
           if (  req == NULL )
           rtems_aio_set_errno_return_minus_one (  EAGAIN,   aiocbp );
          
           req->aiocbp = aiocbp;
           req->aiocbp->aio_lio_opcode = LIO_WRITE;
          
           return rtems_aio_enqueue (  req );
          }

posix/src/alarm.c

       1  /*
           * 3.4.1 Schedule Alarm,   P1003.1b-1993,   p. 79
           */
          
          /* COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: alarm.c,  v 1.16 2010/04/30 08:37:26 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          
          /*PAGE
           *
           * _POSIX_signals_Alarm_TSR
           */
          
      30  void _POSIX_signals_Alarm_TSR(  
           Objects_Id id __attribute__(  (  unused ) ),  
           void *argument __attribute__(  (  unused ) )
           )
          {
           int status;
          
           status = kill(   getpid(   ),   SIGALRM  );
           /* XXX can't print from an ISR,   should this be fatal? */
          }
          
      41  unsigned int alarm(  
           unsigned int seconds
           )
          {
           unsigned int remaining = 0;
           Watchdog_Control *the_timer;
          
           the_timer = &_POSIX_signals_Alarm_timer;
          
           /*
           * Initialize the timer used to implement alarm(   ).
           */
          
           if (   !the_timer->routine  ) {
           _Watchdog_Initialize(   the_timer,   _POSIX_signals_Alarm_TSR,   0,   NULL  );
           } else {
           Watchdog_States state;
          
           state = _Watchdog_Remove(   the_timer  );
           if (   (  state == WATCHDOG_ACTIVE ) || (  state == WATCHDOG_REMOVE_IT )  ) {
           /*
           * The stop_time and start_time fields are snapshots of ticks since
           * boot. Since alarm(   ) is dealing in seconds,   we must account for
           * this.
           */
          
           remaining = the_timer->initial -
           (  (  the_timer->stop_time - the_timer->start_time ) / TOD_TICKS_PER_SECOND );
           }
           }
          
           if (   seconds  )
           _Watchdog_Insert_seconds(   the_timer,   seconds  );
          
           return remaining;
          }

posix/src/barrierattrdestroy.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barrierattrdestroy.c,  v 1.3 2009/02/03 10:10:41 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * Barrier Initialization Attributes
           */
          
      32  int pthread_barrierattr_destroy(  
           pthread_barrierattr_t *attr
           )
          {
           if (   !attr || attr->is_initialized == false  )
           return EINVAL;
          
           attr->is_initialized = false;
           return 0;
          }

posix/src/barrierattrgetpshared.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barrierattrgetpshared.c,  v 1.2 2007/12/17 16:19:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          /*PAGE
           *
           * Barrier Attributes Get Process Shared
           */
          
      24  int pthread_barrierattr_getpshared(  
           const pthread_barrierattr_t *attr,  
           int *pshared
           )
          {
           if (   !attr  )
           return EINVAL;
          
           if (   !attr->is_initialized  )
           return EINVAL;
          
           *pshared = attr->process_shared;
           return 0;
          }

posix/src/barrierattrinit.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barrierattrinit.c,  v 1.3 2009/02/03 10:10:42 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          
          /*PAGE
           *
           * Barrier Attributes Initialization
           */
          
      26  int pthread_barrierattr_init(  
           pthread_barrierattr_t *attr
           )
          {
           if (   !attr  )
           return EINVAL;
          
           attr->is_initialized = true;
           attr->process_shared = PTHREAD_PROCESS_PRIVATE;
           return 0;
          }

posix/src/barrierattrsetpshared.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barrierattrsetpshared.c,  v 1.2 2007/12/17 16:19:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          /*PAGE
           *
           * Barrier Attributes Set Process Shared
           */
          
      24  int pthread_barrierattr_setpshared(  
           pthread_barrierattr_t *attr,  
           int pshared
           )
          {
           if (   !attr  )
           return EINVAL;
          
           if (   !attr->is_initialized  )
           return EINVAL;
          
           switch (   pshared  ) {
           case PTHREAD_PROCESS_SHARED:
           case PTHREAD_PROCESS_PRIVATE:
           attr->process_shared = pshared;
           return 0;
          
           default:
           return EINVAL;
           }
          }

posix/src/cancel.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cancel.c,  v 1.19 2009/10/10 16:03:38 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/cancel.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/threadsup.h>
          
          /*
           * 18.2.1 Canceling Execution of a Thread,   P1003.1c/Draft 10,   p. 181
           */
          
      32  int pthread_cancel(  
           pthread_t thread
           )
          {
           Thread_Control *the_thread;
           POSIX_API_Control *thread_support;
           Objects_Locations location;
          
           /*
           * Don't even think about deleting a resource from an ISR.
           */
          
           if (   _ISR_Is_in_progress(   )  )
           return EPROTO;
          
           the_thread = _POSIX_Threads_Get(   thread,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           thread_support->cancelation_requested = 1;
          
           /* This enables dispatch implicitly */
           _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch(   the_thread  );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/canceleval.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: canceleval.c,  v 1.4 2009/11/30 15:44:20 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          #include <rtems/posix/cancel.h>
          #include <rtems/posix/pthread.h>
          
      22  void _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch(  
           Thread_Control *the_thread
           )
          {
           POSIX_API_Control *thread_support;
          
           thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           if (   thread_support->cancelability_state == PTHREAD_CANCEL_ENABLE &&
           thread_support->cancelability_type == PTHREAD_CANCEL_ASYNCHRONOUS &&
           thread_support->cancelation_requested  ) {
           _Thread_Unnest_dispatch(   );
           _POSIX_Thread_Exit(   the_thread,   PTHREAD_CANCELED  );
           } else
           _Thread_Enable_dispatch(   );
          
          }

posix/src/cancelrun.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cancelrun.c,  v 1.11 2008/05/22 20:38:03 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/cancel.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/threadsup.h>
          
      28  void _POSIX_Threads_cancel_run(  
           Thread_Control *the_thread
           )
          {
           POSIX_Cancel_Handler_control *handler;
           Chain_Control *handler_stack;
           POSIX_API_Control *thread_support;
           ISR_Level level;
          
           thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           handler_stack = &thread_support->Cancellation_Handlers;
          
           thread_support->cancelability_state = PTHREAD_CANCEL_DISABLE;
          
           while (   !_Chain_Is_empty(   handler_stack  )  ) {
           _ISR_Disable(   level  );
           handler = (  POSIX_Cancel_Handler_control * )
           _Chain_Tail(   handler_stack  )->previous;
           _Chain_Extract_unprotected(   &handler->Node  );
           _ISR_Enable(   level  );
          
           (  *handler->routine )(   handler->arg  );
          
           _Workspace_Free(   handler  );
           }
          }

posix/src/cleanuppop.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cleanuppop.c,  v 1.7 2008/01/18 16:31:55 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/cancel.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/threadsup.h>
          
          /*PAGE
           *
           * 18.2.3.1 Establishing Cancellation Handlers,   P1003.1c/Draft 10,   p. 184
           */
          
      33  void pthread_cleanup_pop(  
           int execute
           )
          {
           POSIX_Cancel_Handler_control *handler;
           POSIX_Cancel_Handler_control tmp_handler;
           Chain_Control *handler_stack;
           POSIX_API_Control *thread_support;
           ISR_Level level;
          
           thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
          
           handler_stack = &thread_support->Cancellation_Handlers;
          
           /*
           * We need interrupts disabled to safely check the chain and pull
           * the last element off. But we also need dispatching disabled to
           * ensure that we do not get prempted and deleted while we are holding
           * memory that needs to be freed.
           */
          
           _Thread_Disable_dispatch(   );
           _ISR_Disable(   level  );
          
           if (   _Chain_Is_empty(   handler_stack  )  ) {
           _Thread_Enable_dispatch(   );
           _ISR_Enable(   level  );
           return;
           }
          
           handler = (  POSIX_Cancel_Handler_control * )
           _Chain_Tail(   handler_stack  )->previous;
           _Chain_Extract_unprotected(   &handler->Node  );
          
           _ISR_Enable(   level  );
          
           tmp_handler = *handler;
          
           _Workspace_Free(   handler  );
          
           _Thread_Enable_dispatch(   );
          
           if (   execute  )
           (  *tmp_handler.routine )(   tmp_handler.arg  );
          }

posix/src/cleanuppush.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cleanuppush.c,  v 1.7 2009/11/30 15:44:20 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/cancel.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/threadsup.h>
          
          /*PAGE
           *
           * 18.2.3.1 Establishing Cancellation Handlers,   P1003.1c/Draft 10,   p. 184
           */
          
      33  void pthread_cleanup_push(  
           void (  *routine )(   void *  ),  
           void *arg
           )
          {
           POSIX_Cancel_Handler_control *handler;
           Chain_Control *handler_stack;
           POSIX_API_Control *thread_support;
          
           /*
           * The POSIX standard does not address what to do when the routine
           * is NULL. It also does not address what happens when we cannot
           * allocate memory or anything else bad happens.
           */
           if (   !routine  )
           return;
          
           _Thread_Disable_dispatch(   );
           handler = _Workspace_Allocate(   sizeof(   POSIX_Cancel_Handler_control  )  );
          
           if (   handler  ) {
           thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
          
           handler_stack = &thread_support->Cancellation_Handlers;
          
           handler->routine = routine;
           handler->arg = arg;
          
           _Chain_Append(   handler_stack,   &handler->Node  );
           }
           _Thread_Enable_dispatch(   );
          }

posix/src/clockgetcpuclockid.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockgetcpuclockid.c,  v 1.6 2007/12/13 16:52:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          
          #include <rtems/seterr.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 20.1.3 Accessing a Process CPU-time CLock,   P1003.4b/D8,   p. 55
           */
          
      32  int clock_getcpuclockid(  
           pid_t pid,  
           clockid_t *clock_id
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/clockgetenableattr.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockgetenableattr.c,  v 1.6 2007/12/13 16:52:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          
          #include <rtems/seterr.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 20.1.5 CPU-time Clock Attribute Access,   P1003.4b/D8,   p. 58
           */
          
      32  int clock_getenable_attr(  
           clockid_t clock_id,  
           int *attr
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/clockgetres.c

       1  /*
           * $Id: clockgetres.c,  v 1.11 2009/11/30 15:44:20 ralf Exp $
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockgetres.c,  v 1.11 2009/11/30 15:44:20 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 14.2.1 Clocks,   P1003.1b-1993,   p. 263
           */
          
      36  int clock_getres(  
           clockid_t clock_id,  
           struct timespec *res
           )
          {
           if (   !res  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           switch (   clock_id  ) {
          
           /*
           * All time in rtems is based on the same clock tick.
           */
          
           case CLOCK_REALTIME:
           case CLOCK_PROCESS_CPUTIME:
           case CLOCK_THREAD_CPUTIME:
           if (   res  ) {
           res->tv_sec = rtems_configuration_get_microseconds_per_tick(   ) /
           TOD_MICROSECONDS_PER_SECOND;
           res->tv_nsec = rtems_configuration_get_nanoseconds_per_tick(   );
           }
           break;
          
           default:
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           }
           return 0;
          }

posix/src/clockgettime.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockgettime.c,  v 1.14 2009/11/30 15:44:20 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 14.2.1 Clocks,   P1003.1b-1993,   p. 263
           */
          
      31  int clock_gettime(  
           clockid_t clock_id,  
           struct timespec *tp
           )
          {
           if (   !tp  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   clock_id == CLOCK_REALTIME  ) {
           _TOD_Get(  tp );
           return 0;
           }
          #ifdef CLOCK_MONOTONIC
           if (   clock_id == CLOCK_MONOTONIC  ) {
           _TOD_Get_uptime_as_timespec(   tp  );
           return 0;
           }
          #endif
          
          #ifdef _POSIX_CPUTIME
           if (   clock_id == CLOCK_PROCESS_CPUTIME  ) {
           _TOD_Get_uptime_as_timespec(   tp  );
           return 0;
           }
          #endif
          
          #ifdef _POSIX_THREAD_CPUTIME
           if (   clock_id == CLOCK_THREAD_CPUTIME  )
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          #endif
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           return 0;
          }

posix/src/clocksetenableattr.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clocksetenableattr.c,  v 1.6 2007/12/13 16:52:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          
          #include <rtems/seterr.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 20.1.5 CPU-time Clock Attribute Access,   P1003.4b/D8,   p. 58
           */
          
      32  int clock_setenable_attr(  
           clockid_t clock_id,  
           int attr
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/clocksettime.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clocksettime.c,  v 1.10 2008/02/01 00:44:15 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 14.2.1 Clocks,   P1003.1b-1993,   p. 263
           */
          
      31  int clock_settime(  
           clockid_t clock_id,  
           const struct timespec *tp
           )
          {
           if (   !tp  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   clock_id == CLOCK_REALTIME  ) {
           if (   tp->tv_sec < TOD_SECONDS_1970_THROUGH_1988  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           _Thread_Disable_dispatch(   );
           _TOD_Set(   tp  );
           _Thread_Enable_dispatch(   );
           }
          #ifdef _POSIX_CPUTIME
           else if (   clock_id == CLOCK_PROCESS_CPUTIME  )
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          #endif
          #ifdef _POSIX_THREAD_CPUTIME
           else if (   clock_id == CLOCK_THREAD_CPUTIME  )
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          #endif
           else
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           return 0;
          }

posix/src/cond.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cond.c,  v 1.33 2009/02/03 10:10:42 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * _POSIX_Condition_variables_Manager_initialization
           *
           * This routine initializes all condition variable manager related data
           * structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      41  void _POSIX_Condition_variables_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_POSIX_Condition_variables_Information,   /* object information table */
           OBJECTS_POSIX_API,   /* object API */
           OBJECTS_POSIX_CONDITION_VARIABLES,   /* object class */
           Configuration_POSIX_API.maximum_condition_variables,  
           /* maximum objects of this class */
           sizeof(   POSIX_Condition_variables_Control  ),  
           /* size of this object's control block */
           true,   /* true if names for this object are strings */
           _POSIX_PATH_MAX /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

posix/src/condattrdestroy.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condattrdestroy.c,  v 1.5 2009/02/03 10:10:42 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * 11.4.1 Condition Variable Initialization Attributes,  
           * P1003.1c/Draft 10,   p. 96
           */
          
      33  int pthread_condattr_destroy(  
           pthread_condattr_t *attr
           )
          {
           if (   !attr || attr->is_initialized == false  )
           return EINVAL;
          
           attr->is_initialized = false;
           return 0;
          }

posix/src/condattrgetpshared.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condattrgetpshared.c,  v 1.4 2007/12/17 16:19:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * 11.4.1 Condition Variable Initialization Attributes,  
           * P1003.1c/Draft 10,   p. 96
           */
          
      33  int pthread_condattr_getpshared(  
           const pthread_condattr_t *attr,  
           int *pshared
           )
          {
           if (   !attr  )
           return EINVAL;
          
           *pshared = attr->process_shared;
           return 0;
          }

posix/src/condattrinit.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condattrinit.c,  v 1.4 2007/12/17 16:19:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * 11.4.1 Condition Variable Initialization Attributes,  
           * P1003.1c/Draft 10,   p. 96
           */
          
      33  int pthread_condattr_init(  
           pthread_condattr_t *attr
           )
          {
           if (   !attr  )
           return EINVAL;
          
           *attr = _POSIX_Condition_variables_Default_attributes;
           return 0;
          }

posix/src/condattrsetpshared.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condattrsetpshared.c,  v 1.4 2007/12/17 16:19:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * 11.4.1 Condition Variable Initialization Attributes,  
           * P1003.1c/Draft 10,   p. 96
           */
          
      33  int pthread_condattr_setpshared(  
           pthread_condattr_t *attr,  
           int pshared
           )
          {
           if (   !attr  )
           return EINVAL;
          
           switch (   pshared  ) {
           case PTHREAD_PROCESS_SHARED:
           case PTHREAD_PROCESS_PRIVATE:
           attr->process_shared = pshared;
           return 0;
          
           default:
           return EINVAL;
           }
          }

posix/src/condbroadcast.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condbroadcast.c,  v 1.5 2009/02/03 10:10:43 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * 11.4.3 Broadcasting and Signaling a Condition,   P1003.1c/Draft 10,   p. 101
           */
          
      32  int pthread_cond_broadcast(  
           pthread_cond_t *cond
           )
          {
           return _POSIX_Condition_variables_Signal_support(   cond,   true  );
          }

posix/src/conddefaultattributes.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: conddefaultattributes.c,  v 1.5 2009/02/03 10:10:43 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * The default condition variable attributes structure.
           */
          
          const pthread_condattr_t _POSIX_Condition_variables_Default_attributes = {
           true,   /* is_initialized */
           PTHREAD_PROCESS_PRIVATE /* process_shared */
          };

posix/src/conddestroy.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: conddestroy.c,  v 1.9 2007/12/17 16:19:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * 11.4.2 Initializing and Destroying a Condition Variable,  
           * P1003.1c/Draft 10,   p. 87
           */
          
      33  int pthread_cond_destroy(  
           pthread_cond_t *cond
           )
          {
           POSIX_Condition_variables_Control *the_cond;
           Objects_Locations location;
          
           the_cond = _POSIX_Condition_variables_Get(   cond,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           if (   _Thread_queue_First(   &the_cond->Wait_queue  )  ) {
           _Thread_Enable_dispatch(   );
           return EBUSY;
           }
          
           _Objects_Close(  
           &_POSIX_Condition_variables_Information,  
           &the_cond->Object
            );
          
           _POSIX_Condition_variables_Free(   the_cond  );
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/condget.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condget.c,  v 1.3 2009/11/30 15:44:20 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
      27  POSIX_Condition_variables_Control *_POSIX_Condition_variables_Get (  
           pthread_cond_t *cond,  
           Objects_Locations *location
           )
          {
           int status;
          
           if (   !cond  ) {
           *location = OBJECTS_ERROR;
           return (  POSIX_Condition_variables_Control * ) 0;
           }
          
           if (   *cond == PTHREAD_COND_INITIALIZER  ) {
           /*
           * Do an "auto-create" here.
           */
          
           status = pthread_cond_init(   cond,   0  );
           if (   status  ) {
           *location = OBJECTS_ERROR;
           return (  POSIX_Condition_variables_Control * ) 0;
           }
           }
          
           /*
           * Now call Objects_Get(   )
           */
           return (  POSIX_Condition_variables_Control * )_Objects_Get(  
           &_POSIX_Condition_variables_Information,  
           (  Objects_Id ) *cond,  
           location
            );
          }
          

posix/src/condinit.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condinit.c,  v 1.9 2010/07/28 20:39:40 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * 11.4.2 Initializing and Destroying a Condition Variable,  
           * P1003.1c/Draft 10,   p. 87
           */
          
      33  int pthread_cond_init(  
           pthread_cond_t *cond,  
           const pthread_condattr_t *attr
           )
          {
           POSIX_Condition_variables_Control *the_cond;
           const pthread_condattr_t *the_attr;
          
           if (   attr  ) the_attr = attr;
           else the_attr = &_POSIX_Condition_variables_Default_attributes;
          
           /*
           * Be careful about attributes when global!!!
           */
           if (   the_attr->process_shared == PTHREAD_PROCESS_SHARED  )
           return EINVAL;
          
           if (   !the_attr->is_initialized  )
           return EINVAL;
          
           _Thread_Disable_dispatch(   );
          
           the_cond = _POSIX_Condition_variables_Allocate(   );
          
           if (   !the_cond  ) {
           _Thread_Enable_dispatch(   );
           return ENOMEM;
           }
          
           the_cond->process_shared = the_attr->process_shared;
          
           the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX;
          
           _Thread_queue_Initialize(  
           &the_cond->Wait_queue,  
           THREAD_QUEUE_DISCIPLINE_FIFO,  
           STATES_WAITING_FOR_CONDITION_VARIABLE | STATES_INTERRUPTIBLE_BY_SIGNAL,  
           ETIMEDOUT
            );
          
           _Objects_Open_u32(  
           &_POSIX_Condition_variables_Information,  
           &the_cond->Object,  
           0
            );
          
           *cond = the_cond->Object.id;
          
           _Thread_Enable_dispatch(   );
          
           return 0;
          }

posix/src/condsignal.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condsignal.c,  v 1.5 2009/02/03 10:10:44 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * 11.4.3 Broadcasting and Signaling a Condition,   P1003.1c/Draft 10,   p. 101
           */
          
      32  int pthread_cond_signal(  
           pthread_cond_t *cond
           )
          {
           return _POSIX_Condition_variables_Signal_support(   cond,   false  );
          }

posix/src/condsignalsupp.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condsignalsupp.c,  v 1.8 2008/09/04 15:23:11 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * _POSIX_Condition_variables_Signal_support
           *
           * A support routine which implements guts of the broadcast and single task
           * wake up version of the "signal" operation.
           */
          
      35  int _POSIX_Condition_variables_Signal_support(  
           pthread_cond_t *cond,  
           bool is_broadcast
           )
          {
           register POSIX_Condition_variables_Control *the_cond;
           Objects_Locations location;
           Thread_Control *the_thread;
          
           the_cond = _POSIX_Condition_variables_Get(   cond,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           do {
           the_thread = _Thread_queue_Dequeue(   &the_cond->Wait_queue  );
           if (   !the_thread  )
           the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX;
           } while (   is_broadcast && the_thread  );
          
           _Thread_Enable_dispatch(   );
          
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/condtimedwait.c

       1  /*
           * $Id: condtimedwait.c,  v 1.9 2010/08/23 21:31:27 joel Exp $
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condtimedwait.c,  v 1.9 2010/08/23 21:31:27 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * 11.4.4 Waiting on a Condition,   P1003.1c/Draft 10,   p. 105
           */
          
      36  int pthread_cond_timedwait(  
           pthread_cond_t *cond,  
           pthread_mutex_t *mutex,  
           const struct timespec *abstime
           )
          {
           Watchdog_Interval ticks;
           bool already_timedout;
           POSIX_Absolute_timeout_conversion_results_t status;
          
           /*
           * POSIX requires that blocking calls with timeouts that take
           * an absolute timeout must ignore issues with the absolute
           * time provided if the operation would otherwise succeed.
           * So we check the abstime provided,   and hold on to whether it
           * is valid or not. If it isn't correct and in the future,  
           * then we do a polling operation and convert the UNSATISFIED
           * status into the appropriate error.
           */
           already_timedout = false;
           status = _POSIX_Absolute_timeout_to_ticks(  abstime,   &ticks );
           if (   status == POSIX_ABSOLUTE_TIMEOUT_INVALID  )
           return EINVAL;
          
           if (   status == POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
           status == POSIX_ABSOLUTE_TIMEOUT_IS_NOW  )
           already_timedout = true;
          
           return _POSIX_Condition_variables_Wait_support(  
           cond,  
           mutex,  
           ticks,  
           already_timedout
            );
          }

posix/src/condwait.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condwait.c,  v 1.5 2009/02/03 10:10:46 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * 11.4.4 Waiting on a Condition,   P1003.1c/Draft 10,   p. 105
           */
          
      32  int pthread_cond_wait(  
           pthread_cond_t *cond,  
           pthread_mutex_t *mutex
           )
          {
           return _POSIX_Condition_variables_Wait_support(  
           cond,  
           mutex,  
           THREAD_QUEUE_WAIT_FOREVER,  
           false
            );
          }

posix/src/condwaitsupp.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: condwaitsupp.c,  v 1.9 2010/07/28 20:39:44 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * _POSIX_Condition_variables_Wait_support
           *
           * A support routine which implements guts of the blocking,   non-blocking,   and
           * timed wait version of condition variable wait routines.
           */
          
      35  int _POSIX_Condition_variables_Wait_support(  
           pthread_cond_t *cond,  
           pthread_mutex_t *mutex,  
           Watchdog_Interval timeout,  
           bool already_timedout
           )
          {
           register POSIX_Condition_variables_Control *the_cond;
           Objects_Locations location;
           int status;
           int mutex_status;
          
           if (   !_POSIX_Mutex_Get(   mutex,   &location  )  ) {
           return EINVAL;
           }
          
           _Thread_Unnest_dispatch(   );
          
           the_cond = _POSIX_Condition_variables_Get(   cond,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           if (   the_cond->Mutex && (   the_cond->Mutex != *mutex  )  ) {
           _Thread_Enable_dispatch(   );
           return EINVAL;
           }
          
           (  void ) pthread_mutex_unlock(   mutex  );
          /* XXX ignore this for now since behavior is undefined
           if (   mutex_status  ) {
           _Thread_Enable_dispatch(   );
           return EINVAL;
           }
          */
          
           if (   !already_timedout  ) {
           the_cond->Mutex = *mutex;
          
           _Thread_queue_Enter_critical_section(   &the_cond->Wait_queue  );
           _Thread_Executing->Wait.return_code = 0;
           _Thread_Executing->Wait.queue = &the_cond->Wait_queue;
           _Thread_Executing->Wait.id = *cond;
          
           _Thread_queue_Enqueue(   &the_cond->Wait_queue,   timeout  );
          
           _Thread_Enable_dispatch(   );
          
           /*
           * Switch ourself out because we blocked as a result of the
           * _Thread_queue_Enqueue.
           */
          
           /*
           * If the thread is interrupted,   while in the thread queue,   by
           * a POSIX signal,   then pthread_cond_wait returns spuriously,  
           * according to the POSIX standard. It means that pthread_cond_wait
           * returns a success status,   except for the fact that it was not
           * woken up a pthread_cond_signal or a pthread_cond_broadcast.
           */
           status = _Thread_Executing->Wait.return_code;
           if (   status == EINTR  )
           status = 0;
          
           } else {
           _Thread_Enable_dispatch(   );
           status = ETIMEDOUT;
           }
          
           /*
           * When we get here the dispatch disable level is 0.
           */
          
           mutex_status = pthread_mutex_lock(   mutex  );
           if (   mutex_status  )
           return EINVAL;
          
           return status;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/execl.c

       1  /*
           * execl(   ) - POSIX 1003.1b 3.1.2
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: execl.c,  v 1.5 2008/12/05 06:44:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_EXECL
          
          #include <errno.h>
          #include <rtems/seterr.h>
          
      23  int execl(  
           const char *path,  
           const char *arg,  
           ...
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }
          
          #endif

posix/src/execle.c

       1  /*
           * execle(   ) - POSIX 1003.1b 3.1.2
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: execle.c,  v 1.5 2008/12/05 06:44:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_EXECLE
          
          #include <errno.h>
          #include <rtems/seterr.h>
          
      23  int execle(  
           const char *path,  
           char const *arg,  
           ...
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }
          
          #endif

posix/src/execlp.c

       1  /*
           * execlp(   ) - POSIX 1003.1b 3.1.2
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: execlp.c,  v 1.6 2008/12/05 06:44:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_EXECLP
          
          #include <errno.h>
          #include <rtems/seterr.h>
          
      23  int execlp(  
           const char *file,  
           const char *arg,  
           ...
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }
          
          #endif

posix/src/execv.c

       1  /*
           * execv(   ) - POSIX 1003.1b 3.1.2
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: execv.c,  v 1.7 2008/12/05 06:44:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_EXECV
          
          #include <errno.h>
          #include <rtems/seterr.h>
          
      23  int execv(  
           const char *file,  
           char *const argv[]
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }
          
          #endif

posix/src/execve.c

       1  /*
           * execve(   ) - POSIX 1003.1b 3.1.2
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: execve.c,  v 1.6 2008/12/05 06:44:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_EXECVE
          
          #include <errno.h>
          #include <rtems/seterr.h>
          
      23  int execve(  
           const char *path,  
           char *const argv[],  
           char *const envp[]
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }
          
          #endif

posix/src/execvp.c

       1  /*
           * execvp(   ) - POSIX 1003.1b 3.1.2
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: execvp.c,  v 1.6 2008/12/05 06:44:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_EXECVP
          
          #include <errno.h>
          #include <rtems/seterr.h>
          
      23  int execvp(  
           const char *path,  
           char *const argv[]
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }
          
          #endif

posix/src/fork.c

       1  /*
           * fork(   ) - POSIX 1003.1b 3.1.1
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: fork.c,  v 1.4 2007/12/13 16:52:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <errno.h>
          #include <rtems/seterr.h>
          
      22  int fork(   void  )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/getitimer.c

       1  /*
           * COPYRIGHT (  c ) 1989-20089
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: getitimer.c,  v 1.2 2009/05/15 17:43:02 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <sys/time.h>
          #include <errno.h>
          #include <rtems/seterr.h>
          
      21  int getitimer(  
           int which,  
           struct itimerval *value
           )
          {
           if (   !value  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           switch (   which  ) {
           case ITIMER_REAL:
           case ITIMER_VIRTUAL:
           case ITIMER_PROF:
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
           default:
           break;
           }
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }
          

posix/src/key.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: key.c,  v 1.18 2009/02/03 10:10:46 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <limits.h>
          #include <pthread.h>
          #include <string.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/key.h>
          
          /*
           * _POSIX_Key_Manager_initialization
           *
           * DESCRIPTION:
           *
           * This routine performs the initialization necessary for this manager.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      40  void _POSIX_Key_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_POSIX_Keys_Information,   /* object information table */
           OBJECTS_POSIX_API,   /* object API */
           OBJECTS_POSIX_KEYS,   /* object class */
           Configuration_POSIX_API.maximum_keys,  
           /* maximum objects of this class */
           sizeof(   POSIX_Keys_Control  ),  
           /* size of this object's control block */
           true,   /* true if names for this object are strings */
           _POSIX_PATH_MAX /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

posix/src/keycreate.c

       1  /*
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: keycreate.c,  v 1.17 2010/07/27 21:22:52 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <limits.h>
          #include <pthread.h>
          #include <string.h>
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/key.h>
          
          /*
           * 17.1.1 Thread-Specific Data Key Create,   P1003.1c/Draft 10,   p. 163
           */
          
      30  int pthread_key_create(  
           pthread_key_t *key,  
           void (  *destructor )(   void *  )
           )
          {
           POSIX_Keys_Control *the_key;
           void *table;
           uint32_t the_api;
           uint32_t bytes_to_allocate;
          
          
           _Thread_Disable_dispatch(   );
          
           the_key = _POSIX_Keys_Allocate(   );
          
           if (   !the_key  ) {
           _Thread_Enable_dispatch(   );
           return EAGAIN;
           }
          
           the_key->destructor = destructor;
          
           /*
           * This is a bit more complex than one might initially expect because
           * APIs are optional.
           *
           * NOTE: Currently RTEMS Classic API tasks are always enabled.
           */
           for (   the_api = 1; the_api <= OBJECTS_APIS_LAST; the_api++  ) {
           the_key->Values[ the_api ] = NULL;
          
           #if defined(  RTEMS_DEBUG )
           /*
           * Since the removal of ITRON,   this cannot occur.
           */
           if (   !_Objects_Information_table[ the_api ]  )
           continue;
          
           /*
           * Currently all managers are installed if the API is installed.
           * This would be a horrible implementation error.
           */
           if (  _Objects_Information_table[ the_api ][ 1 ] == NULL  )
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY
            );
           #endif
          
           bytes_to_allocate = sizeof(   void *  ) *
           (  _Objects_Information_table[ the_api ][ 1 ]->maximum + 1 );
           table = _Workspace_Allocate(   bytes_to_allocate  );
           if (   !table  ) {
           _POSIX_Keys_Free_memory(   the_key  );
          
           _POSIX_Keys_Free(   the_key  );
           _Thread_Enable_dispatch(   );
           return ENOMEM;
           }
          
           the_key->Values[ the_api ] = table;
           memset(   table,   '\0',   bytes_to_allocate  );
           }
          
           _Objects_Open_u32(   &_POSIX_Keys_Information,   &the_key->Object,   0  );
           *key = the_key->Object.id;
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/keydelete.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: keydelete.c,  v 1.12 2010/07/26 22:03:17 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <limits.h>
          #include <pthread.h>
          #include <string.h>
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/key.h>
          
          /*
           * 17.1.3 Thread-Specific Data Key Deletion,   P1003.1c/Draft 10,   p. 167
           */
      29  int pthread_key_delete(  
           pthread_key_t key
           )
          {
           POSIX_Keys_Control *the_key;
           Objects_Locations location;
          
           the_key = _POSIX_Keys_Get(   key,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _Objects_Close(   &_POSIX_Keys_Information,   &the_key->Object  );
          
           _POSIX_Keys_Free_memory(   the_key  );
          
           /*
           * NOTE: The destructor is not called and it is the responsibility
           * of the application to free the memory.
           */
           _POSIX_Keys_Free(   the_key  );
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never happen */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/keyfreememory.c

       1  /*
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: keyfreememory.c,  v 1.1 2010/07/26 22:03:18 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/key.h>
          
      21  void _POSIX_Keys_Free_memory(  
           POSIX_Keys_Control *the_key
           )
          {
           uint32_t the_api;
          
           for (   the_api = 1; the_api <= OBJECTS_APIS_LAST; the_api++  )
           if (   the_key->Values[ the_api ]  )
           _Workspace_Free(   the_key->Values[ the_api ]  );
          }

posix/src/keygetspecific.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: keygetspecific.c,  v 1.9 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <limits.h>
          #include <pthread.h>
          #include <string.h>
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/key.h>
          
          /*PAGE
           *
           * 17.1.2 Thread-Specific Data Management,   P1003.1c/Draft 10,   p. 165
           */
          
      31  void *pthread_getspecific(  
           pthread_key_t key
           )
          {
           register POSIX_Keys_Control *the_key;
           uint32_t api;
           uint32_t index;
           Objects_Locations location;
           void *key_data;
          
           the_key = _POSIX_Keys_Get(   key,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           api = _Objects_Get_API(   _Thread_Executing->Object.id  );
           index = _Objects_Get_index(   _Thread_Executing->Object.id  );
           key_data = (  void * ) the_key->Values[ api ][ index ];
           _Thread_Enable_dispatch(   );
           return key_data;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never happen */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return NULL;
          }

posix/src/keyrundestructors.c

       1  /*
           * Copyright (  c ) 2010 embedded brains GmbH.
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: keyrundestructors.c,  v 1.10 2010/08/09 08:13:21 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/posix/key.h>
          
          /*PAGE
           *
           * _POSIX_Keys_Run_destructors
           *
           * 17.1.1 Thread-Specific Data Key Create,   P1003.1c/Draft 10,   p. 163
           *
           * NOTE: This is the routine executed when a thread exits to
           * run through all the keys and do the destructor action.
           */
          
      33  void _POSIX_Keys_Run_destructors(  
           Thread_Control *thread
           )
          {
           Objects_Maximum thread_index = _Objects_Get_index(   thread->Object.id  );
           Objects_APIs thread_api = _Objects_Get_API(   thread->Object.id  );
           bool done = false;
          
           /*
           * The standard allows one to avoid a potential infinite loop and limit the
           * number of iterations. An infinite loop may happen if destructors set
           * thread specific data. This can be considered dubious.
           *
           * Reference: 17.1.1.2 P1003.1c/Draft 10,   p. 163,   line 99.
           */
           while (   !done  ) {
           Objects_Maximum index = 0;
           Objects_Maximum max = _POSIX_Keys_Information.maximum;
          
           done = true;
          
           for (   index = 1 ; index <= max ; ++index  ) {
           POSIX_Keys_Control *key = (  POSIX_Keys_Control * )
           _POSIX_Keys_Information.local_table [ index ];
          
           if (   key != NULL && key->destructor != NULL  ) {
           void *value = key->Values [ thread_api ][ thread_index ];
          
           if (   value != NULL  ) {
           key->Values [ thread_api ][ thread_index ] = NULL;
           (  *key->destructor )(   value  );
           done = false;
           }
           }
           }
           }
          }

posix/src/keysetspecific.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: keysetspecific.c,  v 1.8 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <limits.h>
          #include <pthread.h>
          #include <string.h>
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/key.h>
          
          /*PAGE
           *
           * 17.1.2 Thread-Specific Data Management,   P1003.1c/Draft 10,   p. 165
           */
          
      31  int pthread_setspecific(  
           pthread_key_t key,  
           const void *value
           )
          {
           register POSIX_Keys_Control *the_key;
           uint32_t api;
           uint32_t index;
           Objects_Locations location;
          
           the_key = _POSIX_Keys_Get(   key,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           api = _Objects_Get_API(   _Thread_Executing->Object.id  );
           index = _Objects_Get_index(   _Thread_Executing->Object.id  );
           the_key->Values[ api ][ index ] = (  void * ) value;
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never happen */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/kill.c

       1  /*
           * 3.3.2 Send a Signal to a Process,   P1003.1b-1993,   p. 68
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: kill.c,  v 1.6 2007/12/20 19:32:03 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          
      25  int kill(  
           pid_t pid,  
           int sig
           )
          {
           return killinfo(   pid,   sig,   NULL  );
          }
          

posix/src/kill_r.c

       1  /*
           * 3.3.2 Send a Signal to a Process,   P1003.1b-1993,   p. 68
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: kill_r.c,  v 1.1 2007/12/20 19:32:03 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          
          #if defined(  RTEMS_NEWLIB )
          
          #include <reent.h>
          
      29  int _kill_r(  
           struct _reent *ptr,  
           pid_t pid,  
           int sig
           )
          {
           return killinfo(   pid,   sig,   NULL  );
          }
          #endif

posix/src/killinfo.c

       1  /*
           * kill(   ) support routine
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: killinfo.c,  v 1.26 2010/08/29 19:50:33 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <signal.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/seterr.h>
          #include <rtems/score/isr.h>
          
          /*
           * If you enable this,   then you get printk(   ) feedback on each path
           * and the input to the decision that lead to the decision. Hopefully
           * this will help in debugging the algorithm that distributes process
           * signals to individual threads.
           */
          
          /* #define DEBUG_SIGNAL_PROCESSING */
          #if defined(  DEBUG_SIGNAL_PROCESSING )
           #include <rtems/bspIo.h>
           #define DEBUG_STEP(  _x ) printk(  _x )
          #else
           #define DEBUG_STEP(  _x )
          #endif
          
          /*
           * 3.3.2 Send a Signal to a Process,   P1003.1b-1993,   p. 68
           *
           * NOTE: Behavior of kill(   ) depends on _POSIX_SAVED_IDS.
           */
          
          #define _POSIX_signals_Is_interested(   _api,   _mask  ) \
           (   ~(  _api )->signals_blocked & (  _mask )  )
      51  
          int killinfo(  
           pid_t pid,  
           int sig,  
           const union sigval *value
           )
          {
           sigset_t mask;
           POSIX_API_Control *api;
           uint32_t the_api;
           uint32_t index;
           uint32_t maximum;
           Objects_Information *the_info;
           Objects_Control **object_table;
           Thread_Control *the_thread;
           Thread_Control *interested;
           Priority_Control interested_priority;
           Chain_Control *the_chain;
           Chain_Node *the_node;
           siginfo_t siginfo_struct;
           siginfo_t *siginfo;
           POSIX_signals_Siginfo_node *psiginfo;
          
           /*
           * Only supported for the "calling process" (  i.e. this node ).
           */
           if (   pid != getpid(   )  )
           rtems_set_errno_and_return_minus_one(   ESRCH  );
          
           /*
           * Validate the signal passed.
           */
           if (   !sig  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   !is_valid_signo(  sig )  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /*
           * If the signal is being ignored,   then we are out of here.
           */
           if (   _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN  )
           return 0;
          
           /*
           * P1003.1c/Draft 10,   p. 33 says that certain signals should always
           * be directed to the executing thread such as those caused by hardware
           * faults.
           */
           if (   (  sig == SIGFPE ) || (  sig == SIGILL ) || (  sig == SIGSEGV  )  )
           return pthread_kill(   pthread_self(   ),   sig  );
          
           mask = signo_to_mask(   sig  );
          
           /*
           * Build up a siginfo structure
           */
           siginfo = &siginfo_struct;
           siginfo->si_signo = sig;
           siginfo->si_code = SI_USER;
           if (   !value  ) {
           siginfo->si_value.sival_int = 0;
           } else {
           siginfo->si_value = *value;
           }
          
           _Thread_Disable_dispatch(   );
          
           /*
           * Is the currently executing thread interested? If so then it will
           * get it an execute it as soon as the dispatcher executes.
           */
           the_thread = _Thread_Executing;
          
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
           if (   _POSIX_signals_Is_interested(   api,   mask  )  ) {
           goto process_it;
           }
          
           /*
           * Is an interested thread waiting for this signal (  sigwait(   ) )?
           *
           * There is no requirement on the order of threads pending on a sigwait(   ).
           */
          
           /* XXX violation of visibility -- need to define thread queue support */
          
           the_chain = &_POSIX_signals_Wait_queue.Queues.Fifo;
          
           for (   the_node = the_chain->first ;
           !_Chain_Is_tail(   the_chain,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_thread = (  Thread_Control * )the_node;
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           #if defined(  DEBUG_SIGNAL_PROCESSING )
           printk(   "Waiting Thread=%p option=0x%08x mask=0x%08x blocked=0x%08x\n",  
           the_thread,   the_thread->Wait.option,   mask,   api->signals_blocked );
           #endif
          
           /*
           * Is this thread is actually blocked waiting for the signal?
           */
           if (  the_thread->Wait.option & mask )
           goto process_it;
          
           /*
           * Is this thread is blocked waiting for another signal but has
           * not blocked this one?
           */
           if (  ~api->signals_blocked & mask )
           goto process_it;
           }
          
           /*
           * Is any other thread interested? The highest priority interested
           * thread is selected. In the event of a tie,   then the following
           * additional criteria is used:
           *
           * + ready thread over blocked
           * + blocked on call interruptible by signal (  can return EINTR )
           * + blocked on call not interruptible by signal
           *
           * This looks at every thread in the system regardless of the creating API.
           *
           * NOTES:
           *
           * + rtems internal threads do not receive signals.
           */
           interested = NULL;
           interested_priority = PRIORITY_MAXIMUM + 1;
          
           for (  the_api = OBJECTS_CLASSIC_API; the_api <= OBJECTS_APIS_LAST; the_api++ ) {
          
           /*
           * This can occur when no one is interested and an API is not configured.
           */
           if (   !_Objects_Information_table[ the_api ]  )
           continue;
          
           the_info = _Objects_Information_table[ the_api ][ 1 ];
          
           #if defined(  RTEMS_DEBUG )
           /*
           * This cannot happen in the current (  as of June 2009 ) implementation
           * of initialization but at some point,   the object information
           * structure for a particular manager may not be installed.
           */
           if (   !the_info  )
           continue;
           #endif
          
           maximum = the_info->maximum;
           object_table = the_info->local_table;
          
           for (   index = 1 ; index <= maximum ; index++  ) {
           the_thread = (  Thread_Control * ) object_table[ index ];
          
           if (   !the_thread  )
           continue;
          
           #if defined(  DEBUG_SIGNAL_PROCESSING )
           printk(  "\n 0x%08x/0x%08x %d/%d 0x%08x 1",  
           the_thread->Object.id,  
           (  (  interested ) ? interested->Object.id : 0 ),  
           the_thread->current_priority,   interested_priority,  
           the_thread->current_state
            );
           #endif
          
           /*
           * If this thread is of lower priority than the interested thread,  
           * go on to the next thread.
           */
           if (   the_thread->current_priority > interested_priority  )
           continue;
           DEBUG_STEP(  "2" );
          
           /*
           * If this thread is not interested,   then go on to the next thread.
           */
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           #if defined(  RTEMS_DEBUG )
           if (   !api  )
           continue;
           #endif
          
           if (   !_POSIX_signals_Is_interested(   api,   mask  )  )
           continue;
           DEBUG_STEP(  "3" );
          
           /*
           * Now we know the thread under consideration is interested.
           * If the thread under consideration is of higher priority,   then
           * it becomes the interested thread.
           *
           * NOTE: We initialized interested_priority to PRIORITY_MAXIMUM + 1
           * so we never have to worry about deferencing a NULL
           * interested thread.
           */
           if (   the_thread->current_priority < interested_priority  ) {
           interested = the_thread;
           interested_priority = the_thread->current_priority;
           continue;
           }
           DEBUG_STEP(  "4" );
          
           /*
           * Now the thread and the interested thread have the same priority.
           * We have to sort through the combinations of blocked/not blocked
           * and blocking interruptibutable by signal.
           *
           * If the interested thread is ready,   don't think about changing.
           */
          
           if (   interested && !_States_Is_ready(   interested->current_state  )  ) {
           /* preferred ready over blocked */
           DEBUG_STEP(  "5" );
           if (   _States_Is_ready(   the_thread->current_state  )  ) {
           interested = the_thread;
           interested_priority = the_thread->current_priority;
           continue;
           }
          
           DEBUG_STEP(  "6" );
           /* prefer blocked/interruptible over blocked/not interruptible */
           if (   !_States_Is_interruptible_by_signal(  interested->current_state )  ) {
           DEBUG_STEP(  "7" );
           if (   _States_Is_interruptible_by_signal(  the_thread->current_state )  ) {
           DEBUG_STEP(  "8" );
           interested = the_thread;
           interested_priority = the_thread->current_priority;
           continue;
           }
           }
           }
           }
           }
          
           if (   interested  ) {
           the_thread = interested;
           goto process_it;
           }
          
           /*
           * OK so no threads were interested right now. It will be left on the
           * global pending until a thread receives it. The global set of threads
           * can change interest in this signal in one of the following ways:
           *
           * + a thread is created with the signal unblocked,  
           * + pthread_sigmask(   ) unblocks the signal,  
           * + sigprocmask(   ) unblocks the signal,   OR
           * + sigaction(   ) which changes the handler to SIG_IGN.
           */
           the_thread = NULL;
           goto post_process_signal;
          
           /*
           * We found a thread which was interested,   so now we mark that this
           * thread needs to do the post context switch extension so it can
           * evaluate the signals pending.
           */
          process_it:
          
           /*
           * Returns true if the signal was synchronously given to a thread
           * blocked waiting for the signal.
           */
           if (   _POSIX_signals_Unblock_thread(   the_thread,   sig,   siginfo  )  ) {
           _Thread_Enable_dispatch(   );
           return 0;
           }
          
          post_process_signal:
          
           /*
           * We may have woken up a thread but we definitely need to post the
           * signal to the process wide information set.
           */
           _POSIX_signals_Set_process_signals(   mask  );
          
           if (   _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO  ) {
          
           psiginfo = (  POSIX_signals_Siginfo_node * )
           _Chain_Get(   &_POSIX_signals_Inactive_siginfo  );
           if (   !psiginfo  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   EAGAIN  );
           }
          
           psiginfo->Info = *siginfo;
          
           _Chain_Append(   &_POSIX_signals_Siginfo[ sig ],   &psiginfo->Node  );
           }
          
           DEBUG_STEP(  "\n" );
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/lio_listio.c

       1  /*
           * 6.7.4 List Directed I/O,   P1003.1b-1993,   p. 158
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: lio_listio.c,  v 1.2 2009/01/02 10:04:23 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <aio.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          
      24  int lio_listio(  
           int mode __attribute__(  (  unused ) ),  
           struct aiocb * const list[] __attribute__(  (  unused ) ),  
           int nent __attribute__(  (  unused ) ),  
           struct sigevent *sig __attribute__(  (  unused ) )
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/mprotect.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mprotect.c,  v 1.4 2009/11/30 15:44:20 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h>
          
          /*PAGE
           *
           * 12.2.3 Change Memory Protection,   P1003.1b-1996,   p. 277.
           *
           * This is not a functional version but the SPARC backend for at least
           * gcc 2.8.1 plus gnat 3.13p and gcc 3.0.1 require it to be there and
           * return 0.
           *
           * As of gcc 4.2.2,   the gcc SPARC backend doesn't appear to have a
           * way to call this for RTEMS anymore but it doesn't hurt to leave it.
           */
          
      30  int mprotect(  
           const void *addr __attribute__(  (  unused ) ),  
           size_t len __attribute__(  (  unused ) ),  
           int prot __attribute__(  (  unused ) )  )
          {
           return 0;
          }

posix/src/mqueue.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueue.c,  v 1.23 2009/08/05 15:29:19 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * _POSIX_Message_queue_Manager_initialization
           *
           * This routine initializes all message_queue manager related data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      54  void _POSIX_Message_queue_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_POSIX_Message_queue_Information,   /* object information table */
           OBJECTS_POSIX_API,   /* object API */
           OBJECTS_POSIX_MESSAGE_QUEUES,   /* object class */
           Configuration_POSIX_API.maximum_message_queues,  
           /* maximum objects of this class */
           sizeof(   POSIX_Message_queue_Control  ),  
           /* size of this object's control block */
           true,   /* true if names for this object are strings */
           _POSIX_PATH_MAX /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
           _Objects_Initialize_information(  
           &_POSIX_Message_queue_Information_fds,  
           OBJECTS_POSIX_API,  
           OBJECTS_POSIX_MESSAGE_QUEUE_FDS,  
           Configuration_POSIX_API.maximum_message_queue_descriptors,  
           sizeof(   POSIX_Message_queue_Control_fd  ),  
           /* size of this object's control block */
           true,   /* true if names for this object are strings */
           NAME_MAX /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

posix/src/mqueueclose.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueueclose.c,  v 1.12 2008/01/18 16:31:56 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*
           *
           * 15.2.2 Close a Message Queue,   P1003.1b-1993,   p. 275
           */
          
      47  int mq_close(  
           mqd_t mqdes
           )
          {
           POSIX_Message_queue_Control *the_mq;
           POSIX_Message_queue_Control_fd *the_mq_fd;
           Objects_Locations location;
          
           the_mq_fd = _POSIX_Message_queue_Get_fd(   mqdes,   &location  );
           if (   location == OBJECTS_LOCAL  ) {
           /* OBJECTS_LOCAL:
           *
           * First update the actual message queue to reflect this descriptor
           * being disassociated. This may result in the queue being really
           * deleted.
           */
          
           the_mq = the_mq_fd->Queue;
           the_mq->open_count -= 1;
           _POSIX_Message_queue_Delete(   the_mq  );
          
           /*
           * Now close this file descriptor.
           */
          
           _Objects_Close(  
           &_POSIX_Message_queue_Information_fds,   &the_mq_fd->Object  );
           _POSIX_Message_queue_Free_fd(   the_mq_fd  );
          
           _Thread_Enable_dispatch(   );
           return 0;
           }
          
           /*
           * OBJECTS_REMOTE:
           * OBJECTS_ERROR:
           */
           rtems_set_errno_and_return_minus_one(   EBADF  );
          }

posix/src/mqueuecreatesupp.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuecreatesupp.c,  v 1.22 2009/08/06 19:26:56 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          #include <stdarg.h>
          #include <stdlib.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /* pure ANSI mode does not have this prototype */
      46  size_t strnlen(  const char *,   size_t );
          
          /*PAGE
           *
           * _POSIX_Message_queue_Create_support
           *
           * This routine does the actual creation and initialization of
           * a poxix message queue.
           */
          
      56  int _POSIX_Message_queue_Create_support(  
           const char *name_arg,  
           int pshared,  
           struct mq_attr *attr_ptr,  
           POSIX_Message_queue_Control **message_queue
           )
          {
           POSIX_Message_queue_Control *the_mq;
           CORE_message_queue_Attributes *the_mq_attr;
           struct mq_attr attr;
           char *name;
           size_t n;
          
           n = strnlen(   name_arg,   NAME_MAX  );
           /* length of name has already been validated */
          
           _Thread_Disable_dispatch(   );
          
           /*
           * There is no real basis for the default values. They will work
           * but were not compared against any existing implementation for
           * compatibility. See README.mqueue for an example program we
           * think will print out the defaults. Report anything you find with it.
           */
           if (   attr_ptr == NULL  ) {
           attr.mq_maxmsg = 10;
           attr.mq_msgsize = 16;
           } else {
           if (   attr_ptr->mq_maxmsg <= 0  ){
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           if (   attr_ptr->mq_msgsize <= 0  ){
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           attr = *attr_ptr;
           }
          
           the_mq = _POSIX_Message_queue_Allocate(   );
           if (   !the_mq  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   ENFILE  );
           }
          
           the_mq->process_shared = pshared;
           the_mq->named = true;
           the_mq->open_count = 1;
           the_mq->linked = true;
          
           /*
           * Make a copy of the user's string for name just in case it was
           * dynamically constructed.
           */
           name = _Workspace_Allocate(  n+1 );
           if (  !name ) {
           _POSIX_Message_queue_Free(   the_mq  );
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   ENOMEM  );
           }
           strncpy(   name,   name_arg,   n+1  );
          
           /*
           * NOTE: That thread blocking discipline should be based on the
           * current scheduling policy.
           *
           * Joel: Cite POSIX or OpenGroup on above statement so we can determine
           * if it is a real requirement.
           */
           the_mq_attr = &the_mq->Message_queue.Attributes;
           the_mq_attr->discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
          
           if (   !_CORE_message_queue_Initialize(  
           &the_mq->Message_queue,  
           the_mq_attr,  
           attr.mq_maxmsg,  
           attr.mq_msgsize
            )  ) {
          
           _POSIX_Message_queue_Free(   the_mq  );
           _Workspace_Free(  name );
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   ENOSPC  );
           }
          
           _Objects_Open_string(  
           &_POSIX_Message_queue_Information,  
           &the_mq->Object,  
           name
            );
          
           *message_queue = the_mq;
          
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/mqueuedeletesupp.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuedeletesupp.c,  v 1.13 2009/07/29 20:26:42 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          #if defined(  RTEMS_DEBUG )
           #include <rtems/bspIo.h>
          #endif
          
          /*PAGE
           *
           * _POSIX_Message_queue_Delete
           */
          
      51  void _POSIX_Message_queue_Delete(  
           POSIX_Message_queue_Control *the_mq
           )
          {
           if (   !the_mq->linked && !the_mq->open_count  ) {
           Objects_Control *the_object = &the_mq->Object;
          
           #if defined(  RTEMS_DEBUG )
           /*
           * the name memory will have been freed by unlink.
           */
           if (   the_object->name.name_p  ) {
           printk(  
           "POSIX MQ name (  %p ) not freed by unlink\n",  
           (  void * )the_object->name.name_p
            );
           _Workspace_Free(   (  void * )the_object->name.name_p  );
           }
           #endif
          
           _Objects_Close(   &_POSIX_Message_queue_Information,   the_object  );
          
           _CORE_message_queue_Close(  
           &the_mq->Message_queue,  
           NULL,   /* no MP support */
           CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED
            );
          
           _POSIX_Message_queue_Free(   the_mq  );
          
           }
          }

posix/src/mqueuegetattr.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuegetattr.c,  v 1.12 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 15.2.8 Get Message Queue Attributes,   P1003.1b-1993,   p. 283
           */
          
      47  int mq_getattr(  
           mqd_t mqdes,  
           struct mq_attr *mqstat
           )
          {
           POSIX_Message_queue_Control *the_mq;
           POSIX_Message_queue_Control_fd *the_mq_fd;
           Objects_Locations location;
           CORE_message_queue_Attributes *the_mq_attr;
          
           if (   !mqstat  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           the_mq_fd = _POSIX_Message_queue_Get_fd(   mqdes,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           the_mq = the_mq_fd->Queue;
          
           /*
           * Return the old values.
           */
          
           the_mq_attr = &the_mq->Message_queue.Attributes;
          
           mqstat->mq_flags = the_mq_fd->oflag;
           mqstat->mq_msgsize = the_mq->Message_queue.maximum_message_size;
           mqstat->mq_maxmsg = the_mq->Message_queue.maximum_pending_messages;
           mqstat->mq_curmsgs = the_mq->Message_queue.number_of_pending_messages;
          
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EBADF  );
          }

posix/src/mqueuenametoid.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuenametoid.c,  v 1.13 2009/08/06 19:26:56 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /* pure ANSI mode does not have this prototype */
      31  size_t strnlen(  const char *,   size_t );
          
          /*
           * _POSIX_Message_queue_Name_to_id
           *
           * Look up the specified name and attempt to locate the id
           * for the associated message queue.
           */
      39  int _POSIX_Message_queue_Name_to_id(  
           const char *name,  
           Objects_Id *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
           Objects_Id the_id;
          
           if (   !name  )
           return EINVAL;
          
           if (   !name[0]  )
           return EINVAL;
          
           if (   strnlen(   name,   NAME_MAX  ) >= NAME_MAX  )
           return ENAMETOOLONG;
          
           status = _Objects_Name_to_id_string(  
           &_POSIX_Message_queue_Information,  
           name,  
           &the_id
            );
           *id = the_id;
          
           if (   status == OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL  )
           return 0;
          
           return ENOENT;
          }

posix/src/mqueuenotify.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuenotify.c,  v 1.13 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          #include <sys/types.h>
          #include <signal.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * _POSIX_Message_queue_Notify_handler
           *
           */
          
      50  void _POSIX_Message_queue_Notify_handler(  
           void *user_data
           )
          {
           POSIX_Message_queue_Control *the_mq;
          
           the_mq = user_data;
          
           kill(   getpid(   ),   the_mq->notification.sigev_signo  );
          
           _CORE_message_queue_Set_notify(   &the_mq->Message_queue,   NULL,   NULL  );
          }
          
          /*PAGE
           *
           * 15.2.6 Notify Process that a Message is Available on a Queue,  
           * P1003.1b-1993,   p. 280
           */
          
      69  int mq_notify(  
           mqd_t mqdes,  
           const struct sigevent *notification
           )
          {
           POSIX_Message_queue_Control *the_mq;
           POSIX_Message_queue_Control_fd *the_mq_fd;
           Objects_Locations location;
          
           the_mq_fd = _POSIX_Message_queue_Get_fd(   mqdes,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           the_mq = the_mq_fd->Queue;
          
           if (   notification  ) {
           if (   _CORE_message_queue_Is_notify_enabled(   &the_mq->Message_queue  )  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   EBUSY  );
           }
          
           _CORE_message_queue_Set_notify(   &the_mq->Message_queue,   NULL,   NULL  );
          
           the_mq->notification = *notification;
          
           _CORE_message_queue_Set_notify(  
           &the_mq->Message_queue,  
           _POSIX_Message_queue_Notify_handler,  
           the_mq
            );
           } else {
          
           _CORE_message_queue_Set_notify(   &the_mq->Message_queue,   NULL,   NULL  );
          
           }
          
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EBADF  );
          }

posix/src/mqueueopen.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueueopen.c,  v 1.16 2009/08/06 19:26:56 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*
           * 15.2.2 Open a Message Queue,   P1003.1b-1993,   p. 272
           */
      45  mqd_t mq_open(  
           const char *name,  
           int oflag,  
           ...
           /* mode_t mode,   */
           /* struct mq_attr attr */
           )
          {
           va_list arg;
           mode_t mode;
           struct mq_attr *attr = NULL;
           int status;
           Objects_Id the_mq_id;
           POSIX_Message_queue_Control *the_mq;
           POSIX_Message_queue_Control_fd *the_mq_fd;
           Objects_Locations location;
          
           _Thread_Disable_dispatch(   );
          
           if (   oflag & O_CREAT  ) {
           va_start(  arg,   oflag );
           mode = (  mode_t ) va_arg(   arg,   unsigned int  );
           attr = (  struct mq_attr * ) va_arg(   arg,   struct mq_attr *  );
           va_end(  arg );
           }
          
           the_mq_fd = _POSIX_Message_queue_Allocate_fd(   );
           if (   !the_mq_fd  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   ENFILE  );
           }
           the_mq_fd->oflag = oflag;
          
           status = _POSIX_Message_queue_Name_to_id(   name,   &the_mq_id  );
          
           /*
           * If the name to id translation worked,   then the message queue exists
           * and we can just return a pointer to the id. Otherwise we may
           * need to check to see if this is a "message queue does not exist"
           * or some other miscellaneous error on the name.
           */
           if (   status  ) {
           /*
           * Unless provided a valid name that did not already exist
           * and we are willing to create then it is an error.
           */
           if (   !(   status == ENOENT && (  oflag & O_CREAT )  )  ) {
           _POSIX_Message_queue_Free_fd(   the_mq_fd  );
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one_cast(   status,   mqd_t  );
           }
          
           } else { /* name -> ID translation succeeded */
           /*
           * Check for existence with creation.
           */
           if (   (  oflag & (  O_CREAT | O_EXCL ) ) == (  O_CREAT | O_EXCL )  ) {
           _POSIX_Message_queue_Free_fd(   the_mq_fd  );
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one_cast(   EEXIST,   mqd_t  );
           }
          
           /*
           * In this case we need to do an ID->pointer conversion to
           * check the mode.
           */
           the_mq = _POSIX_Message_queue_Get(   the_mq_id,   &location  );
           the_mq->open_count += 1;
           the_mq_fd->Queue = the_mq;
           _Objects_Open_string(  
           &_POSIX_Message_queue_Information_fds,  
           &the_mq_fd->Object,  
           NULL
            );
           _Thread_Enable_dispatch(   );
           _Thread_Enable_dispatch(   );
           return (  mqd_t )the_mq_fd->Object.id;
          
           }
          
           /*
           * At this point,   the message queue does not exist and everything has been
           * checked. We should go ahead and create a message queue.
           */
           status = _POSIX_Message_queue_Create_support(  
           name,  
           true,   /* shared across processes */
           attr,  
           &the_mq
            );
          
           /*
           * errno was set by Create_support,   so don't set it again.
           */
           if (   status == -1  ) {
           _POSIX_Message_queue_Free_fd(   the_mq_fd  );
           _Thread_Enable_dispatch(   );
           return (  mqd_t ) -1;
           }
          
           the_mq_fd->Queue = the_mq;
           _Objects_Open_string(  
           &_POSIX_Message_queue_Information_fds,  
           &the_mq_fd->Object,  
           NULL
            );
          
           _Thread_Enable_dispatch(   );
          
           return (  mqd_t ) the_mq_fd->Object.id;
          }

posix/src/mqueuereceive.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuereceive.c,  v 1.8 2009/02/03 10:10:47 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 15.2.5 Receive a Message From a Message Queue,   P1003.1b-1993,   p. 279
           *
           * NOTE: P1003.4b/D8,   p. 45 adds mq_timedreceive(   ).
           */
          
      49  ssize_t mq_receive(  
           mqd_t mqdes,  
           char *msg_ptr,  
           size_t msg_len,  
           unsigned int *msg_prio
           )
          {
           return _POSIX_Message_queue_Receive_support(  
           mqdes,  
           msg_ptr,  
           msg_len,  
           msg_prio,  
           true,  
           THREAD_QUEUE_WAIT_FOREVER
            );
          }

posix/src/mqueuerecvsupp.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuerecvsupp.c,  v 1.18 2009/02/03 10:10:48 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*
           * _POSIX_Message_queue_Receive_support
           *
           * NOTE: XXX Document how size,   priority,   length,   and the buffer go
           * through the layers.
           */
          
      49  ssize_t _POSIX_Message_queue_Receive_support(  
           mqd_t mqdes,  
           char *msg_ptr,  
           size_t msg_len,  
           unsigned int *msg_prio,  
           bool wait,  
           Watchdog_Interval timeout
           )
          {
           POSIX_Message_queue_Control *the_mq;
           POSIX_Message_queue_Control_fd *the_mq_fd;
           Objects_Locations location;
           size_t length_out;
           bool do_wait;
          
           the_mq_fd = _POSIX_Message_queue_Get_fd(   mqdes,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   (  the_mq_fd->oflag & O_ACCMODE ) == O_WRONLY  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   EBADF  );
           }
          
           the_mq = the_mq_fd->Queue;
          
           if (   msg_len < the_mq->Message_queue.maximum_message_size  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   EMSGSIZE  );
           }
          
           /*
           * Now if something goes wrong,   we return a "length" of -1
           * to indicate an error.
           */
          
           length_out = -1;
          
           /*
           * A timed receive with a bad time will do a poll regardless.
           */
           if (   wait  )
           do_wait = (  the_mq_fd->oflag & O_NONBLOCK ) ? false : true;
           else
           do_wait = wait;
          
           /*
           * Now perform the actual message receive
           */
           _CORE_message_queue_Seize(  
           &the_mq->Message_queue,  
           mqdes,  
           msg_ptr,  
           &length_out,  
           do_wait,  
           timeout
            );
          
           _Thread_Enable_dispatch(   );
           *msg_prio =
           _POSIX_Message_queue_Priority_from_core(  _Thread_Executing->Wait.count );
          
           if (   !_Thread_Executing->Wait.return_code  )
           return length_out;
          
           rtems_set_errno_and_return_minus_one(  
           _POSIX_Message_queue_Translate_core_message_queue_return_code(  
           _Thread_Executing->Wait.return_code
            )
            );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EBADF  );
          }

posix/src/mqueuesend.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuesend.c,  v 1.8 2009/02/03 10:10:48 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 15.2.4 Send a Message to a Message Queue,   P1003.1b-1993,   p. 277
           *
           * NOTE: P1003.4b/D8,   p. 45 adds mq_timedsend(   ).
           */
          
      49  int mq_send(  
           mqd_t mqdes,  
           const char *msg_ptr,  
           size_t msg_len,  
           unsigned int msg_prio
           )
          {
           return _POSIX_Message_queue_Send_support(  
           mqdes,  
           msg_ptr,  
           msg_len,  
           msg_prio,  
           true,  
           THREAD_QUEUE_WAIT_FOREVER
            );
          }

posix/src/mqueuesendsupp.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuesendsupp.c,  v 1.22 2009/02/03 10:10:48 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          
          /*PAGE
           *
           * _POSIX_Message_queue_Send_support
           */
          
      48  int _POSIX_Message_queue_Send_support(  
           mqd_t mqdes,  
           const char *msg_ptr,  
           size_t msg_len,  
           uint32_t msg_prio,  
           bool wait,  
           Watchdog_Interval timeout
           )
          {
           POSIX_Message_queue_Control *the_mq;
           POSIX_Message_queue_Control_fd *the_mq_fd;
           Objects_Locations location;
           CORE_message_queue_Status msg_status;
           bool do_wait;
          
           /*
           * Validate the priority.
           * XXX - Do not validate msg_prio is not less than 0.
           */
          
           if (   msg_prio > MQ_PRIO_MAX  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           the_mq_fd = _POSIX_Message_queue_Get_fd(   mqdes,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   (  the_mq_fd->oflag & O_ACCMODE ) == O_RDONLY  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   EBADF  );
           }
          
           the_mq = the_mq_fd->Queue;
          
           /*
           * A timed receive with a bad time will do a poll regardless.
           */
           if (   wait  )
           do_wait = (  the_mq_fd->oflag & O_NONBLOCK ) ? false : true;
           else
           do_wait = wait;
          
           /*
           * Now perform the actual message receive
           */
           msg_status = _CORE_message_queue_Submit(  
           &the_mq->Message_queue,  
           (  void * )msg_ptr,  
           msg_len,  
           mqdes,   /* mqd_t is an object id */
           NULL,  
           _POSIX_Message_queue_Priority_to_core(   msg_prio  ),  
           do_wait,  
           timeout /* no timeout */
            );
          
           _Thread_Enable_dispatch(   );
          
           /*
           * If we had to block,   then this is where the task returns
           * after it wakes up. The returned status is correct for
           * non-blocking operations but if we blocked,   then we need
           * to look at the status in our TCB.
           */
          
           if (   msg_status == CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT  )
           msg_status = _Thread_Executing->Wait.return_code;
          
           if (   !msg_status  )
           return msg_status;
          
           rtems_set_errno_and_return_minus_one(  
           _POSIX_Message_queue_Translate_core_message_queue_return_code(  
           msg_status
            )
            );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EBADF  );
          }

posix/src/mqueuesetattr.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuesetattr.c,  v 1.12 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 15.2.7 Set Message Queue Attributes,   P1003.1b-1993,   p. 281
           */
          
      47  int mq_setattr(  
           mqd_t mqdes,  
           const struct mq_attr *mqstat,  
           struct mq_attr *omqstat
           )
          {
           POSIX_Message_queue_Control_fd *the_mq_fd;
           CORE_message_queue_Control *the_core_mq;
           Objects_Locations location;
          
           if (   !mqstat  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           the_mq_fd = _POSIX_Message_queue_Get_fd(   mqdes,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           the_core_mq = &the_mq_fd->Queue->Message_queue;
          
           /*
           * Return the old values.
           */
          
           if (   omqstat  ) {
           omqstat->mq_flags = the_mq_fd->oflag;
           omqstat->mq_msgsize = the_core_mq->maximum_message_size;
           omqstat->mq_maxmsg = the_core_mq->maximum_pending_messages;
           omqstat->mq_curmsgs = the_core_mq->number_of_pending_messages;
           }
          
           the_mq_fd->oflag = mqstat->mq_flags;
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EBADF  );
          }

posix/src/mqueuetimedreceive.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuetimedreceive.c,  v 1.13 2009/11/30 15:44:20 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 15.2.5 Receive a Message From a Message Queue,   P1003.1b-1993,   p. 279
           *
           * NOTE: P1003.4b/D8,   p. 45 adds mq_timedreceive(   ).
           */
          
      51  ssize_t mq_timedreceive(  
           mqd_t mqdes,  
           char *msg_ptr,  
           size_t msg_len,  
           unsigned int *msg_prio,  
           const struct timespec *abstime
           )
          {
           Watchdog_Interval ticks;
           bool do_wait = true;
           POSIX_Absolute_timeout_conversion_results_t status;
          
           /*
           * POSIX requires that blocking calls with timeouts that take
           * an absolute timeout must ignore issues with the absolute
           * time provided if the operation would otherwise succeed.
           * So we check the abstime provided,   and hold on to whether it
           * is valid or not. If it isn't correct and in the future,  
           * then we do a polling operation and convert the UNSATISFIED
           * status into the appropriate error.
           *
           * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID,  
           * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST,   or POSIX_ABSOLUTE_TIMEOUT_IS_NOW,  
           * then we should not wait.
           */
           status = _POSIX_Absolute_timeout_to_ticks(   abstime,   &ticks  );
           if (   status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE  )
           do_wait = false;
          
           return _POSIX_Message_queue_Receive_support(  
           mqdes,  
           msg_ptr,  
           msg_len,  
           msg_prio,  
           do_wait,  
           ticks
            );
          }

posix/src/mqueuetimedsend.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuetimedsend.c,  v 1.12 2009/11/30 15:44:20 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 15.2.4 Send a Message to a Message Queue,   P1003.1b-1993,   p. 277
           *
           * NOTE: P1003.4b/D8,   p. 45 adds mq_timedsend(   ).
           */
          
      51  int mq_timedsend(  
           mqd_t mqdes,  
           const char *msg_ptr,  
           size_t msg_len,  
           unsigned int msg_prio,  
           const struct timespec *abstime
           )
          {
           Watchdog_Interval ticks;
           bool do_wait = true;
           POSIX_Absolute_timeout_conversion_results_t status;
          
           /*
           * POSIX requires that blocking calls with timeouts that take
           * an absolute timeout must ignore issues with the absolute
           * time provided if the operation would otherwise succeed.
           * So we check the abstime provided,   and hold on to whether it
           * is valid or not. If it isn't correct and in the future,  
           * then we do a polling operation and convert the UNSATISFIED
           * status into the appropriate error.
           *
           * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID,  
           * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST,   or POSIX_ABSOLUTE_TIMEOUT_IS_NOW,  
           * then we should not wait.
           */
           status = _POSIX_Absolute_timeout_to_ticks(   abstime,   &ticks  );
           if (   status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE  )
           do_wait = false;
          
           return _POSIX_Message_queue_Send_support(  
           mqdes,  
           msg_ptr,  
           msg_len,  
           msg_prio,  
           do_wait,  
           ticks
            );
          }

posix/src/mqueuetranslatereturncode.c

       1  /*
           * POSIX Message Queue Error Translation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueuetranslatereturncode.c,  v 1.9 2007/11/30 20:34:13 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremsg.h>
          
          
          /*PAGE
           *
           * _POSIX_Message_queue_Translate_core_message_queue_return_code
           *
           * Input parameters:
           * the_message_queue_status - message_queue status code to translate
           *
           * Output parameters:
           * status code - translated POSIX status code
           *
           */
          
          static
           int _POSIX_Message_queue_Return_codes[CORE_MESSAGE_QUEUE_STATUS_LAST + 1] = {
           0,   /* CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL */
           EMSGSIZE,   /* CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE */
           EAGAIN,   /* CORE_MESSAGE_QUEUE_STATUS_TOO_MANY */
           ENOMEM,   /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED */
           EAGAIN,   /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT */
           EBADF,   /* CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED */
           ETIMEDOUT,   /* CORE_MESSAGE_QUEUE_STATUS_TIMEOUT */
           ENOSYS /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT */
          };
          
          
      50  int _POSIX_Message_queue_Translate_core_message_queue_return_code(  
           uint32_t the_message_queue_status
           )
          {
           /*
           * Internal consistency check for bad status from SuperCore
           */
           #if defined(  RTEMS_DEBUG )
           if (   the_message_queue_status > CORE_MESSAGE_QUEUE_STATUS_LAST  )
           return EINVAL;
           #endif
           return _POSIX_Message_queue_Return_codes[the_message_queue_status];
          }

posix/src/mqueueunlink.c

       1  /*
           * NOTE: The structure of the routines is identical to that of POSIX
           * Message_queues to leave the option of having unnamed message
           * queues at a future date. They are currently not part of the
           * POSIX standard but unnamed message_queues are. This is also
           * the reason for the apparently unnecessary tracking of
           * the process_shared attribute. [In addition to the fact that
           * it would be trivial to add pshared to the mq_attr structure
           * and have process private message queues.]
           *
           * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
           * time.
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mqueueunlink.c,  v 1.17 2009/02/03 10:10:49 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <pthread.h>
          #include <limits.h>
          #include <errno.h>
          #include <fcntl.h>
          #include <mqueue.h>
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 15.2.2 Remove a Message Queue,   P1003.1b-1993,   p. 276
           */
          
      48  int mq_unlink(  
           const char *name
           )
          {
           int status;
           register POSIX_Message_queue_Control *the_mq;
           Objects_Id the_mq_id;
          
           _Thread_Disable_dispatch(   );
          
           status = _POSIX_Message_queue_Name_to_id(   name,   &the_mq_id  );
           if (   status != 0  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   status  );
           }
          
           the_mq = (  POSIX_Message_queue_Control * ) _Objects_Get_local_object(  
           &_POSIX_Message_queue_Information,  
           _Objects_Get_index(   the_mq_id  )
            );
          
           the_mq->linked = false;
           _POSIX_Message_queue_Namespace_remove(   the_mq  );
           _POSIX_Message_queue_Delete(   the_mq  );
          
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/mutex.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutex.c,  v 1.38 2009/07/06 14:46:36 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * _POSIX_Mutex_Manager_initialization
           *
           * This routine initializes all mutex manager related data structures.
           *
           * Input parameters:
           * maximum_mutexes - maximum configured mutexes
           *
           * Output parameters: NONE
           */
          
      43  void _POSIX_Mutex_Manager_initialization(  void )
          {
           pthread_mutexattr_t *default_attr = &_POSIX_Mutex_Default_attributes;
          
           /*
           * Since the maximum priority is run-time configured,   this
           * structure cannot be initialized statically.
           */
           default_attr->is_initialized = true;
           default_attr->process_shared = PTHREAD_PROCESS_PRIVATE;
           default_attr->prio_ceiling = POSIX_SCHEDULER_MAXIMUM_PRIORITY;
           default_attr->protocol = PTHREAD_PRIO_NONE;
           default_attr->recursive = false;
           #if defined(  _UNIX98_THREAD_MUTEX_ATTRIBUTES )
           default_attr->type = PTHREAD_MUTEX_DEFAULT;
           #endif
          
           /*
           * Initialize the POSIX mutex object class information structure.
           */
           _Objects_Initialize_information(  
           &_POSIX_Mutex_Information,   /* object information table */
           OBJECTS_POSIX_API,   /* object API */
           OBJECTS_POSIX_MUTEXES,   /* object class */
           Configuration_POSIX_API.maximum_mutexes,  
           /* maximum objects of this class */
           sizeof(   POSIX_Mutex_Control  ),  
           /* size of this object's control block */
           true,   /* true if names for this object are strings */
           _POSIX_PATH_MAX /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

posix/src/mutexattrdestroy.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexattrdestroy.c,  v 1.7 2009/02/03 10:10:50 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 11.3.1 Mutex Initialization Attributes,   P1003.1c/Draft 10,   p. 81
           */
          
      31  int pthread_mutexattr_destroy(  
           pthread_mutexattr_t *attr
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           attr->is_initialized = false;
           return 0;
          }

posix/src/mutexattrgetprioceiling.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexattrgetprioceiling.c,  v 1.6 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 13.6.1 Mutex Initialization Scheduling Attributes,   P1003.1c/Draft 10,   p. 128
           */
          
      31  int pthread_mutexattr_getprioceiling(  
           const pthread_mutexattr_t *attr,  
           int *prioceiling
           )
          {
           if (   !attr || !attr->is_initialized || !prioceiling  )
           return EINVAL;
          
           *prioceiling = attr->prio_ceiling;
           return 0;
          }

posix/src/mutexattrgetprotocol.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexattrgetprotocol.c,  v 1.7 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 13.6.1 Mutex Initialization Scheduling Attributes,   P1003.1c/Draft 10,   p. 128
           */
          
      31  int pthread_mutexattr_getprotocol(  
           const pthread_mutexattr_t *attr,  
           int *protocol
           )
          {
           if (   !attr || !attr->is_initialized || !protocol  )
           return EINVAL;
          
           *protocol = attr->protocol;
           return 0;
          }

posix/src/mutexattrgetpshared.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexattrgetpshared.c,  v 1.5 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 11.3.1 Mutex Initialization Attributes,   P1003.1c/Draft 10,   p. 81
           */
          
      31  int pthread_mutexattr_getpshared(  
           const pthread_mutexattr_t *attr,  
           int *pshared
           )
          {
           if (   !attr || !attr->is_initialized || !pshared  )
           return EINVAL;
          
           *pshared = attr->process_shared;
           return 0;
          }

posix/src/mutexattrgettype.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexattrgettype.c,  v 1.2 2009/07/17 16:17:59 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          #if defined(  _UNIX98_THREAD_MUTEX_ATTRIBUTES )
      27  int pthread_mutexattr_gettype(  
           const pthread_mutexattr_t *attr,  
           int *type
           )
          {
           if (   !attr  )
           return EINVAL;
          
           if (   !attr->is_initialized  )
           return EINVAL;
          
           if (   !type  )
           return EINVAL;
          
           *type = attr->type;
           return 0;
          }
          #endif
          

posix/src/mutexattrinit.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexattrinit.c,  v 1.5 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 11.3.1 Mutex Initialization Attributes,   P1003.1c/Draft 10,   p. 81
           */
          
      31  int pthread_mutexattr_init(  
           pthread_mutexattr_t *attr
           )
          {
           if (   !attr  )
           return EINVAL;
          
           *attr = _POSIX_Mutex_Default_attributes;
           return 0;
          }

posix/src/mutexattrsetprioceiling.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexattrsetprioceiling.c,  v 1.6 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 13.6.1 Mutex Initialization Scheduling Attributes,   P1003.1c/Draft 10,   p. 128
           */
          
      31  int pthread_mutexattr_setprioceiling(  
           pthread_mutexattr_t *attr,  
           int prioceiling
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           if (   !_POSIX_Priority_Is_valid(   prioceiling  )  )
           return EINVAL;
          
           attr->prio_ceiling = prioceiling;
           return 0;
          }

posix/src/mutexattrsetprotocol.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexattrsetprotocol.c,  v 1.6 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 13.6.1 Mutex Initialization Scheduling Attributes,   P1003.1c/Draft 10,   p. 128
           */
          
      31  int pthread_mutexattr_setprotocol(  
           pthread_mutexattr_t *attr,  
           int protocol
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           switch (   protocol  ) {
           case PTHREAD_PRIO_NONE:
           case PTHREAD_PRIO_INHERIT:
           case PTHREAD_PRIO_PROTECT:
           attr->protocol = protocol;
           return 0;
          
           default:
           return EINVAL;
           }
          }

posix/src/mutexattrsetpshared.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexattrsetpshared.c,  v 1.6 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 11.3.1 Mutex Initialization Attributes,   P1003.1c/Draft 10,   p. 81
           */
          
      31  int pthread_mutexattr_setpshared(  
           pthread_mutexattr_t *attr,  
           int pshared
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           switch (   pshared  ) {
           case PTHREAD_PROCESS_SHARED:
           case PTHREAD_PROCESS_PRIVATE:
           attr->process_shared = pshared;
           return 0;
          
           default:
           return EINVAL;
           }
          }

posix/src/mutexattrsettype.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexattrsettype.c,  v 1.1 2009/07/06 14:46:36 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          #if defined(  _UNIX98_THREAD_MUTEX_ATTRIBUTES )
      27  int pthread_mutexattr_settype(  
           pthread_mutexattr_t *attr,  
           int type
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           switch (   type  ) {
           case PTHREAD_MUTEX_NORMAL:
           case PTHREAD_MUTEX_RECURSIVE:
           case PTHREAD_MUTEX_ERRORCHECK:
           case PTHREAD_MUTEX_DEFAULT:
           attr->type = type;
           return 0;
          
           default:
           return EINVAL;
           }
          }
          #endif

posix/src/mutexdestroy.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexdestroy.c,  v 1.9 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 11.3.2 Initializing and Destroying a Mutex,   P1003.1c/Draft 10,   p. 87
           */
          
      31  int pthread_mutex_destroy(  
           pthread_mutex_t *mutex
           )
          {
           register POSIX_Mutex_Control *the_mutex;
           Objects_Locations location;
          
           the_mutex = _POSIX_Mutex_Get(   mutex,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           /*
           * XXX: There is an error for the mutex being locked
           * or being in use by a condition variable.
           */
          
           if (   _CORE_mutex_Is_locked(   &the_mutex->Mutex  )  ) {
           _Thread_Enable_dispatch(   );
           return EBUSY;
           }
          
           _Objects_Close(   &_POSIX_Mutex_Information,   &the_mutex->Object  );
          
           _CORE_mutex_Flush(   &the_mutex->Mutex,   NULL,   EINVAL  );
          
           _POSIX_Mutex_Free(   the_mutex  );
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/mutexget.c

          /*
           * Convert POSIX Mutex ID to local object pointer
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexget.c,  v 1.4 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/posix/mutex.h>
          
          
          /*
           * _POSIX_Mutex_Get_support
           *
           * NOTE: The support macro makes it possible for both to use exactly
           * the same code to check for NULL id pointer and
           * PTHREAD_MUTEX_INITIALIZER without adding overhead.
           */
          
          #define ___POSIX_Mutex_Get_support_error_check(   _id,   _location  ) \
           do { \
           if (   !_id  ) { \
           *_location = OBJECTS_ERROR; \
           return (  POSIX_Mutex_Control * ) 0; \
           } \
      43   } while (  0 )
          
          #define ___POSIX_Mutex_Get_support_auto_initialization(   _id,   _location  ) \
           do { \
           int _status; \
           \
           if (   *_id == PTHREAD_MUTEX_INITIALIZER  ) { \
           /* \
           * Do an "auto-create" here. \
           */ \
           \
           _status = pthread_mutex_init(   (  pthread_mutex_t * )_id,   0  ); \
           if (   _status  ) { \
           *_location = OBJECTS_ERROR; \
           return (  POSIX_Mutex_Control * ) 0; \
           } \
           } \
           } while (  0 )
          
          POSIX_Mutex_Control *_POSIX_Mutex_Get (  
           pthread_mutex_t *mutex,  
           Objects_Locations *location
           )
          {
           ___POSIX_Mutex_Get_support_error_check(   mutex,   location  );
          
           ___POSIX_Mutex_Get_support_auto_initialization(   mutex,   location  );
          
           return (  POSIX_Mutex_Control * )
           _Objects_Get(   &_POSIX_Mutex_Information,   (  Objects_Id ) *mutex,   location  );
          }
          
          POSIX_Mutex_Control *_POSIX_Mutex_Get_interrupt_disable (  
           pthread_mutex_t *mutex,  
           Objects_Locations *location,  
           ISR_Level *level
           )
          {
           ___POSIX_Mutex_Get_support_error_check(   mutex,   location  );
          
           ___POSIX_Mutex_Get_support_auto_initialization(   mutex,   location  );
          
           return (  POSIX_Mutex_Control * ) _Objects_Get_isr_disable(  
           &_POSIX_Mutex_Information,  
           (  Objects_Id ) *mutex,  
           location,  
           level
            );
          }

posix/src/mutexgetprioceiling.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexgetprioceiling.c,  v 1.8 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 13.6.2 Change the Priority Ceiling of a Mutex,   P1003.1c/Draft 10,   p. 131
           */
          
      34  int pthread_mutex_getprioceiling(  
           pthread_mutex_t *mutex,  
           int *prioceiling
           )
          {
           register POSIX_Mutex_Control *the_mutex;
           Objects_Locations location;
          
           if (   !prioceiling  )
           return EINVAL;
          
           the_mutex = _POSIX_Mutex_Get(   mutex,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           *prioceiling = _POSIX_Priority_From_core(  
           the_mutex->Mutex.Attributes.priority_ceiling
            );
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/mutexinit.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexinit.c,  v 1.15 2009/07/06 14:47:09 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 11.3.2 Initializing and Destroying a Mutex,   P1003.1c/Draft 10,   p. 87
           *
           * NOTE: XXX Could be optimized so all the attribute error checking
           * is not performed when attr is NULL.
           */
          
      34  int pthread_mutex_init(  
           pthread_mutex_t *mutex,  
           const pthread_mutexattr_t *attr
           )
          {
           POSIX_Mutex_Control *the_mutex;
           CORE_mutex_Attributes *the_mutex_attr;
           const pthread_mutexattr_t *the_attr;
           CORE_mutex_Disciplines the_discipline;
          
           if (   attr  ) the_attr = attr;
           else the_attr = &_POSIX_Mutex_Default_attributes;
          
           /* Check for NULL mutex */
           if (   !mutex  )
           return EINVAL;
          
           /*
           * This code should eventually be removed.
           *
           * Although the POSIX specification says:
           *
           * "Attempting to initialize an already initialized mutex results
           * in undefined behavior."
           *
           * Trying to keep the caller from doing the create when *mutex
           * is actually a valid ID causes grief. All it takes is the wrong
           * value in an uninitialized variable to make this fail. As best
           * I can tell,   RTEMS was the only pthread implementation to choose
           * this option for "undefined behavior" and doing so has created
           * portability problems. In particular,   Rosimildo DaSilva
           * <rdasilva@connecttel.com> saw seemingly random failures in the
           * RTEMS port of omniORB2 when this code was enabled.
           *
           * Joel Sherrill <joel@OARcorp.com> 14 May 1999
           * NOTE: Be careful to avoid infinite recursion on call to this
           * routine in _POSIX_Mutex_Get.
           */
           #if 0
           {
           POSIX_Mutex_Control *mutex_in_use;
           Objects_Locations location;
          
           if (   *mutex != PTHREAD_MUTEX_INITIALIZER  ) {
          
           /* EBUSY if *mutex is a valid id */
          
           mutex_in_use = _POSIX_Mutex_Get(   mutex,   &location  );
           switch (   location  ) {
           case OBJECTS_LOCAL:
           _Thread_Enable_dispatch(   );
           return EBUSY;
           #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           #endif
           case OBJECTS_ERROR:
           break;
           }
           }
           }
           #endif
          
           if (   !the_attr->is_initialized  )
           return EINVAL;
          
           /*
           * We only support process private mutexes.
           */
           if (   the_attr->process_shared == PTHREAD_PROCESS_SHARED  )
           return ENOSYS;
          
           if (   the_attr->process_shared != PTHREAD_PROCESS_PRIVATE  )
           return EINVAL;
          
           /*
           * Determine the discipline of the mutex
           */
           switch (   the_attr->protocol  ) {
           case PTHREAD_PRIO_NONE:
           the_discipline = CORE_MUTEX_DISCIPLINES_FIFO;
           break;
           case PTHREAD_PRIO_INHERIT:
           the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
           break;
           case PTHREAD_PRIO_PROTECT:
           the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
           break;
           default:
           return EINVAL;
           }
          
           /*
           * Validate the priority ceiling field -- should always be valid.
           */
           if (   !_POSIX_Priority_Is_valid(   the_attr->prio_ceiling  )  )
           return EINVAL;
          
          #if defined(  _UNIX98_THREAD_MUTEX_ATTRIBUTES )
           /*
           * Validate the mutex type and set appropriate SuperCore mutex
           * attributes.
           */
           switch (   the_attr->type  ) {
           case PTHREAD_MUTEX_NORMAL:
           case PTHREAD_MUTEX_RECURSIVE:
           case PTHREAD_MUTEX_ERRORCHECK:
           case PTHREAD_MUTEX_DEFAULT:
           break;
          
           default:
           return EINVAL;
           }
          #endif
          
           /*
           * Enter a dispatching critical section and begin to do the real work.
           */
           _Thread_Disable_dispatch(   );
          
           the_mutex = _POSIX_Mutex_Allocate(   );
          
           if (   !the_mutex  ) {
           _Thread_Enable_dispatch(   );
           return EAGAIN;
           }
          
           the_mutex->process_shared = the_attr->process_shared;
          
           the_mutex_attr = &the_mutex->Mutex.Attributes;
          
           if (   the_attr->recursive  )
           the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
           else
           the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_IS_ERROR;
           the_mutex_attr->only_owner_release = true;
           the_mutex_attr->priority_ceiling =
           _POSIX_Priority_To_core(   the_attr->prio_ceiling  );
           the_mutex_attr->discipline = the_discipline;
          
           /*
           * Must be initialized to unlocked.
           */
           _CORE_mutex_Initialize(  
           &the_mutex->Mutex,  
           the_mutex_attr,  
           CORE_MUTEX_UNLOCKED
            );
          
           _Objects_Open_u32(   &_POSIX_Mutex_Information,   &the_mutex->Object,   0  );
          
           *mutex = the_mutex->Object.id;
          
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/mutexlock.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexlock.c,  v 1.6 2009/02/03 10:10:51 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 11.3.3 Locking and Unlocking a Mutex,   P1003.1c/Draft 10,   p. 93
           *
           * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(   ),   p. 29
           */
          
      36  int pthread_mutex_lock(  
           pthread_mutex_t *mutex
           )
          {
           return _POSIX_Mutex_Lock_support(   mutex,   true,   THREAD_QUEUE_WAIT_FOREVER  );
          }

posix/src/mutexlocksupp.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexlocksupp.c,  v 1.10 2008/09/04 15:23:12 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * _POSIX_Mutex_Lock_support
           *
           * A support routine which implements guts of the blocking,   non-blocking,   and
           * timed wait version of mutex lock.
           */
          
      37  int _POSIX_Mutex_Lock_support(  
           pthread_mutex_t *mutex,  
           bool blocking,  
           Watchdog_Interval timeout
           )
          {
           register POSIX_Mutex_Control *the_mutex;
           Objects_Locations location;
           ISR_Level level;
          
           the_mutex = _POSIX_Mutex_Get_interrupt_disable(   mutex,   &location,   &level  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _CORE_mutex_Seize(  
           &the_mutex->Mutex,  
           the_mutex->Object.id,  
           blocking,  
           timeout,  
           level
            );
           return _POSIX_Mutex_Translate_core_mutex_return_code(  
           (  CORE_mutex_Status ) _Thread_Executing->Wait.return_code
            );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/mutexsetprioceiling.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexsetprioceiling.c,  v 1.13 2009/07/07 21:04:57 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 13.6.2 Change the Priority Ceiling of a Mutex,   P1003.1c/Draft 10,   p. 131
           */
          
      31  int pthread_mutex_setprioceiling(  
           pthread_mutex_t *mutex,  
           int prioceiling,  
           int *old_ceiling
           )
          {
           register POSIX_Mutex_Control *the_mutex;
           Objects_Locations location;
           Priority_Control the_priority;
          
           if (   !old_ceiling  )
           return EINVAL;
          
           if (   !_POSIX_Priority_Is_valid(   prioceiling  )  )
           return EINVAL;
          
           the_priority = _POSIX_Priority_To_core(   prioceiling  );
          
           /*
           * Must acquire the mutex before we can change it's ceiling.
           * POSIX says block until we acquire it.
           */
           (  void ) pthread_mutex_lock(   mutex  );
          
           /*
           * Do not worry about the return code from this. The Get operation
           * will also fail if it is a bad id or was deleted between the two
           * operations.
           *
           * NOTE: This makes it easier to get 100% binary coverage since the
           * bad Id case is handled by the switch.
           */
           the_mutex = _POSIX_Mutex_Get(   mutex,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           *old_ceiling = _POSIX_Priority_From_core(  
           the_mutex->Mutex.Attributes.priority_ceiling
            );
           the_mutex->Mutex.Attributes.priority_ceiling = the_priority;
           /*
           * We are required to unlock the mutex before we return.
           */
           _CORE_mutex_Surrender(  
           &the_mutex->Mutex,  
           the_mutex->Object.id,  
           NULL
            );
           _Thread_Enable_dispatch(   );
          
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* impossible to get here */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/mutextimedlock.c

       1  /*
           * Mutex Timed Lock
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutextimedlock.c,  v 1.13 2010/10/21 22:21:09 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 11.3.3 Locking and Unlocking a Mutex,   P1003.1c/Draft 10,   p. 93
           *
           * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(   ),   p. 29
           */
          
      40  int pthread_mutex_timedlock(  
           pthread_mutex_t *mutex,  
           const struct timespec *abstime
           )
          {
           Watchdog_Interval ticks;
           bool do_wait = true;
           POSIX_Absolute_timeout_conversion_results_t status;
           int lock_status;
          
           /*
           * POSIX requires that blocking calls with timeouts that take
           * an absolute timeout must ignore issues with the absolute
           * time provided if the operation would otherwise succeed.
           * So we check the abstime provided,   and hold on to whether it
           * is valid or not. If it isn't correct and in the future,  
           * then we do a polling operation and convert the UNSATISFIED
           * status into the appropriate error.
           *
           * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID,  
           * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST,   or POSIX_ABSOLUTE_TIMEOUT_IS_NOW,  
           * then we should not wait.
           */
           status = _POSIX_Absolute_timeout_to_ticks(   abstime,   &ticks  );
           if (   status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE  )
           do_wait = false;
          
           lock_status = _POSIX_Mutex_Lock_support(   mutex,   do_wait,   ticks  );
           /*
           * This service only gives us the option to block. We used a polling
           * attempt to lock if the abstime was not in the future. If we did
           * not obtain the mutex,   then not look at the status immediately,  
           * make sure the right reason is returned.
           */
           if (   !do_wait && (  lock_status == EBUSY )  ) {
           if (   status == POSIX_ABSOLUTE_TIMEOUT_INVALID  )
           return EINVAL;
           if (   status == POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
           status == POSIX_ABSOLUTE_TIMEOUT_IS_NOW  )
           return ETIMEDOUT;
           }
          
           return lock_status;
          }

posix/src/mutextranslatereturncode.c

       1  /*
           * POSIX Mutex Error Translation
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutextranslatereturncode.c,  v 1.3 2009/03/12 15:32:58 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          
          /*
           * _POSIX_Mutex_Translate_core_mutex_return_code
           *
           * Input parameters:
           * the_mutex_status - mutex status code to translate
           *
           * Output parameters:
           * status code - translated POSIX status code
           *
           */
          
          static int _POSIX_Mutex_Return_codes[CORE_MUTEX_STATUS_LAST + 1] = {
           0,   /* CORE_MUTEX_STATUS_SUCCESSFUL */
           EBUSY,   /* CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT */
           EDEADLK,   /* CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED */
           EPERM,   /* CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE */
           EINVAL,   /* CORE_MUTEX_WAS_DELETED */
           ETIMEDOUT,   /* CORE_MUTEX_TIMEOUT */
          #ifdef __RTEMS_STRICT_ORDER_MUTEX__
           EDEADLK,   /* CORE_MUTEX_RELEASE_NOT_ORDER */
          #endif
           EINVAL /* CORE_MUTEX_STATUS_CEILING_VIOLATED */
          };
          
          
      49  int _POSIX_Mutex_Translate_core_mutex_return_code(  
           CORE_mutex_Status the_mutex_status
           )
          {
           /*
           * Internal consistency check for bad status from SuperCore
           */
           #if defined(  RTEMS_DEBUG )
           if (   the_mutex_status > CORE_MUTEX_STATUS_LAST  )
           return EINVAL;
           #endif
           return _POSIX_Mutex_Return_codes[the_mutex_status];
          }

posix/src/mutextrylock.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutextrylock.c,  v 1.6 2009/02/03 10:10:51 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 11.3.3 Locking and Unlocking a Mutex,   P1003.1c/Draft 10,   p. 93
           *
           * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(   ),   p. 29
           */
          
      36  int pthread_mutex_trylock(  
           pthread_mutex_t *mutex
           )
          {
           return _POSIX_Mutex_Lock_support(   mutex,   false,   THREAD_QUEUE_WAIT_FOREVER  );
          }

posix/src/mutexunlock.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mutexunlock.c,  v 1.10 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/watchdog.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * 11.3.3 Locking and Unlocking a Mutex,   P1003.1c/Draft 10,   p. 93
           *
           * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(   ),   p. 29
           */
          
      36  int pthread_mutex_unlock(  
           pthread_mutex_t *mutex
           )
          {
           register POSIX_Mutex_Control *the_mutex;
           Objects_Locations location;
           CORE_mutex_Status status;
          
           the_mutex = _POSIX_Mutex_Get(   mutex,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           status = _CORE_mutex_Surrender(  
           &the_mutex->Mutex,  
           the_mutex->Object.id,  
           NULL
            );
           _Thread_Enable_dispatch(   );
           return _POSIX_Mutex_Translate_core_mutex_return_code(   status  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/nanosleep.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: nanosleep.c,  v 1.11 2010/06/22 15:36:06 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          
          #include <rtems/seterr.h>
          #include <rtems/score/timespec.h>
          
          /*PAGE
           *
           * 14.2.5 High Resolution Sleep,   P1003.1b-1993,   p. 269
           */
          
      32  int nanosleep(  
           const struct timespec *rqtp,  
           struct timespec *rmtp
           )
          {
           Watchdog_Interval ticks;
          
          
           /*
           * Return EINVAL if the delay interval is negative.
           *
           * NOTE: This behavior is beyond the POSIX specification.
           * FSU and GNU/Linux pthreads shares this behavior.
           */
           if (   !_Timespec_Is_valid(   rqtp  )  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           ticks = _Timespec_To_ticks(   rqtp  );
          
           /*
           * A nanosleep for zero time is implemented as a yield.
           * This behavior is also beyond the POSIX specification but is
           * consistent with the RTEMS API and yields desirable behavior.
           */
          
           if (   !ticks  ) {
           _Thread_Disable_dispatch(   );
           _Thread_Yield_processor(   );
           _Thread_Enable_dispatch(   );
           if (   rmtp  ) {
           rmtp->tv_sec = 0;
           rmtp->tv_nsec = 0;
           }
           return 0;
           }
          
           /*
           * Block for the desired amount of time
           */
           _Thread_Disable_dispatch(   );
           _Thread_Set_state(  
           _Thread_Executing,  
           STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL
            );
           _Watchdog_Initialize(  
           &_Thread_Executing->Timer,  
           _Thread_Delay_ended,  
           _Thread_Executing->Object.id,  
           NULL
            );
           _Watchdog_Insert_ticks(   &_Thread_Executing->Timer,   ticks  );
           _Thread_Enable_dispatch(   );
          
           /* calculate time remaining */
          
           if (   rmtp  ) {
           ticks -=
           _Thread_Executing->Timer.stop_time - _Thread_Executing->Timer.start_time;
          
           _Timespec_From_ticks(   ticks,   rmtp  );
          
           /*
           * Only when POSIX is enabled,   can a sleep be interrupted.
           */
           #if defined(  RTEMS_POSIX_API )
           /*
           * If there is time remaining,   then we were interrupted by a signal.
           */
           if (   ticks  )
           rtems_set_errno_and_return_minus_one(   EINTR  );
           #endif
           }
          
           return 0;
          }

posix/src/pause.c

       1  /*
           * 3.4.2 Suspend Process Execution,   P1003.1b-1993,   p. 81
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pause.c,  v 1.5 2004/04/15 13:24:47 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <signal.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          
          /*
           * 3.4.2 Suspend Process Execution,   P1003.1b-1993,   p. 81
           */
          
      30  int pause(   void  )
          {
           sigset_t all_signals;
           int status;
          
           (  void ) sigfillset(   &all_signals  );
          
           status = sigtimedwait(   &all_signals,   NULL,   NULL  );
          
           return status;
          }

posix/src/pbarrier.c

       1  /*
           * Barrier Manager
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Barrier Manager.
           *
           * Directives provided are:
           *
           * + create a barrier
           * + get an ID of a barrier
           * + delete a barrier
           * + acquire a barrier
           * + release a barrier
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pbarrier.c,  v 1.5 2009/02/03 10:10:51 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/posix/barrier.h>
          
          /**
           * @brief _POSIX_Barrier_Manager_initialization
           */
          
      40  void _POSIX_Barrier_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_POSIX_Barrier_Information,   /* object information table */
           OBJECTS_POSIX_API,   /* object API */
           OBJECTS_POSIX_BARRIERS,   /* object class */
           Configuration_POSIX_API.maximum_barriers,  
           /* maximum objects of this class */
           sizeof(   POSIX_Barrier_Control  ),  /* size of this object's control block */
           true,   /* true if the name is a string */
           _POSIX_PATH_MAX /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

posix/src/pbarrierdestroy.c

       1  /*
           * POSIX Barrier Manager -- Destroy a Barrier
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pbarrierdestroy.c,  v 1.3 2007/11/30 20:34:13 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/barrier.h>
          
          /*
           * pthread_barrier_destroy
           *
           * This directive allows a thread to delete a barrier specified by
           * the barrier id. The barrier is freed back to the inactive
           * barrier chain.
           *
           * Input parameters:
           * barrier - barrier id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      39  int pthread_barrier_destroy(  
           pthread_barrier_t *barrier
           )
          {
           POSIX_Barrier_Control *the_barrier = NULL;
           Objects_Locations location;
          
           if (   !barrier  )
           return EINVAL;
          
           the_barrier = _POSIX_Barrier_Get(   barrier,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   the_barrier->Barrier.number_of_waiting_threads != 0  ) {
           _Thread_Enable_dispatch(   );
           return EBUSY;
           }
          
           _Objects_Close(   &_POSIX_Barrier_Information,   &the_barrier->Object  );
          
           _POSIX_Barrier_Free(   the_barrier  );
          
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/pbarrierinit.c

       1  /*
           * POSIX Barrier Manager -- Initialize a Barrier Instance
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pbarrierinit.c,  v 1.3 2008/01/23 22:57:43 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/barrier.h>
          
          /*
           * pthread_barrier_init
           *
           * This directive creates a barrier. A barrier id is returned.
           *
           * Input parameters:
           * barrier - pointer to barrier id
           * attr - barrier attributes
           * count - number of threads before automatic release
           *
           * Output parameters:
           * barrier - barrier id
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      40  int pthread_barrier_init(  
           pthread_barrier_t *barrier,  
           const pthread_barrierattr_t *attr,  
           unsigned int count
           )
          {
           POSIX_Barrier_Control *the_barrier;
           CORE_barrier_Attributes the_attributes;
           pthread_barrierattr_t my_attr;
           const pthread_barrierattr_t *the_attr;
          
           /*
           * Error check parameters
           */
           if (   !barrier  )
           return EINVAL;
          
           if (   count == 0  )
           return EINVAL;
          
           /*
           * If the user passed in NULL,   use the default attributes
           */
           if (   attr  ) {
           the_attr = attr;
           } else {
           (  void ) pthread_barrierattr_init(   &my_attr  );
           the_attr = &my_attr;
           }
          
           /*
           * Now start error checking the attributes that we are going to use
           */
           if (   !the_attr->is_initialized  )
           return EINVAL;
          
           switch (   the_attr->process_shared  ) {
           case PTHREAD_PROCESS_PRIVATE: /* only supported values */
           break;
           case PTHREAD_PROCESS_SHARED:
           default:
           return EINVAL;
           }
          
           /*
           * Convert from POSIX attributes to Core Barrier attributes
           */
           the_attributes.discipline = CORE_BARRIER_AUTOMATIC_RELEASE;
           the_attributes.maximum_count = count;
          
           /*
           * Enter dispatching critical section to allocate and initialize barrier
           */
           _Thread_Disable_dispatch(   ); /* prevents deletion */
          
           the_barrier = _POSIX_Barrier_Allocate(   );
          
           if (   !the_barrier  ) {
           _Thread_Enable_dispatch(   );
           return EAGAIN;
           }
          
           _CORE_barrier_Initialize(   &the_barrier->Barrier,   &the_attributes  );
          
           _Objects_Open_u32(  
           &_POSIX_Barrier_Information,  
           &the_barrier->Object,  
           0
            );
          
           /*
           * Exit the critical section and return the user an operational barrier
           */
           *barrier = the_barrier->Object.id;
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/pbarriertranslatereturncode.c

       1  /*
           * Barrier Manager -- Translate SuperCore Status
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pbarriertranslatereturncode.c,  v 1.2 2007/11/30 20:34:13 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/barrier.h>
          
          /*
           * _POSIX_Barrier_Translate_core_barrier_return_code
           *
           * Input parameters:
           * the_barrier_status - barrier status code to translate
           *
           * Output parameters:
           * status code - translated POSIX status code
           *
           */
          
          static int _POSIX_Barrier_Return_codes[CORE_BARRIER_STATUS_LAST + 1] = {
           0,   /* CORE_BARRIER_STATUS_SUCCESSFUL */
           PTHREAD_BARRIER_SERIAL_THREAD,  
           /* CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED */
           -1,   /* CORE_BARRIER_WAS_DELETED */
           0 /* CORE_BARRIER_TIMEOUT */
          };
          
          
      44  int _POSIX_Barrier_Translate_core_barrier_return_code(  
           CORE_barrier_Status the_barrier_status
           )
          {
           /*
           * Internal consistency check for bad status from SuperCore
           */
           #if defined(  RTEMS_DEBUG )
           if (   the_barrier_status > CORE_BARRIER_STATUS_LAST  )
           return EINVAL;
           #endif
           return _POSIX_Barrier_Return_codes[the_barrier_status];
          }

posix/src/pbarrierwait.c

       1  /*
           * POSIX Barrier Manager -- Wait at a Barrier
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pbarrierwait.c,  v 1.4 2009/01/02 10:04:23 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/barrier.h>
          
          /*
           * pthread_barrier_wait
           *
           * This directive allows a thread to wait at a barrier.
           *
           * Input parameters:
           * barrier - barrier id
           *
           * Output parameters:
           * 0 - if successful
           * PTHREAD_BARRIER_SERIAL_THREAD - if successful
           * error code - if unsuccessful
           */
          
      38  int pthread_barrier_wait(  
           pthread_barrier_t *barrier
           )
          {
           POSIX_Barrier_Control *the_barrier = NULL;
           Objects_Locations location;
          
           if (   !barrier  )
           return EINVAL;
          
           the_barrier = _POSIX_Barrier_Get(   barrier,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _CORE_barrier_Wait(  
           &the_barrier->Barrier,  
           the_barrier->Object.id,  
           true,  
           0,  
           NULL
            );
           _Thread_Enable_dispatch(   );
           return _POSIX_Barrier_Translate_core_barrier_return_code(  
           _Thread_Executing->Wait.return_code  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/posixtimespecabsolutetimeout.c

       1  /*
           * Convert abstime timeout to ticks
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: posixtimespecabsolutetimeout.c,  v 1.4 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*
           * The abstime is a walltime. We turn it into an interval.
           */
      37  POSIX_Absolute_timeout_conversion_results_t _POSIX_Absolute_timeout_to_ticks(  
           const struct timespec *abstime,  
           Watchdog_Interval *ticks_out
           )
          {
           struct timespec current_time;
           struct timespec difference;
          
          
           /*
           * Make sure there is always a value returned.
           */
           *ticks_out = 0;
          
           /*
           * Is the absolute time even valid?
           */
           if (   !_Timespec_Is_valid(  abstime )  )
           return POSIX_ABSOLUTE_TIMEOUT_INVALID;
          
           /*
           * Is the absolute time in the past?
           */
           _TOD_Get(   &current_time  );
          
           if (   _Timespec_Less_than(   abstime,   &current_time  )  )
           return POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST;
          
           /*
           * How long until the requested absolute time?
           */
           _Timespec_Subtract(   &current_time,   abstime,   &difference  );
          
           /*
           * Internally the SuperCore uses ticks,   so convert to them.
           */
           *ticks_out = _Timespec_To_ticks(   &difference  );
          
           /*
           * If the difference was 0,   then the future is now. It is so bright
           * we better wear shades.
           */
           if (   !*ticks_out  )
           return POSIX_ABSOLUTE_TIMEOUT_IS_NOW;
          
           /*
           * This is the case we were expecting and it took this long to
           * get here.
           */
           return POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE;
          }
          

posix/src/prwlock.c

       1  /*
           * RWLock Manager -- Initialization
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: prwlock.c,  v 1.5 2009/02/03 10:10:51 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/posix/rwlock.h>
          
          /**
           * @brief _POSIX_RWLock_Manager_initialization
           */
          
      28  void _POSIX_RWLock_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_POSIX_RWLock_Information,   /* object information table */
           OBJECTS_POSIX_API,   /* object API */
           OBJECTS_POSIX_SPINLOCKS,   /* object class */
           Configuration_POSIX_API.maximum_rwlocks,  
           /* maximum objects of this class */
           sizeof(   POSIX_RWLock_Control  ),   /* size of this object's control block */
           true,   /* true if the name is a string */
           _POSIX_PATH_MAX /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

posix/src/prwlockdestroy.c

       1  /*
           * POSIX RWLock Manager -- Destroy a RWLock
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: prwlockdestroy.c,  v 1.4 2007/11/30 20:34:13 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/rwlock.h>
          
          /*
           * pthread_rwlock_destroy
           *
           * This directive allows a thread to delete a rwlock specified by
           * the rwlock id. The rwlock is freed back to the inactive
           * rwlock chain.
           *
           * Input parameters:
           * rwlock - rwlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      39  int pthread_rwlock_destroy(  
           pthread_rwlock_t *rwlock
           )
          {
           POSIX_RWLock_Control *the_rwlock = NULL;
           Objects_Locations location;
          
           if (   !rwlock  )
           return EINVAL;
          
           the_rwlock = _POSIX_RWLock_Get(   rwlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           /*
           * If there is at least one thread waiting,   then do not delete it.
           */
           if (   _Thread_queue_First(   &the_rwlock->RWLock.Wait_queue  ) != NULL  ) {
           _Thread_Enable_dispatch(   );
           return EBUSY;
           }
          
           /*
           * POSIX doesn't require behavior when it is locked.
           */
          
           _Objects_Close(   &_POSIX_RWLock_Information,   &the_rwlock->Object  );
          
           _POSIX_RWLock_Free(   the_rwlock  );
          
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/prwlockinit.c

       1  /*
           * POSIX RWLock Manager -- Destroy a RWLock Instance
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: prwlockinit.c,  v 1.5 2010/08/25 20:01:47 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/rwlock.h>
          
          /*
           * pthread_rwlock_init
           *
           * This directive creates a rwlock. A rwlock id is returned.
           *
           * Input parameters:
           * rwlock - pointer to rwlock id
           * attr - rwlock attributes
           *
           * Output parameters:
           * rwlock - rwlock id
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      39  int pthread_rwlock_init(  
           pthread_rwlock_t *rwlock,  
           const pthread_rwlockattr_t *attr
           )
          {
           POSIX_RWLock_Control *the_rwlock;
           CORE_RWLock_Attributes the_attributes;
           pthread_rwlockattr_t default_attr;
           const pthread_rwlockattr_t *the_attr;
          
           /*
           * Error check parameters
           */
           if (   !rwlock  )
           return EINVAL;
          
           /*
           * If the user passed in NULL,   use the default attributes
           */
           if (   attr  ) {
           the_attr = attr;
           } else {
           (  void ) pthread_rwlockattr_init(   &default_attr  );
           the_attr = &default_attr;
           }
          
           /*
           * Now start error checking the attributes that we are going to use
           */
           if (   !the_attr->is_initialized  )
           return EINVAL;
          
           switch (   the_attr->process_shared  ) {
           case PTHREAD_PROCESS_PRIVATE: /* only supported values */
           break;
           case PTHREAD_PROCESS_SHARED:
           default:
           return EINVAL;
           }
          
           /*
           * Convert from POSIX attributes to Core RWLock attributes
           *
           * NOTE: Currently there are no core rwlock attributes
           */
           _CORE_RWLock_Initialize_attributes(   &the_attributes  );
          
           /*
           * Enter dispatching critical section to allocate and initialize RWLock
           */
           _Thread_Disable_dispatch(   ); /* prevents deletion */
          
           the_rwlock = _POSIX_RWLock_Allocate(   );
          
           if (   !the_rwlock  ) {
           _Thread_Enable_dispatch(   );
           return EAGAIN;
           }
          
           _CORE_RWLock_Initialize(   &the_rwlock->RWLock,   &the_attributes  );
          
           _Objects_Open_u32(  
           &_POSIX_RWLock_Information,  
           &the_rwlock->Object,  
           0
            );
          
           *rwlock = the_rwlock->Object.id;
          
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/prwlockrdlock.c

       1  /*
           * POSIX RWLock Manager -- Obtain a Read Lock on a RWLock Instance
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: prwlockrdlock.c,  v 1.6 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/rwlock.h>
          
          /*
           * pthread_rwlock_rdlock
           *
           * This directive attempts to obtain a read only lock on an rwlock instance.
           *
           * Input parameters:
           * rwlock - pointer to rwlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      37  int pthread_rwlock_rdlock(  
           pthread_rwlock_t *rwlock
           )
          {
           POSIX_RWLock_Control *the_rwlock;
           Objects_Locations location;
          
           if (   !rwlock  )
           return EINVAL;
          
           the_rwlock = _POSIX_RWLock_Get(   rwlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           _CORE_RWLock_Obtain_for_reading(  
           &the_rwlock->RWLock,  
           *rwlock,  
           true,   /* we are willing to wait forever */
           0,  
           NULL
            );
          
           _Thread_Enable_dispatch(   );
           return _POSIX_RWLock_Translate_core_RWLock_return_code(  
           (  CORE_RWLock_Status ) _Thread_Executing->Wait.return_code
            );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/prwlocktimedrdlock.c

       1  /*
           * POSIX RWLock Manager -- Attempt to Obtain a Read Lock on a RWLock Instance
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: prwlocktimedrdlock.c,  v 1.12 2010/08/23 21:31:27 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/rwlock.h>
          #include <rtems/posix/time.h>
          
          /*
           * pthread_rwlock_timedrdlock
           *
           * This directive attempts to obtain a read only lock on an rwlock instance.
           *
           * Input parameters:
           * rwlock - pointer to rwlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      38  int pthread_rwlock_timedrdlock(  
           pthread_rwlock_t *rwlock,  
           const struct timespec *abstime
           )
          {
           POSIX_RWLock_Control *the_rwlock;
           Objects_Locations location;
           Watchdog_Interval ticks;
           bool do_wait = true;
           POSIX_Absolute_timeout_conversion_results_t status;
          
           if (   !rwlock  )
           return EINVAL;
          
           /*
           * POSIX requires that blocking calls with timeouts that take
           * an absolute timeout must ignore issues with the absolute
           * time provided if the operation would otherwise succeed.
           * So we check the abstime provided,   and hold on to whether it
           * is valid or not. If it isn't correct and in the future,  
           * then we do a polling operation and convert the UNSATISFIED
           * status into the appropriate error.
           *
           * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID,  
           * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST,   or POSIX_ABSOLUTE_TIMEOUT_IS_NOW,  
           * then we should not wait.
           */
           status = _POSIX_Absolute_timeout_to_ticks(   abstime,   &ticks  );
           if (   status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE  )
           do_wait = false;
          
           the_rwlock = _POSIX_RWLock_Get(   rwlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           _CORE_RWLock_Obtain_for_reading(  
           &the_rwlock->RWLock,  
           *rwlock,  
           do_wait,  
           ticks,  
           NULL
            );
          
           _Thread_Enable_dispatch(   );
           if (   !do_wait  ) {
           if (   _Thread_Executing->Wait.return_code == CORE_RWLOCK_UNAVAILABLE  ) {
           if (   status == POSIX_ABSOLUTE_TIMEOUT_INVALID  )
           return EINVAL;
           if (   status == POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
           status == POSIX_ABSOLUTE_TIMEOUT_IS_NOW  )
           return ETIMEDOUT;
           }
           }
          
           return _POSIX_RWLock_Translate_core_RWLock_return_code(  
           (  CORE_RWLock_Status ) _Thread_Executing->Wait.return_code
            );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/prwlocktimedwrlock.c

       1  /*
           * POSIX RWLock Manager -- Attempt to Obtain a Write Lock on a RWLock Instance
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: prwlocktimedwrlock.c,  v 1.11 2010/08/23 21:31:27 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/rwlock.h>
          #include <rtems/posix/time.h>
          
          /*
           * pthread_rwlock_timedwrlock
           *
           * This directive attempts to obtain a write only lock on an rwlock instance.
           *
           * Input parameters:
           * rwlock - pointer to rwlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      38  int pthread_rwlock_timedwrlock(  
           pthread_rwlock_t *rwlock,  
           const struct timespec *abstime
           )
          {
           POSIX_RWLock_Control *the_rwlock;
           Objects_Locations location;
           Watchdog_Interval ticks;
           bool do_wait = true;
           POSIX_Absolute_timeout_conversion_results_t status;
          
           if (   !rwlock  )
           return EINVAL;
          
           /*
           * POSIX requires that blocking calls with timeouts that take
           * an absolute timeout must ignore issues with the absolute
           * time provided if the operation would otherwise succeed.
           * So we check the abstime provided,   and hold on to whether it
           * is valid or not. If it isn't correct and in the future,  
           * then we do a polling operation and convert the UNSATISFIED
           * status into the appropriate error.
           *
           * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID,  
           * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST,   or POSIX_ABSOLUTE_TIMEOUT_IS_NOW,  
           * then we should not wait.
           */
           status = _POSIX_Absolute_timeout_to_ticks(   abstime,   &ticks  );
           if (   status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE  )
           do_wait = false;
          
           the_rwlock = _POSIX_RWLock_Get(   rwlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           _CORE_RWLock_Obtain_for_writing(  
           &the_rwlock->RWLock,  
           *rwlock,  
           do_wait,  
           ticks,  
           NULL
            );
          
           _Thread_Enable_dispatch(   );
           if (   !do_wait &&
           (  _Thread_Executing->Wait.return_code == CORE_RWLOCK_UNAVAILABLE )  ) {
           if (   status == POSIX_ABSOLUTE_TIMEOUT_INVALID  )
           return EINVAL;
           if (   status == POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
           status == POSIX_ABSOLUTE_TIMEOUT_IS_NOW  )
           return ETIMEDOUT;
           }
          
           return _POSIX_RWLock_Translate_core_RWLock_return_code(  
           (  CORE_RWLock_Status ) _Thread_Executing->Wait.return_code
            );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/prwlocktranslatereturncode.c

       1  /*
           * RWLock Manager -- Translate SuperCore Status
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: prwlocktranslatereturncode.c,  v 1.2 2007/11/30 20:34:13 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/rwlock.h>
          
          /*
           * _POSIX_RWLock_Translate_core_rwlock_return_code
           *
           * Input parameters:
           * the_rwlock_status - rwlock status code to translate
           *
           * Output parameters:
           * status code - translated POSIX status code
           *
           */
          
          static int _POSIX_RWLock_Return_codes[CORE_RWLOCK_STATUS_LAST + 1] = {
           0,   /* CORE_RWLOCK_SUCCESSFUL */
           EINVAL,   /* CORE_RWLOCK_DELETED */
           EBUSY,   /* CORE_RWLOCK_UNAVAILABLE */
           ETIMEDOUT,   /* CORE_RWLOCK_TIMEOUT */
          };
          
          
      43  int _POSIX_RWLock_Translate_core_RWLock_return_code(  
           CORE_RWLock_Status the_rwlock_status
           )
          {
           /*
           * Internal consistency check for bad status from SuperCore
           */
           #if defined(  RTEMS_DEBUG )
           if (   the_rwlock_status > CORE_RWLOCK_STATUS_LAST  )
           return EINVAL;
           #endif
           return _POSIX_RWLock_Return_codes[the_rwlock_status];
          }

posix/src/prwlocktryrdlock.c

       1  /*
           * POSIX RWLock Manager -- Attempt to Obtain a Read Lock on a RWLock Instance
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: prwlocktryrdlock.c,  v 1.6 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/rwlock.h>
          
          /*
           * pthread_rwlock_tryrdlock
           *
           * This directive attempts to obtain a read only lock on an rwlock instance.
           *
           * Input parameters:
           * rwlock - pointer to rwlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      37  int pthread_rwlock_tryrdlock(  
           pthread_rwlock_t *rwlock
           )
          {
           POSIX_RWLock_Control *the_rwlock;
           Objects_Locations location;
          
           if (   !rwlock  )
           return EINVAL;
          
           the_rwlock = _POSIX_RWLock_Get(   rwlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           _CORE_RWLock_Obtain_for_reading(  
           &the_rwlock->RWLock,  
           *rwlock,  
           false,   /* do not wait for the rwlock */
           0,  
           NULL
            );
          
          
           _Thread_Enable_dispatch(   );
           return _POSIX_RWLock_Translate_core_RWLock_return_code(  
           (  CORE_RWLock_Status ) _Thread_Executing->Wait.return_code
            );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/prwlocktrywrlock.c

       1  /*
           * POSIX RWLock Manager -- Attempt to Obtain a Write Lock on a RWLock Instance
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: prwlocktrywrlock.c,  v 1.6 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/rwlock.h>
          
          /*
           * pthread_rwlock_trywrlock
           *
           * This directive attempts to obtain a Write only lock on an rwlock instance.
           *
           * Input parameters:
           * rwlock - pointer to rwlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      37  int pthread_rwlock_trywrlock(  
           pthread_rwlock_t *rwlock
           )
          {
           POSIX_RWLock_Control *the_rwlock;
           Objects_Locations location;
          
           if (   !rwlock  )
           return EINVAL;
          
           the_rwlock = _POSIX_RWLock_Get(   rwlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           _CORE_RWLock_Obtain_for_writing(  
           &the_rwlock->RWLock,  
           *rwlock,  
           false,   /* we are not willing to wait */
           0,  
           NULL
            );
          
           _Thread_Enable_dispatch(   );
           return _POSIX_RWLock_Translate_core_RWLock_return_code(  
           (  CORE_RWLock_Status ) _Thread_Executing->Wait.return_code
            );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/prwlockunlock.c

       1  /*
           * POSIX RWLock Manager -- Release a lock held on a RWLock Instance
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: prwlockunlock.c,  v 1.5 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/rwlock.h>
          
          /*
           * pthread_rwlock_unlock
           *
           * This directive attempts to release a lock on an RWLock.
           *
           * Input parameters:
           * rwlock - pointer to rwlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      37  int pthread_rwlock_unlock(  
           pthread_rwlock_t *rwlock
           )
          {
           POSIX_RWLock_Control *the_rwlock;
           Objects_Locations location;
           CORE_RWLock_Status status;
          
           if (   !rwlock  )
           return EINVAL;
          
           the_rwlock = _POSIX_RWLock_Get(   rwlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           status = _CORE_RWLock_Release(   &the_rwlock->RWLock  );
           _Thread_Enable_dispatch(   );
           return _POSIX_RWLock_Translate_core_RWLock_return_code(   status  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/prwlockwrlock.c

       1  /*
           * POSIX RWLock Manager -- Obtain a Write Lock on a RWLock Instance
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: prwlockwrlock.c,  v 1.6 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/rwlock.h>
          
          /*
           * pthread_rwlock_wrlock
           *
           * This directive attempts to obtain a write only lock on an rwlock instance.
           *
           * Input parameters:
           * rwlock - pointer to rwlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      37  int pthread_rwlock_wrlock(  
           pthread_rwlock_t *rwlock
           )
          {
           POSIX_RWLock_Control *the_rwlock;
           Objects_Locations location;
          
           if (   !rwlock  )
           return EINVAL;
          
           the_rwlock = _POSIX_RWLock_Get(   rwlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           _CORE_RWLock_Obtain_for_writing(  
           &the_rwlock->RWLock,  
           *rwlock,  
           true,   /* do not timeout -- wait forever */
           0,  
           NULL
            );
          
           _Thread_Enable_dispatch(   );
           return _POSIX_RWLock_Translate_core_RWLock_return_code(  
           (  CORE_RWLock_Status ) _Thread_Executing->Wait.return_code
            );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/psignal.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: psignal.c,  v 1.69 2010/09/28 07:40:34 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_DEBUG )
           #include <assert.h>
          #endif
          #include <errno.h>
          #include <pthread.h>
          #include <signal.h>
          #include <string.h> /* memcpy */
          #include <stdlib.h> /* exit */
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tqdata.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/threadsup.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/time.h>
          #include <stdio.h>
          
          /*** PROCESS WIDE STUFF ****/
          
          sigset_t _POSIX_signals_Pending;
          
      42  void _POSIX_signals_Abnormal_termination_handler(  
           int signo __attribute__(  (  unused ) )  )
          {
           exit(   1  );
          }
          
          #define SIG_ARRAY_MAX (  SIGRTMAX + 1 )
          const struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = {
           /* NO SIGNAL 0 */ SIGACTION_IGNORE,  
           /* SIGHUP 1 */ SIGACTION_TERMINATE,  
           /* SIGINT 2 */ SIGACTION_TERMINATE,  
           /* SIGQUIT 3 */ SIGACTION_TERMINATE,  
           /* SIGILL 4 */ SIGACTION_TERMINATE,  
           /* SIGTRAP 5 */ SIGACTION_TERMINATE,  
           /* SIGIOT 6 */ SIGACTION_TERMINATE,  
           /* SIGABRT 6 SIGACTION_TERMINATE,   -- alias for SIGIOT */
           /* SIGEMT 7 */ SIGACTION_TERMINATE,  
           /* SIGFPE 8 */ SIGACTION_TERMINATE,  
           /* SIGKILL 9 */ SIGACTION_TERMINATE,  
           /* SIGBUS 10 */ SIGACTION_TERMINATE,  
           /* SIGSEGV 11 */ SIGACTION_TERMINATE,  
           /* SIGSYS 12 */ SIGACTION_TERMINATE,  
           /* SIGPIPE 13 */ SIGACTION_TERMINATE,  
           /* SIGALRM 14 */ SIGACTION_TERMINATE,  
           /* SIGTERM 15 */ SIGACTION_TERMINATE,  
           /* SIGURG 16 */ SIGACTION_TERMINATE,  
           /* SIGSTOP 17 */ SIGACTION_TERMINATE,  
           /* SIGTSTP 18 */ SIGACTION_TERMINATE,  
           /* SIGCONT 19 */ SIGACTION_TERMINATE,  
           /* SIGCHLD 20 */ SIGACTION_TERMINATE,  
           /* SIGTTIN 21 */ SIGACTION_TERMINATE,  
           /* SIGTTOU 22 */ SIGACTION_TERMINATE,  
           /* SIGIO 23 */ SIGACTION_TERMINATE,  
           /* SIGWINCH 24 */ SIGACTION_TERMINATE,  
           /* SIGUSR1 25 */ SIGACTION_TERMINATE,  
           /* SIGUSR2 26 */ SIGACTION_TERMINATE,  
           /* SIGRT 27 */ SIGACTION_TERMINATE,  
           /* SIGRT 28 */ SIGACTION_TERMINATE,  
           /* SIGRT 29 */ SIGACTION_TERMINATE,  
           /* SIGRT 30 */ SIGACTION_TERMINATE,  
           /* SIGRTMAX 31 */ SIGACTION_TERMINATE
          };
          
          struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
          
          Thread_queue_Control _POSIX_signals_Wait_queue;
          
          Chain_Control _POSIX_signals_Inactive_siginfo;
          Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
          
          Watchdog_Control _POSIX_signals_Alarm_timer;
          Watchdog_Control _POSIX_signals_Ualarm_timer;
          
          /*PAGE
           *
           * XXX - move these
           */
          
          #define _States_Is_interruptible_signal(   _states  ) \
           (   (  (  _states ) & \
           (  STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL ) ) == \
           (  STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL ) )
          
          /*
     106   * _POSIX_signals_Post_switch_extension
           */
          
          void _POSIX_signals_Post_switch_extension(  
           Thread_Control *the_thread
           )
          {
           POSIX_API_Control *api;
           int signo;
           ISR_Level level;
          
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           /*
           * api may be NULL in case of a thread close in progress
           */
           if (   !api  )
           return;
          
           /*
           * If we invoke any user code,   there is the possibility that
           * a new signal has been posted that we should process so we
           * restart the loop if a signal handler was invoked.
           *
           * The first thing done is to check there are any signals to be
           * processed at all. No point in doing this loop otherwise.
           */
           while (  1 ) {
           _ISR_Disable(   level  );
           if (   !(  ~api->signals_blocked &
           (  api->signals_pending | _POSIX_signals_Pending ) )  ) {
           _ISR_Enable(   level  );
           break;
           }
           _ISR_Enable(   level  );
          
           for (   signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++  ) {
           _POSIX_signals_Check_signal(   api,   signo,   false  );
           _POSIX_signals_Check_signal(   api,   signo,   true  );
           }
           /* Unfortunately - nothing like __SIGFIRSTNOTRT in newlib signal .h */
          
           for (   signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++  ) {
           _POSIX_signals_Check_signal(   api,   signo,   false  );
           _POSIX_signals_Check_signal(   api,   signo,   true  );
           }
           }
          }
          
          /*PAGE
           *
     157   * _POSIX_signals_Manager_Initialization
           */
          
          void _POSIX_signals_Manager_Initialization(  void )
          {
           uint32_t signo;
           uint32_t maximum_queued_signals;
          
           maximum_queued_signals = Configuration_POSIX_API.maximum_queued_signals;
          
           /*
           * Ensure we have the same number of vectors and default vector entries
           */
          
           #if defined(  RTEMS_DEBUG )
           assert(  
           sizeof(  _POSIX_signals_Vectors ) == sizeof(  _POSIX_signals_Default_vectors )
            );
           #endif
          
           memcpy(  
           _POSIX_signals_Vectors,  
           _POSIX_signals_Default_vectors,  
           sizeof(   _POSIX_signals_Vectors  )
            );
          
           /*
           * Initialize the set of pending signals for the entire process
           */
           sigemptyset(   &_POSIX_signals_Pending  );
          
           /*
           * Initialize the queue we use to block for signals
           */
           _Thread_queue_Initialize(  
           &_POSIX_signals_Wait_queue,  
           THREAD_QUEUE_DISCIPLINE_FIFO,  
           STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL,  
           EAGAIN
            );
          
           /* XXX status codes */
          
           /*
           * Allocate the siginfo pools.
           */
           for (   signo=1 ; signo<= SIGRTMAX ; signo++  )
           _Chain_Initialize_empty(   &_POSIX_signals_Siginfo[ signo ]  );
          
           if (   maximum_queued_signals  ) {
           _Chain_Initialize(  
           &_POSIX_signals_Inactive_siginfo,  
           _Workspace_Allocate_or_fatal_error(  
           maximum_queued_signals * sizeof(   POSIX_signals_Siginfo_node  )
            ),  
           maximum_queued_signals,  
           sizeof(   POSIX_signals_Siginfo_node  )
            );
           } else {
           _Chain_Initialize_empty(   &_POSIX_signals_Inactive_siginfo  );
           }
          
           /*
           * Initialize the Alarm Timer
           */
           _Watchdog_Initialize(   &_POSIX_signals_Alarm_timer,   NULL,   0,   NULL  );
           _Watchdog_Initialize(   &_POSIX_signals_Ualarm_timer,   NULL,   0,   NULL  );
          }

posix/src/psignalchecksignal.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: psignalchecksignal.c,  v 1.10 2010/07/27 16:34:26 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if defined(  RTEMS_DEBUG )
           #include <assert.h>
          #endif
          #include <errno.h>
          #include <pthread.h>
          #include <signal.h>
          #include <string.h>
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tqdata.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/threadsup.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/time.h>
          #include <stdio.h>
          
          
          /*PAGE
           *
           * _POSIX_signals_Check_signal
           */
          
      42  bool _POSIX_signals_Check_signal(  
           POSIX_API_Control *api,  
           int signo,  
           bool is_global
           )
          {
           siginfo_t siginfo_struct;
           sigset_t saved_signals_blocked;
           Thread_Wait_information stored_thread_wait_information;
          
           if (   ! _POSIX_signals_Clear_signals(   api,   signo,   &siginfo_struct,  
           is_global,   true  )  )
           return false;
          
           /*
           * Since we made a union of these,   only one test is necessary but this is
           * safer.
           */
           #if defined(  RTEMS_DEBUG )
           assert(   _POSIX_signals_Vectors[ signo ].sa_handler ||
           _POSIX_signals_Vectors[ signo ].sa_sigaction  );
           #endif
          
           /*
           * Just to prevent sending a signal which is currently being ignored.
           */
           if (   _POSIX_signals_Vectors[ signo ].sa_handler == SIG_IGN  )
           return false;
          
           /*
           * Block the signals requested in sa_mask
           */
           saved_signals_blocked = api->signals_blocked;
           api->signals_blocked |= _POSIX_signals_Vectors[ signo ].sa_mask;
          
           /*
           * We have to save the blocking information of the current wait queue
           * because the signal handler may subsequently go on and put the thread
           * on a wait queue,   for its own purposes.
           */
           memcpy(   &stored_thread_wait_information,   &_Thread_Executing->Wait,  
           sizeof(   Thread_Wait_information  ) );
          
           /*
           * Here,   the signal handler function executes
           */
           switch (   _POSIX_signals_Vectors[ signo ].sa_flags  ) {
           case SA_SIGINFO:
           (  *_POSIX_signals_Vectors[ signo ].sa_sigaction )(  
           signo,  
           &siginfo_struct,  
           NULL /* context is undefined per 1003.1b-1993,   p. 66 */
            );
           break;
           default:
           (  *_POSIX_signals_Vectors[ signo ].sa_handler )(   signo  );
           break;
           }
          
           /*
           * Restore the blocking information
           */
           memcpy(   &_Thread_Executing->Wait,   &stored_thread_wait_information,  
           sizeof(   Thread_Wait_information  ) );
          
           /*
           * Restore the previous set of blocked signals
           */
           api->signals_blocked = saved_signals_blocked;
          
           return true;
          }

posix/src/psignalclearprocesssignals.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: psignalclearprocesssignals.c,  v 1.7 2010/06/29 00:34:10 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          #include <signal.h>
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tqdata.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/threadsup.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/time.h>
          #include <stdio.h>
          
          /*PAGE
           *
           * _POSIX_signals_Clear_process_signals
           */
          
      37  void _POSIX_signals_Clear_process_signals(  
           int signo
           )
          {
           sigset_t mask;
           bool clear_signal;
          
           clear_signal = true;
           mask = signo_to_mask(   signo  );
          
           ISR_Level level;
          
           _ISR_Disable(   level  );
           if (   _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO  ) {
           if (   !_Chain_Is_empty(   &_POSIX_signals_Siginfo[ signo ]  )  )
           clear_signal = false;
           }
           if (   clear_signal  ) {
           _POSIX_signals_Pending &= ~mask;
           }
           _ISR_Enable(   level  );
          }

posix/src/psignalclearsignals.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: psignalclearsignals.c,  v 1.10 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          #include <signal.h>
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tqdata.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/threadsup.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/time.h>
          #include <stdio.h>
          
          /*PAGE
           *
           * _POSIX_signals_Clear_signals
           */
          
      37  bool _POSIX_signals_Clear_signals(  
           POSIX_API_Control *api,  
           int signo,  
           siginfo_t *info,  
           bool is_global,  
           bool check_blocked
           )
          {
           sigset_t mask;
           sigset_t signals_blocked;
           ISR_Level level;
           bool do_callout;
           POSIX_signals_Siginfo_node *psiginfo;
          
           mask = signo_to_mask(   signo  );
          
           do_callout = false;
          
           /* set blocked signals based on if checking for them,   SIGNAL_ALL_MASK
           * insures that no signals are blocked and all are checked.
           */
          
           if (   check_blocked  )
           signals_blocked = ~api->signals_blocked;
           else
           signals_blocked = SIGNAL_ALL_MASK;
          
           /* XXX is this right for siginfo type signals? */
           /* XXX are we sure they can be cleared the same way? */
          
           _ISR_Disable(   level  );
           if (   is_global  ) {
           if (   mask & (  _POSIX_signals_Pending & signals_blocked )  ) {
           if (   _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO  ) {
           psiginfo = (  POSIX_signals_Siginfo_node * )
           _Chain_Get_unprotected(   &_POSIX_signals_Siginfo[ signo ]  );
           _POSIX_signals_Clear_process_signals(   signo  );
           /*
           * It may be impossible to get here with an empty chain
           * BUT until that is proven we need to be defensive and
           * protect against it.
           */
           if (   psiginfo  ) {
           *info = psiginfo->Info;
           _Chain_Append_unprotected(  
           &_POSIX_signals_Inactive_siginfo,  
           &psiginfo->Node
            );
           } else
           do_callout = false;
           }
           _POSIX_signals_Clear_process_signals(   signo  );
           do_callout = true;
           }
           } else {
           if (   mask & (  api->signals_pending & signals_blocked )  ) {
           api->signals_pending &= ~mask;
           do_callout = true;
           }
           }
           _ISR_Enable(   level  );
           return do_callout;
          }

posix/src/psignalsetprocesssignals.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: psignalsetprocesssignals.c,  v 1.7 2010/06/29 00:34:11 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          #include <signal.h>
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tqdata.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/threadsup.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/time.h>
          #include <stdio.h>
          
          /*PAGE
           *
           * _POSIX_signals_Set_process_signals
           */
          
      37  void _POSIX_signals_Set_process_signals(  
           sigset_t mask
           )
          {
           ISR_Level level;
          
           _ISR_Disable(   level  );
           _POSIX_signals_Pending |= mask;
           _ISR_Enable(   level  );
          }

posix/src/psignalunblockthread.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: psignalunblockthread.c,  v 1.15 2010/10/21 22:27:16 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          #include <signal.h>
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tqdata.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/threadsup.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/time.h>
          #include <stdio.h>
          
          
          /*PAGE
           *
           * _POSIX_signals_Unblock_thread
           */
          
          /* XXX this routine could probably be cleaned up */
      39  bool _POSIX_signals_Unblock_thread(  
           Thread_Control *the_thread,  
           int signo,  
           siginfo_t *info
           )
          {
           POSIX_API_Control *api;
           sigset_t mask;
           siginfo_t *the_info = NULL;
          
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           mask = signo_to_mask(   signo  );
          
           /*
           * Is the thread is specifically waiting for a signal?
           */
          
           if (   _States_Is_interruptible_signal(   the_thread->current_state  )  ) {
          
           if (   (  the_thread->Wait.option & mask ) || (  ~api->signals_blocked & mask )  ) {
           the_thread->Wait.return_code = EINTR;
          
           the_info = (  siginfo_t * ) the_thread->Wait.return_argument;
          
           if (   !info  ) {
           the_info->si_signo = signo;
           the_info->si_code = SI_USER;
           the_info->si_value.sival_int = 0;
           } else {
           *the_info = *info;
           }
          
           _Thread_queue_Extract_with_proxy(   the_thread  );
           return true;
           }
          
           /*
           * This should only be reached via pthread_kill(   ).
           */
          
           return false;
           }
          
           /*
           * Thread is not waiting due to a sigwait.
           */
           if (   ~api->signals_blocked & mask  ) {
          
           /*
           * The thread is interested in this signal. We are going
           * to post it. We have a few broad cases:
           * + If it is blocked on an interruptible signal,   THEN
           * we unblock the thread.
           * + If it is in the ready state AND
           * we are sending from an ISR AND
           * it is the interrupted thread AND
           * it is not blocked,   THEN
           * we need to dispatch at the end of this ISR.
           * + Any other combination,   do nothing.
           */
          
           if (   _States_Is_interruptible_by_signal(   the_thread->current_state  )  ) {
           the_thread->Wait.return_code = EINTR;
           /*
           * In pthread_cond_wait,   a thread will be blocking on a thread
           * queue,   but is also interruptible by a POSIX signal.
           */
           if (   _States_Is_waiting_on_thread_queue(  the_thread->current_state )  )
           _Thread_queue_Extract_with_proxy(   the_thread  );
           else if (   _States_Is_delaying(  the_thread->current_state )  ) {
           (  void ) _Watchdog_Remove(   &the_thread->Timer  );
           _Thread_Unblock(   the_thread  );
           }
          
           } else if (   the_thread->current_state == STATES_READY  ) {
           if (   _ISR_Is_in_progress(   ) && _Thread_Is_executing(   the_thread  )  )
           _Thread_Dispatch_necessary = true;
           }
           }
           return false;
          }

posix/src/pspin.c

       1  /*
           * Spinlock Manager
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Spinlock Manager.
           *
           * Directives provided are:
           *
           * + create a spinlock
           * + get an ID of a spinlock
           * + delete a spinlock
           * + acquire a spinlock
           * + release a spinlock
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pspin.c,  v 1.5 2009/02/03 10:10:53 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/posix/spinlock.h>
          
          /**
           * @brief _POSIX_Spinlock_Manager_initialization
           */
          
      40  void _POSIX_Spinlock_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_POSIX_Spinlock_Information,   /* object information table */
           OBJECTS_POSIX_API,   /* object API */
           OBJECTS_POSIX_SPINLOCKS,   /* object class */
           Configuration_POSIX_API.maximum_spinlocks,  
           /* maximum objects of this class */
           sizeof(   POSIX_Spinlock_Control  ),  /* size of this object's control block */
           true,   /* true if the name is a string */
           _POSIX_PATH_MAX /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

posix/src/pspindestroy.c

       1  /*
           * POSIX Spinlock Manager -- Destroy a Spinlock
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pspindestroy.c,  v 1.3 2007/11/30 20:34:13 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/spinlock.h>
          
          /*
           * pthread_spin_destroy
           *
           * This directive allows a thread to delete a spinlock specified by
           * the spinlock id. The spinlock is freed back to the inactive
           * spinlock chain.
           *
           * Input parameters:
           * spinlock - spinlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      39  int pthread_spin_destroy(  
           pthread_spinlock_t *spinlock
           )
          {
           POSIX_Spinlock_Control *the_spinlock = NULL;
           Objects_Locations location;
          
           if (   !spinlock  )
           return EINVAL;
          
           the_spinlock = _POSIX_Spinlock_Get(   spinlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   _CORE_spinlock_Is_busy(   &the_spinlock->Spinlock  )  ) {
           _Thread_Enable_dispatch(   );
           return EBUSY;
           }
          
           _Objects_Close(   &_POSIX_Spinlock_Information,   &the_spinlock->Object  );
          
           _POSIX_Spinlock_Free(   the_spinlock  );
          
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/pspininit.c

       1  /*
           * POSIX Spinlock Manager -- Initialize a Spinlock Instance
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pspininit.c,  v 1.4 2010/08/25 20:01:47 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/spinlock.h>
          
          /*
           * pthread_spinlock_init
           *
           * This directive creates a spinlock. A spinlock id is returned.
           *
           * Input parameters:
           * spinlock - pointer to spinlock id
           * pshared - is this spinlock shared between processes
           *
           * Output parameters:
           * spinlock - spinlock id
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      39  int pthread_spin_init(  
           pthread_spinlock_t *spinlock,  
           int pshared
           )
          {
           POSIX_Spinlock_Control *the_spinlock;
           CORE_spinlock_Attributes attributes;
          
          
           if (   !spinlock  )
           return EINVAL;
          
           switch (   pshared  ) {
           case PTHREAD_PROCESS_PRIVATE: /* only supported values */
           break;
           case PTHREAD_PROCESS_SHARED:
           default:
           return EINVAL;
           }
          
           _Thread_Disable_dispatch(   ); /* prevents deletion */
          
           the_spinlock = _POSIX_Spinlock_Allocate(   );
          
           if (   !the_spinlock  ) {
           _Thread_Enable_dispatch(   );
           return EAGAIN;
           }
          
           _CORE_spinlock_Initialize_attributes(   &attributes  );
          
           _CORE_spinlock_Initialize(   &the_spinlock->Spinlock,   &attributes  );
          
           _Objects_Open_u32(   &_POSIX_Spinlock_Information,   &the_spinlock->Object,   0  );
          
           *spinlock = the_spinlock->Object.id;
          
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/pspinlock.c

       1  /*
           * POSIX Spinlock Manager -- Wait at a Spinlock
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pspinlock.c,  v 1.4 2009/02/03 10:10:53 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/spinlock.h>
          
          /*
           * pthread_spin_lock
           *
           * This directive allows a thread to wait at a spinlock.
           *
           * Input parameters:
           * spinlock - spinlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      37  int pthread_spin_lock(  
           pthread_spinlock_t *spinlock
           )
          {
           POSIX_Spinlock_Control *the_spinlock = NULL;
           Objects_Locations location;
           CORE_spinlock_Status status;
          
           if (   !spinlock  )
           return EINVAL;
          
           the_spinlock = _POSIX_Spinlock_Get(   spinlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           status = _CORE_spinlock_Wait(   &the_spinlock->Spinlock,   true,   0  );
           _Thread_Enable_dispatch(   );
           return _POSIX_Spinlock_Translate_core_spinlock_return_code(   status  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/pspinlocktranslatereturncode.c

       1  /*
           * Spinlock Manager -- Translate SuperCore Status
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pspinlocktranslatereturncode.c,  v 1.3 2007/11/30 20:34:13 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/corespinlock.h>
          
          /*
           * _POSIX_Spinlock_Translate_core_spinlock_return_code
           *
           * Input parameters:
           * the_spinlock_status - spinlock status code to translate
           *
           * Output parameters:
           * status code - translated POSIX status code
           *
           */
          
          static int _POSIX_Spinlock_Return_codes[CORE_SPINLOCK_STATUS_LAST + 1] = {
           0,   /* CORE_SPINLOCK_SUCCESSFUL */
           EDEADLK,   /* CORE_SPINLOCK_HOLDER_RELOCKING */
           EPERM,   /* CORE_SPINLOCK_NOT_HOLDER */
           -1,   /* CORE_SPINLOCK_TIMEOUT */
           EBUSY,   /* CORE_SPINLOCK_IS_BUSY */
           EBUSY,   /* CORE_SPINLOCK_UNAVAILABLE */
           0 /* CORE_SPINLOCK_NOT_LOCKED */
          };
          
          
      46  int _POSIX_Spinlock_Translate_core_spinlock_return_code(  
           CORE_spinlock_Status the_spinlock_status
           )
          {
           /*
           * Internal consistency check for bad status from SuperCore
           */
           #if defined(  RTEMS_DEBUG )
           if (   the_spinlock_status > CORE_SPINLOCK_STATUS_LAST  )
           return EINVAL;
           #endif
           return _POSIX_Spinlock_Return_codes[the_spinlock_status];
          }

posix/src/pspintrylock.c

       1  /*
           * POSIX Spinlock Manager -- Wait at a Spinlock
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pspintrylock.c,  v 1.4 2009/02/03 10:10:53 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/spinlock.h>
          
          /*
           * pthread_spin_trylock
           *
           * This directive allows a thread to poll an attempt at locking a spinlock.
           *
           * Input parameters:
           * spinlock - spinlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      37  int pthread_spin_trylock(  
           pthread_spinlock_t *spinlock
           )
          {
           POSIX_Spinlock_Control *the_spinlock = NULL;
           Objects_Locations location;
           CORE_spinlock_Status status;
          
           if (   !spinlock  )
           return EINVAL;
          
           the_spinlock = _POSIX_Spinlock_Get(   spinlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           status = _CORE_spinlock_Wait(   &the_spinlock->Spinlock,   false,   0  );
           _Thread_Enable_dispatch(   );
           return _POSIX_Spinlock_Translate_core_spinlock_return_code(   status  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/pspinunlock.c

       1  /*
           * POSIX Spinlock Manager -- Wait at a Spinlock
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pspinunlock.c,  v 1.3 2007/11/30 20:34:13 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/spinlock.h>
          
          /*
           * pthread_spin_unlock
           *
           * This directive allows a thread to wait at a spinlock.
           *
           * Input parameters:
           * spinlock - spinlock id
           *
           * Output parameters:
           * 0 - if successful
           * error code - if unsuccessful
           */
          
      37  int pthread_spin_unlock(  
           pthread_spinlock_t *spinlock
           )
          {
           POSIX_Spinlock_Control *the_spinlock = NULL;
           Objects_Locations location;
           CORE_spinlock_Status status;
          
           if (   !spinlock  )
           return EINVAL;
          
           the_spinlock = _POSIX_Spinlock_Get(   spinlock,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           status = _CORE_spinlock_Release(   &the_spinlock->Spinlock  );
           _Thread_Enable_dispatch(   );
           return _POSIX_Spinlock_Translate_core_spinlock_return_code(   status  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return EINVAL;
          }

posix/src/psxpriorityisvalid.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: psxpriorityisvalid.c,  v 1.1 2009/06/24 06:38:52 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/posix/priority.h>
          
      19  bool _POSIX_Priority_Is_valid(  
           int priority
           )
          {
           return (  (  priority >= POSIX_SCHEDULER_MINIMUM_PRIORITY ) &&
           (  priority <= POSIX_SCHEDULER_MAXIMUM_PRIORITY ) );
          
          }
          

posix/src/psxtransschedparam.c

       1  /* COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: psxtransschedparam.c,  v 1.5 2010/04/03 05:55:58 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
      23  int _POSIX_Thread_Translate_sched_param(  
           int policy,  
           struct sched_param *param,  
           Thread_CPU_budget_algorithms *budget_algorithm,  
           Thread_CPU_budget_algorithm_callout *budget_callout
           )
          {
           if (   !_POSIX_Priority_Is_valid(   param->sched_priority  )  )
           return EINVAL;
          
           *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
           *budget_callout = NULL;
          
           if (   policy == SCHED_OTHER  ) {
           *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
           return 0;
           }
          
           if (   policy == SCHED_FIFO  ) {
           *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
           return 0;
           }
          
           if (   policy == SCHED_RR  ) {
           *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE;
           return 0;
           }
          
           if (   policy == SCHED_SPORADIC  ) {
           if (   (  param->sched_ss_repl_period.tv_sec == 0 ) &&
           (  param->sched_ss_repl_period.tv_nsec == 0 )  )
           return EINVAL;
          
           if (   (  param->sched_ss_init_budget.tv_sec == 0 ) &&
           (  param->sched_ss_init_budget.tv_nsec == 0 )  )
           return EINVAL;
          
           if (   _Timespec_To_ticks(   &param->sched_ss_repl_period  ) <
           _Timespec_To_ticks(   &param->sched_ss_init_budget  )  )
           return EINVAL;
          
           if (   !_POSIX_Priority_Is_valid(   param->sched_ss_low_priority  )  )
           return EINVAL;
          
           *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
           *budget_callout = _POSIX_Threads_Sporadic_budget_callout;
           return 0;
           }
          
           return EINVAL;
          }

posix/src/pthread.c

       1  /*
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthread.c,  v 1.81 2010/10/04 15:32:36 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/cancel.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/posix/config.h>
          #include <rtems/posix/key.h>
          #include <rtems/posix/time.h>
          #include <rtems/score/timespec.h>
          
          /*
           * The default pthreads attributes structure.
           *
           * NOTE: Be careful .. if the default attribute set changes,  
           * _POSIX_Threads_Initialize_user_threads will need to be examined.
           */
          const pthread_attr_t _POSIX_Threads_Default_attributes = {
           true,   /* is_initialized */
           NULL,   /* stackaddr */
           0,   /* stacksize -- will be adjusted to minimum */
           PTHREAD_SCOPE_PROCESS,   /* contentionscope */
           PTHREAD_INHERIT_SCHED,   /* inheritsched */
           SCHED_FIFO,   /* schedpolicy */
           { /* schedparam */
           2,   /* sched_priority */
           #if defined(  _POSIX_SPORADIC_SERVER ) || \
           defined(  _POSIX_THREAD_SPORADIC_SERVER )
           0,   /* sched_ss_low_priority */
           { 0L,   0 },   /* sched_ss_repl_period */
           { 0L,   0 } /* sched_ss_init_budget */
           #endif
           },  
           #if HAVE_DECL_PTHREAD_ATTR_SETGUARDSIZE
           0,   /* guardsize */
           #endif
           #if defined(  _POSIX_THREAD_CPUTIME )
           1,   /* cputime_clock_allowed */
           #endif
           PTHREAD_CREATE_JOINABLE,   /* detachstate */
          };
          
          /*
           * _POSIX_Threads_Sporadic_budget_TSR
      69   */
          void _POSIX_Threads_Sporadic_budget_TSR(  
           Objects_Id id __attribute__(  (  unused ) ),  
           void *argument
           )
          {
           uint32_t ticks;
           uint32_t new_priority;
           Thread_Control *the_thread;
           POSIX_API_Control *api;
          
           the_thread = argument;
          
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           /* ticks is guaranteed to be at least one */
           ticks = _Timespec_To_ticks(   &api->schedparam.sched_ss_init_budget  );
          
           the_thread->cpu_time_budget = ticks;
          
           new_priority = _POSIX_Priority_To_core(   api->schedparam.sched_priority  );
           the_thread->real_priority = new_priority;
          
           /*
           * If holding a resource,   then do not change it.
           */
           #if 0
           printk(   "TSR %d %d %d\n",   the_thread->resource_count,  
           the_thread->current_priority,   new_priority  );
           #endif
           if (   the_thread->resource_count == 0  ) {
           /*
           * If this would make them less important,   then do not change it.
           */
           if (   the_thread->current_priority > new_priority  ) {
           _Thread_Change_priority(   the_thread,   new_priority,   true  );
           #if 0
           printk(   "raise priority\n"  );
           #endif
           }
           }
          
           /* ticks is guaranteed to be at least one */
           ticks = _Timespec_To_ticks(   &api->schedparam.sched_ss_repl_period  );
          
           _Watchdog_Insert_ticks(   &api->Sporadic_timer,   ticks  );
          }
          
          /*
           * _POSIX_Threads_Sporadic_budget_callout
     119   */
          void _POSIX_Threads_Sporadic_budget_callout(  
           Thread_Control *the_thread
           )
          {
           POSIX_API_Control *api;
           uint32_t new_priority;
          
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           /*
           * This will prevent the thread from consuming its entire "budget"
           * while at low priority.
           */
           the_thread->cpu_time_budget = 0xFFFFFFFF; /* XXX should be based on MAX_U32 */
          
           new_priority = _POSIX_Priority_To_core(  api->schedparam.sched_ss_low_priority );
           the_thread->real_priority = new_priority;
          
           /*
           * If holding a resource,   then do not change it.
           */
           #if 0
           printk(   "callout %d %d %d\n",   the_thread->resource_count,  
           the_thread->current_priority,   new_priority  );
           #endif
           if (   the_thread->resource_count == 0  ) {
           /*
           * Make sure we are actually lowering it. If they have lowered it
           * to logically lower than sched_ss_low_priority,   then we do not want to
           * change it.
           */
           if (   the_thread->current_priority < new_priority  ) {
           _Thread_Change_priority(   the_thread,   new_priority,   true  );
           #if 0
           printk(   "lower priority\n"  );
           #endif
           }
           }
          }
          
          /*
           * _POSIX_Threads_Create_extension
           *
           * This method is invoked for each thread created.
           */
     165  
          bool _POSIX_Threads_Create_extension(  
           Thread_Control *executing __attribute__(  (  unused ) ),  
           Thread_Control *created
           )
          {
           POSIX_API_Control *api;
           POSIX_API_Control *executing_api;
          
           api = _Workspace_Allocate(   sizeof(   POSIX_API_Control  )  );
          
           if (   !api  )
           return false;
          
           created->API_Extensions[ THREAD_API_POSIX ] = api;
          
           /* XXX check all fields are touched */
           api->Attributes = _POSIX_Threads_Default_attributes;
           api->detachstate = _POSIX_Threads_Default_attributes.detachstate;
           api->schedpolicy = _POSIX_Threads_Default_attributes.schedpolicy;
           api->schedparam = _POSIX_Threads_Default_attributes.schedparam;
           api->schedparam.sched_priority =
           _POSIX_Priority_From_core(   created->current_priority  );
          
           /*
           * POSIX 1003.1 1996,   18.2.2.2
           */
           api->cancelation_requested = 0;
           api->cancelability_state = PTHREAD_CANCEL_ENABLE;
           api->cancelability_type = PTHREAD_CANCEL_DEFERRED;
           _Chain_Initialize_empty (  &api->Cancellation_Handlers );
          
           /*
           * If the thread is not a posix thread,   then all posix signals are blocked
           * by default.
           *
           * The check for class == 1 is debug. Should never really happen.
           */
          
           /* XXX use signal constants */
           api->signals_pending = 0;
           if (   _Objects_Get_API(   created->Object.id  ) == OBJECTS_POSIX_API
           #if defined(  RTEMS_DEBUG )
           && _Objects_Get_class(   created->Object.id  ) == 1
           #endif
            ) {
           executing_api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
           api->signals_blocked = executing_api->signals_blocked;
           } else {
           api->signals_blocked = 0xffffffff;
           }
          
           _Thread_queue_Initialize(  
           &api->Join_List,  
           THREAD_QUEUE_DISCIPLINE_FIFO,  
           STATES_WAITING_FOR_JOIN_AT_EXIT,  
           0
            );
          
           _Watchdog_Initialize(  
           &api->Sporadic_timer,  
           _POSIX_Threads_Sporadic_budget_TSR,  
           created->Object.id,  
           created
            );
          
           return true;
          }
          
          /*
           * _POSIX_Threads_Delete_extension
           *
           * This method is invoked for each thread deleted.
     238   */
          void _POSIX_Threads_Delete_extension(  
           Thread_Control *executing __attribute__(  (  unused ) ),  
           Thread_Control *deleted
           )
          {
           Thread_Control *the_thread;
           POSIX_API_Control *api;
           void **value_ptr;
          
           api = deleted->API_Extensions[ THREAD_API_POSIX ];
          
           /*
           * Run the POSIX cancellation handlers
           */
           _POSIX_Threads_cancel_run(   deleted  );
          
           /*
           * Run all the key destructors
           */
           _POSIX_Keys_Run_destructors(   deleted  );
          
           /*
           * Wakeup all the tasks which joined with this one
           */
           value_ptr = (  void ** ) deleted->Wait.return_argument;
          
           while (   (  the_thread = _Thread_queue_Dequeue(   &api->Join_List  ) )  )
           *(  void ** )the_thread->Wait.return_argument = value_ptr;
          
           if (   api->schedpolicy == SCHED_SPORADIC  )
           (  void ) _Watchdog_Remove(   &api->Sporadic_timer  );
          
           deleted->API_Extensions[ THREAD_API_POSIX ] = NULL;
          
           (  void ) _Workspace_Free(   api  );
          }
          
          /*
           * _POSIX_Threads_Exitted_extension
           *
           * This method is invoked each time a thread exits.
     280   */
          void _POSIX_Threads_Exitted_extension(  
           Thread_Control *executing
           )
          {
           /*
           * If the executing thread was not created with the POSIX API,   then this
           * API do not get to define its exit behavior.
           */
           if (   _Objects_Get_API(   executing->Object.id  ) == OBJECTS_POSIX_API  )
           pthread_exit(   executing->Wait.return_argument  );
          }
          
          /*
           * _POSIX_Threads_Initialize_user_threads
           *
           * This routine creates and starts all configured user
           * initialzation threads.
     298   */
          void _POSIX_Threads_Initialize_user_threads(   void  )
          {
           if (   _POSIX_Threads_Initialize_user_threads_p  )
           (  *_POSIX_Threads_Initialize_user_threads_p )(   );
          }
          
          /*
           * API Extension control structures
           */
          API_extensions_Control _POSIX_Threads_API_extensions = {
           { NULL,   NULL },  
           #if defined(  FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API )
           NULL,   /* predriver */
           #endif
           _POSIX_Threads_Initialize_user_threads,   /* postdriver */
           _POSIX_signals_Post_switch_extension,   /* post switch */
          };
          
          User_extensions_Control _POSIX_Threads_User_extensions = {
           { NULL,   NULL },  
           { { NULL,   NULL },   NULL },  
           { _POSIX_Threads_Create_extension,   /* create */
           NULL,   /* start */
           NULL,   /* restart */
           _POSIX_Threads_Delete_extension,   /* delete */
           NULL,   /* switch */
           NULL,   /* begin */
           _POSIX_Threads_Exitted_extension,   /* exitted */
           NULL /* fatal */
           }
          };
          
          /*
           * _POSIX_Threads_Manager_initialization
           *
           * This routine initializes all threads manager related data structures.
     335   */
          void _POSIX_Threads_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_POSIX_Threads_Information,   /* object information table */
           OBJECTS_POSIX_API,   /* object API */
           OBJECTS_POSIX_THREADS,   /* object class */
           Configuration_POSIX_API.maximum_threads,  
           /* maximum objects of this class */
           sizeof(   Thread_Control  ),  
           /* size of this object's control block */
           true,   /* true if names for this object are strings */
           _POSIX_PATH_MAX /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          
           /*
           * Add all the extensions for this API
           */
           _User_extensions_Add_API_set(   &_POSIX_Threads_User_extensions  );
          
           _API_extensions_Add(   &_POSIX_Threads_API_extensions  );
          
           /*
           * If we supported MP,   then here we would ...
           * Register the MP Process Packet routine.
           */
          }

posix/src/pthreadatfork.c

       1  /*
           * pthread_atfork(   ) - POSIX 1003.1b 3.1.3
           *
           * 3.1.3 Register Fork Handlers,   P1003.1c/Draft 10,   P1003.1c/Draft 10,   p. 27
           *
           * RTEMS does not support processes,   so we fall under this and do not
           * provide this routine:
           *
           * "Either the implementation shall support the pthread_atfork(   ) function
           * as described above or the pthread_atfork(   ) funciton shall not be
           * provided."
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadatfork.c,  v 1.6 2009/01/02 10:04:24 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <rtems/seterr.h>
          
      30  int pthread_atfork(  
           void (  *prepare )(  void ) __attribute__(  (  unused ) ),  
           void (  *parent )(  void ) __attribute__(  (  unused ) ),  
           void (  *child )(  void ) __attribute__(  (  unused ) )
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/pthreadattrdestroy.c

       1  /*
           * 16.1.1 Thread Creation Attributes,   P1003.1c/Draft 10,   p,   140
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrdestroy.c,  v 1.5 2009/02/03 10:10:54 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          
      23  int pthread_attr_destroy(  
           pthread_attr_t *attr
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           attr->is_initialized = false;
           return 0;
          }

posix/src/pthreadattrgetdetachstate.c

       1  /*
           * 16.1.1 Thread Creation Attributes,   P1003.1c/Draft 10,   p,   140
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrgetdetachstate.c,  v 1.5 2004/04/15 13:24:47 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_getdetachstate(  
           const pthread_attr_t *attr,  
           int *detachstate
           )
          {
           if (   !attr || !attr->is_initialized || !detachstate  )
           return EINVAL;
          
           *detachstate = attr->detachstate;
           return 0;
          }

posix/src/pthreadattrgetguardsize.c

       1  /*
           * 16.1.1 Thread Creation Attributes
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrgetguardsize.c,  v 1.1 2010/10/04 15:32:36 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_DECL_PTHREAD_ATTR_GETGUARDSIZE
          #include <pthread.h>
          #include <errno.h>
          
      22  int pthread_attr_getguardsize(  
           const pthread_attr_t *attr,  
           size_t *guardsize
           )
          {
           if (   !attr || !attr->is_initialized || !guardsize  )
           return EINVAL;
          
           *guardsize = attr->guardsize;
           return 0;
          }
          #endif

posix/src/pthreadattrgetinheritsched.c

       1  /*
           * 13.5.1 Thread Creation Scheduling Attributes,   P1003.1c/Draft 10,   p. 120
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrgetinheritsched.c,  v 1.5 2004/04/15 13:24:47 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_getinheritsched(  
           const pthread_attr_t *attr,  
           int *inheritsched
           )
          {
           if (   !attr || !attr->is_initialized || !inheritsched  )
           return EINVAL;
          
           *inheritsched = attr->inheritsched;
           return 0;
          }

posix/src/pthreadattrgetschedparam.c

       1  /*
           * 13.5.1 Thread Creation Scheduling Attributes,   P1003.1c/Draft 10,   p. 120
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrgetschedparam.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_getschedparam(  
           const pthread_attr_t *attr,  
           struct sched_param *param
           )
          {
           if (   !attr || !attr->is_initialized || !param  )
           return EINVAL;
          
           *param = attr->schedparam;
           return 0;
          }

posix/src/pthreadattrgetschedpolicy.c

       1  /*
           * 13.5.1 Thread Creation Scheduling Parameters,   P1003.1c/Draft 10,   p. 120
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrgetschedpolicy.c,  v 1.5 2004/04/15 13:24:47 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_getschedpolicy(  
           const pthread_attr_t *attr,  
           int *policy
           )
          {
           if (   !attr || !attr->is_initialized || !policy  )
           return EINVAL;
          
           *policy = attr->schedpolicy;
           return 0;
          }

posix/src/pthreadattrgetscope.c

       1  /*
           * 13.5.1 Thread Creation Scheduling Attributes,   P1003.1c/Draft 10,   p. 120
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrgetscope.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_getscope(  
           const pthread_attr_t *attr,  
           int *contentionscope
           )
          {
           if (   !attr || !attr->is_initialized || !contentionscope  )
           return EINVAL;
          
           *contentionscope = attr->contentionscope;
           return 0;
          }

posix/src/pthreadattrgetstack.c

       1  /*
           * 16.1.1 Thread Creation Attributes
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrgetstack.c,  v 1.1 2010/10/04 15:32:36 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_DECL_PTHREAD_ATTR_GETSTACK
          #include <pthread.h>
          #include <errno.h>
          
      22  int pthread_attr_getstack(  
           const pthread_attr_t *attr,  
           void **stackaddr,  
           size_t *stacksize
           )
          {
           if (   !attr || !attr->is_initialized || !stackaddr || !stacksize  )
           return EINVAL;
          
           *stackaddr = attr->stackaddr;
           *stacksize = attr->stacksize;
           return 0;
          }
          #endif

posix/src/pthreadattrgetstackaddr.c

       1  /*
           * 16.1.1 Thread Creation Attributes,   P1003.1c/Draft 10,   p,   140
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrgetstackaddr.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_getstackaddr(  
           const pthread_attr_t *attr,  
           void **stackaddr
           )
          {
           if (   !attr || !attr->is_initialized || !stackaddr  )
           return EINVAL;
          
           *stackaddr = attr->stackaddr;
           return 0;
          }

posix/src/pthreadattrgetstacksize.c

       1  /*
           * 16.1.1 Thread Creation Attributes,   P1003.1c/Draft 10,   p,   140
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrgetstacksize.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_getstacksize(  
           const pthread_attr_t *attr,  
           size_t *stacksize
           )
          {
           if (   !attr || !attr->is_initialized || !stacksize  )
           return EINVAL;
          
           *stacksize = attr->stacksize;
           return 0;
          }

posix/src/pthreadattrinit.c

       1  /*
           * 16.1.1 Thread Creation Attributes,   P1003.1c/Draft 10,   p,   140
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrinit.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          
      24  int pthread_attr_init(  
           pthread_attr_t *attr
           )
          {
           if (   !attr  )
           return EINVAL;
          
           *attr = _POSIX_Threads_Default_attributes;
           return 0;
          }

posix/src/pthreadattrsetdetachstate.c

       1  /*
           * 16.1.1 Thread Creation Attributes,   P1003.1c/Draft 10,   p,   140
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrsetdetachstate.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_setdetachstate(  
           pthread_attr_t *attr,  
           int detachstate
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           switch (   detachstate  ) {
           case PTHREAD_CREATE_DETACHED:
           case PTHREAD_CREATE_JOINABLE:
           attr->detachstate = detachstate;
           return 0;
          
           default:
           return EINVAL;
           }
          }

posix/src/pthreadattrsetguardsize.c

       1  /*
           * 16.1.1 Thread Creation Attributes
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrsetguardsize.c,  v 1.1 2010/10/04 15:32:36 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_DECL_PTHREAD_ATTR_SETGUARDSIZE
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          
      25  int pthread_attr_setguardsize(  
           pthread_attr_t *attr,  
           size_t guardsize
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           attr->guardsize = guardsize;
           return 0;
          }
          #endif

posix/src/pthreadattrsetinheritsched.c

       1  /*
           * 13.5.1 Thread Creation Scheduling Attributes,   P1003.1c/Draft 10,   p. 120
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrsetinheritsched.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          
      24  int pthread_attr_setinheritsched(  
           pthread_attr_t *attr,  
           int inheritsched
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           switch (   inheritsched  ) {
           case PTHREAD_INHERIT_SCHED:
           case PTHREAD_EXPLICIT_SCHED:
           attr->inheritsched = inheritsched;
           return 0;
          
           default:
           return ENOTSUP;
           }
          }

posix/src/pthreadattrsetschedparam.c

       1  /*
           * 13.5.1 Thread Creation Scheduling Parameters,   P1003.1c/Draft 10,   p. 120
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrsetschedparam.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_setschedparam(  
           pthread_attr_t *attr,  
           const struct sched_param *param
           )
          {
           if (   !attr || !attr->is_initialized || !param  )
           return EINVAL;
          
           attr->schedparam = *param;
           return 0;
          }

posix/src/pthreadattrsetschedpolicy.c

       1  /*
           * 13.5.1 Thread Creation Scheduling Attributes,   P1003.1c/Draft 10,   p. 120
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrsetschedpolicy.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          
      24  int pthread_attr_setschedpolicy(  
           pthread_attr_t *attr,  
           int policy
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           switch (   policy  ) {
           case SCHED_OTHER:
           case SCHED_FIFO:
           case SCHED_RR:
           case SCHED_SPORADIC:
           attr->schedpolicy = policy;
           return 0;
          
           default:
           return ENOTSUP;
           }
          }

posix/src/pthreadattrsetscope.c

       1  /*
           * 13.5.1 Thread Creation Scheduling Attributes,   P1003.1c/Draft 10,   p. 120
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrsetscope.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          
      24  int pthread_attr_setscope(  
           pthread_attr_t *attr,  
           int contentionscope
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           switch (   contentionscope  ) {
           case PTHREAD_SCOPE_PROCESS:
           attr->contentionscope = contentionscope;
           return 0;
          
           case PTHREAD_SCOPE_SYSTEM:
           return ENOTSUP;
          
           default:
           return EINVAL;
           }
          }

posix/src/pthreadattrsetstack.c

       1  /*
           * 16.1.1 Thread Creation Attributes
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrsetstack.c,  v 1.1 2010/10/04 15:32:36 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #if HAVE_DECL_PTHREAD_ATTR_SETSTACK
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          
      25  int pthread_attr_setstack(  
           pthread_attr_t *attr,  
           void *stackaddr,  
           size_t stacksize
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           if (  stacksize < PTHREAD_MINIMUM_STACK_SIZE )
           attr->stacksize = PTHREAD_MINIMUM_STACK_SIZE;
           else
           attr->stacksize = stacksize;
          
           attr->stackaddr = stackaddr;
           return 0;
          }
          #endif

posix/src/pthreadattrsetstackaddr.c

       1  /*
           * 16.1.1 Thread Creation Attributes,   P1003.1c/Draft 10,   p,   140
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrsetstackaddr.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_setstackaddr(  
           pthread_attr_t *attr,  
           void *stackaddr
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           attr->stackaddr = stackaddr;
           return 0;
          }

posix/src/pthreadattrsetstacksize.c

       1  /*
           * 16.1.1 Thread Creation Attributes,   P1003.1c/Draft 10,   p,   140
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadattrsetstacksize.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          
      24  int pthread_attr_setstacksize(  
           pthread_attr_t *attr,  
           size_t stacksize
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           if (  stacksize < PTHREAD_MINIMUM_STACK_SIZE )
           attr->stacksize = PTHREAD_MINIMUM_STACK_SIZE;
           else
           attr->stacksize = stacksize;
           return 0;
          }

posix/src/pthreadcreate.c

       1  /*
           * 16.1.2 Thread Creation,   P1003.1c/Draft 10,   p. 144
           */
          
          /* COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadcreate.c,  v 1.21 2010/06/29 00:34:11 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          #include <rtems/score/apimutex.h>
          
      29  static inline size_t _POSIX_Threads_Ensure_minimum_stack (  
           size_t size
           )
          {
           if (   size >= PTHREAD_MINIMUM_STACK_SIZE  )
           return size;
           return PTHREAD_MINIMUM_STACK_SIZE;
          }
          
          
      39  int pthread_create(  
           pthread_t *thread,  
           const pthread_attr_t *attr,  
           void *(  *start_routine )(   void *  ),  
           void *arg
           )
          {
           const pthread_attr_t *the_attr;
           Priority_Control core_priority;
           Thread_CPU_budget_algorithms budget_algorithm;
           Thread_CPU_budget_algorithm_callout budget_callout;
           bool is_fp;
           bool status;
           Thread_Control *the_thread;
           POSIX_API_Control *api;
           int schedpolicy = SCHED_RR;
           struct sched_param schedparam;
           Objects_Name name;
           int rc;
          
           if (   !start_routine  )
           return EFAULT;
          
           the_attr = (  attr ) ? attr : &_POSIX_Threads_Default_attributes;
          
           if (   !the_attr->is_initialized  )
           return EINVAL;
          
           /*
           * Core Thread Initialize ensures we get the minimum amount of
           * stack space if it is allowed to allocate it itself.
           *
           * NOTE: If the user provides the stack we will let it drop below
           * twice the minimum.
           */
           if (   the_attr->stackaddr && !_Stack_Is_enough(  the_attr->stacksize )  )
           return EINVAL;
          
           #if 0
           int cputime_clock_allowed; /* see time.h */
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
           #endif
          
           /*
           * P1003.1c/Draft 10,   p. 121.
           *
           * If inheritsched is set to PTHREAD_INHERIT_SCHED,   then this thread
           * inherits scheduling attributes from the creating thread. If it is
           * PTHREAD_EXPLICIT_SCHED,   then scheduling parameters come from the
           * attributes structure.
           */
           switch (   the_attr->inheritsched  ) {
           case PTHREAD_INHERIT_SCHED:
           api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
           schedpolicy = api->schedpolicy;
           schedparam = api->schedparam;
           break;
          
           case PTHREAD_EXPLICIT_SCHED:
           schedpolicy = the_attr->schedpolicy;
           schedparam = the_attr->schedparam;
           break;
          
           default:
           return EINVAL;
           }
          
           /*
           * Check the contentionscope since rtems only supports PROCESS wide
           * contention (  i.e. no system wide contention ).
           */
           if (   the_attr->contentionscope != PTHREAD_SCOPE_PROCESS  )
           return ENOTSUP;
          
           /*
           * Interpret the scheduling parameters.
           */
           if (   !_POSIX_Priority_Is_valid(   schedparam.sched_priority  )  )
           return EINVAL;
          
           core_priority = _POSIX_Priority_To_core(   schedparam.sched_priority  );
          
           /*
           * Set the core scheduling policy information.
           */
           rc = _POSIX_Thread_Translate_sched_param(  
           schedpolicy,  
           &schedparam,  
           &budget_algorithm,  
           &budget_callout
            );
           if (   rc  )
           return rc;
          
           /*
           * Currently all POSIX threads are floating point if the hardware
           * supports it.
           */
           #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
           is_fp = true;
           #else
           is_fp = false;
           #endif
          
           /*
           * Lock the allocator mutex for protection
           */
           _RTEMS_Lock_allocator(   );
          
           /*
           * Allocate the thread control block.
           *
           * NOTE: Global threads are not currently supported.
           */
           the_thread = _POSIX_Threads_Allocate(   );
           if (   !the_thread  ) {
           _RTEMS_Unlock_allocator(   );
           return EAGAIN;
           }
          
           /*
           * Initialize the core thread for this task.
           */
           name.name_p = NULL; /* posix threads don't have a name by default */
           status = _Thread_Initialize(  
           &_POSIX_Threads_Information,  
           the_thread,  
           the_attr->stackaddr,  
           _POSIX_Threads_Ensure_minimum_stack(  the_attr->stacksize ),  
           is_fp,  
           core_priority,  
           true,   /* preemptible */
           budget_algorithm,  
           budget_callout,  
           0,   /* isr level */
           name /* posix threads don't have a name */
            );
          
           if (   !status  ) {
           _POSIX_Threads_Free(   the_thread  );
           _RTEMS_Unlock_allocator(   );
           return EAGAIN;
           }
          
           /*
           * finish initializing the per API structure
           */
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           api->Attributes = *the_attr;
           api->detachstate = the_attr->detachstate;
           api->schedpolicy = schedpolicy;
           api->schedparam = schedparam;
          
           /*
           * POSIX threads are allocated and started in one operation.
           */
           status = _Thread_Start(  
           the_thread,  
           THREAD_START_POINTER,  
           start_routine,  
           arg,  
           0 /* unused */
            );
          
           #if defined(  RTEMS_DEBUG )
           /*
           * _Thread_Start only fails if the thread was in the incorrect state
           *
           * NOTE: This can only happen if someone slips in and touches the
           * thread while we are creating it.
           */
           if (   !status  ) {
           _POSIX_Threads_Free(   the_thread  );
           _RTEMS_Unlock_allocator(   );
           return EINVAL;
           }
           #endif
          
           if (   schedpolicy == SCHED_SPORADIC  ) {
           _Watchdog_Insert_ticks(  
           &api->Sporadic_timer,  
           _Timespec_To_ticks(   &api->schedparam.sched_ss_repl_period  )
            );
           }
          
           /*
           * Return the id and indicate we successfully created the thread
           */
           *thread = the_thread->Object.id;
          
           _RTEMS_Unlock_allocator(   );
           return 0;
          }

posix/src/pthreaddetach.c

       1  /*
           * 16.1.4 Detaching a Thread,   P1003.1c/Draft 10,   p. 149
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreaddetach.c,  v 1.7 2007/11/30 20:34:13 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          #include <rtems/posix/pthread.h>
          
      25  int pthread_detach(  
           pthread_t thread
           )
          {
           register Thread_Control *the_thread;
           POSIX_API_Control *api;
           Objects_Locations location;
          
           the_thread = _POSIX_Threads_Get(   thread,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
           api->detachstate = PTHREAD_CREATE_DETACHED;
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return ESRCH;
          }

posix/src/pthreadequal.c

       1  /*
           * 16.1.7 Compare Thread IDs,   p1003.1c/Draft 10,   p. 153
           *
           * NOTE: POSIX does not define the behavior when either thread id is invalid.
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadequal.c,  v 1.10 2008/04/28 18:12:42 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/score/thread.h>
          
      27  int pthread_equal(  
           pthread_t t1,  
           pthread_t t2
           )
          {
           /*
           * If the system is configured for debug,   then we will do everything we
           * can to insure that both ids are valid. Otherwise,   we will do the
           * cheapest possible thing to determine if they are equal.
           */
          
          #ifndef RTEMS_DEBUG
           return _Objects_Are_ids_equal(   t1,   t2  );
          #else
           int status;
           Objects_Locations location;
          
           /*
           * By default this is not a match.
           */
          
           status = 0;
          
           /*
           * Validate the first id and return 0 if it is not valid
           */
          
           (  void ) _POSIX_Threads_Get(   t1,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           /*
           * Validate the second id and return 0 if it is not valid
           */
          
           (  void ) _POSIX_Threads_Get(   t2,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           status = _Objects_Are_ids_equal(   t1,   t2  );
           _Thread_Unnest_dispatch(   );
           _Thread_Enable_dispatch(   );
           break;
          
           case OBJECTS_ERROR:
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           /* t1 must have been valid so exit the critical section */
           _Thread_Enable_dispatch(   );
           /* return status == 0 */
           break;
           }
           break;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           /* return status == 0 */
           break;
           }
          
           return status;
          #endif
          }

posix/src/pthreadexit.c

       1  /*
           * 16.1.5.1 Thread Termination,   p1003.1c/Draft 10,   p. 150
           *
           * NOTE: Key destructors are executed in the POSIX api delete extension.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadexit.c,  v 1.12 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/apimutex.h>
          #include <rtems/score/thread.h>
          #include <rtems/posix/pthread.h>
          
      28  void _POSIX_Thread_Exit(  
           Thread_Control *the_thread,  
           void *value_ptr
           )
          {
           Objects_Information *the_information;
          
           the_information = _Objects_Get_information_id(   the_thread->Object.id  );
          
           /*
           * The_information has to be non-NULL. Otherwise,   we couldn't be
           * running in a thread of this API and class.
           *
           * NOTE: Lock and unlock in different order so we do not throw a
           * fatal error when locking the allocator mutex. And after
           * we unlock,   we want to defer the context switch until we
           * are ready to be switched out. Otherwise,   an ISR could
           * occur and preempt us out while we still hold the
           * allocator mutex.
           */
          
           _RTEMS_Lock_allocator(   );
           _Thread_Disable_dispatch(   );
          
           the_thread->Wait.return_argument = value_ptr;
          
           _Thread_Close(   the_information,   the_thread  );
          
           _POSIX_Threads_Free(   the_thread  );
          
           _RTEMS_Unlock_allocator(   );
           _Thread_Enable_dispatch(   );
          }
          
      62  void pthread_exit(  
           void *value_ptr
           )
          {
           _POSIX_Thread_Exit(   _Thread_Executing,   value_ptr  );
          }

posix/src/pthreadgetcpuclockid.c

       1  /*
           * 20.1.6 Accessing a Thread CPU-time Clock,   P1003.4b/Draft 8,   p. 58
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadgetcpuclockid.c,  v 1.8 2007/12/13 16:52:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          
      24  int pthread_getcpuclockid(  
           pthread_t pid,  
           clockid_t *clock_id
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/pthreadgetcputime.c

       1  /*
           * 20.1.7 CPU-time Clock Thread Creation Attribute,   P1003.4b/Draft 8,   p. 59
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadgetcputime.c,  v 1.5 2004/04/15 13:24:47 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_getcputime(  
           pthread_attr_t *attr,  
           int *clock_allowed
           )
          {
           if (   !attr || !attr->is_initialized || !clock_allowed  )
           return EINVAL;
          
           *clock_allowed = attr->cputime_clock_allowed;
           return 0;
          }

posix/src/pthreadgetschedparam.c

       1  /*
           * 13.5.2 Dynamic Thread Scheduling Parameters Access,  
           * P1003.1c/Draft 10,   p. 124
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadgetschedparam.c,  v 1.8 2007/11/30 20:34:13 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/priority.h>
          
      26  int pthread_getschedparam(  
           pthread_t thread,  
           int *policy,  
           struct sched_param *param
           )
          {
           Objects_Locations location;
           POSIX_API_Control *api;
           register Thread_Control *the_thread;
          
           if (   !policy || !param  )
           return EINVAL;
          
           the_thread = _POSIX_Threads_Get(   thread,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
           if (   policy  )
           *policy = api->schedpolicy;
           if (   param  ) {
           *param = api->schedparam;
           param->sched_priority =
           _POSIX_Priority_From_core(   the_thread->current_priority  );
           }
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return ESRCH;
          
          }

posix/src/pthreadinitthreads.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadinitthreads.c,  v 1.6 2009/06/29 23:19:28 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          #include <pthread.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/cancel.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/posix/config.h>
          #include <rtems/posix/key.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * _POSIX_Threads_Initialize_user_threads_body
           *
           * This routine creates and starts all configured user
           * initialzation threads.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      47  void _POSIX_Threads_Initialize_user_threads_body(  void )
          {
           int status;
           uint32_t index;
           uint32_t maximum;
           posix_initialization_threads_table *user_threads;
           pthread_t thread_id;
           pthread_attr_t attr;
          
           user_threads = Configuration_POSIX_API.User_initialization_threads_table;
           maximum = Configuration_POSIX_API.number_of_initialization_threads;
          
           if (   !user_threads || maximum == 0  )
           return;
          
           /*
           * Be careful .. if the default attribute set changes,   this may need to.
           *
           * Setting the attributes explicitly is critical,   since we don't want
           * to inherit the idle tasks attributes.
           */
          
           for (   index=0 ; index < maximum ; index++  ) {
           /*
           * There is no way for these calls to fail in this situation.
           */
           (  void ) pthread_attr_init(   &attr  );
           (  void ) pthread_attr_setinheritsched(   &attr,   PTHREAD_EXPLICIT_SCHED  );
           (  void ) pthread_attr_setstacksize(  &attr,   user_threads[ index ].stack_size );
          
           status = pthread_create(  
           &thread_id,  
           &attr,  
           user_threads[ index ].thread_entry,  
           NULL
            );
           if (   status  )
           _Internal_error_Occurred(   INTERNAL_ERROR_POSIX_API,   true,   status  );
           }
          }
          

posix/src/pthreadjoin.c

       1  /*
           * 16.1.3 Wait for Thread Termination,   P1003.1c/Draft 10,   p. 147
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadjoin.c,  v 1.8 2007/11/30 20:34:13 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          #include <rtems/posix/pthread.h>
          
      25  int pthread_join(  
           pthread_t thread,  
           void **value_ptr
           )
          {
           register Thread_Control *the_thread;
           POSIX_API_Control *api;
           Objects_Locations location;
           void *return_pointer;
          
           the_thread = _POSIX_Threads_Get(   thread,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           if (   api->detachstate == PTHREAD_CREATE_DETACHED  ) {
           _Thread_Enable_dispatch(   );
           return EINVAL;
           }
          
           if (   _Thread_Is_executing(   the_thread  )  ) {
           _Thread_Enable_dispatch(   );
           return EDEADLK;
           }
          
           /*
           * Put ourself on the threads join list
           */
          
           _Thread_Executing->Wait.return_argument = &return_pointer;
          
           _Thread_queue_Enter_critical_section(   &api->Join_List  );
          
           _Thread_queue_Enqueue(   &api->Join_List,   WATCHDOG_NO_TIMEOUT  );
          
           _Thread_Enable_dispatch(   );
          
           if (   value_ptr  )
           *value_ptr = return_pointer;
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return ESRCH;
          }

posix/src/pthreadkill.c

       1  /*
           * 3.3.10 Send a Signal to a Thread,   P1003.1c/D10,   p. 43
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadkill.c,  v 1.17 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <signal.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/score/isr.h>
          #include <rtems/seterr.h>
          
      28  int pthread_kill(  
           pthread_t thread,  
           int sig
           )
          {
           POSIX_API_Control *api;
           Thread_Control *the_thread;
           Objects_Locations location;
          
           if (   !sig  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   !is_valid_signo(  sig )  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           the_thread = _POSIX_Threads_Get(   thread,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           /*
           * If sig == 0 then just validate arguments
           */
          
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           if (   sig  ) {
          
           if (   _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN  ) {
           _Thread_Enable_dispatch(   );
           return 0;
           }
          
           /* XXX critical section */
          
           api->signals_pending |= signo_to_mask(   sig  );
          
           (  void ) _POSIX_signals_Unblock_thread(   the_thread,   sig,   NULL  );
          
           if (   _ISR_Is_in_progress(   ) && _Thread_Is_executing(   the_thread  )  )
           _Thread_Dispatch_necessary = true;
           }
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   ESRCH  );
          }

posix/src/pthreadonce.c

       1  /*
           * 16.1.8 Dynamic Package Initialization,   P1003.1c/Draft 10,   p. 154
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadonce.c,  v 1.7 2009/02/03 10:10:55 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems.h>
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          
      25  int pthread_once(  
           pthread_once_t *once_control,  
           void (  *init_routine )(  void )
           )
          {
           if (   !once_control || !init_routine  )
           return EINVAL;
          
           if (   !once_control->init_executed  ) {
           rtems_mode saveMode;
           rtems_task_mode(  RTEMS_NO_PREEMPT,   RTEMS_PREEMPT_MASK,   &saveMode );
           if (   !once_control->init_executed  ) {
           once_control->is_initialized = true;
           once_control->init_executed = true;
           (  *init_routine )(   );
           }
           rtems_task_mode(  saveMode,   RTEMS_PREEMPT_MASK,   &saveMode );
           }
           return 0;
          }

posix/src/pthreadself.c

       1  /*
           * 16.1.6 Get Calling Thread's ID,   p1003.1c/Draft 10,   p. 152
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadself.c,  v 1.4 2003/09/04 18:54:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          
      24  pthread_t pthread_self(   void  )
          {
           return _Thread_Executing->Object.id;
          }

posix/src/pthreadsetcputime.c

       1  /*
           * 20.1.7 CPU-time Clock Thread Creation Attribute,   P1003.4b/Draft 8,   p. 59
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadsetcputime.c,  v 1.5 2004/04/15 13:24:47 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
      21  int pthread_attr_setcputime(  
           pthread_attr_t *attr,  
           int clock_allowed
           )
          {
           if (   !attr || !attr->is_initialized  )
           return EINVAL;
          
           switch (   clock_allowed  ) {
           case CLOCK_ENABLED:
           case CLOCK_DISABLED:
           attr->cputime_clock_allowed = clock_allowed;
           return 0;
          
           default:
           return EINVAL;
           }
          }

posix/src/pthreadsetschedparam.c

       1  /*
           * 13.5.2 Dynamic Thread Scheduling Parameters Access,  
           * P1003.1c/Draft 10,   p. 124
           */
          
          /* COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadsetschedparam.c,  v 1.11 2009/06/24 06:38:52 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
      28  int pthread_setschedparam(  
           pthread_t thread,  
           int policy,  
           struct sched_param *param
           )
          {
           register Thread_Control *the_thread;
           POSIX_API_Control *api;
           Thread_CPU_budget_algorithms budget_algorithm;
           Thread_CPU_budget_algorithm_callout budget_callout;
           Objects_Locations location;
           int rc;
          
           /*
           * Check all the parameters
           */
           if (   !param  )
           return EINVAL;
          
           rc = _POSIX_Thread_Translate_sched_param(  
           policy,  
           param,  
           &budget_algorithm,  
           &budget_callout
            );
           if (   rc  )
           return rc;
          
           /*
           * Actually change the scheduling policy and parameters
           */
           the_thread = _POSIX_Threads_Get(   thread,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           if (   api->schedpolicy == SCHED_SPORADIC  )
           (  void ) _Watchdog_Remove(   &api->Sporadic_timer  );
          
           api->schedpolicy = policy;
           api->schedparam = *param;
           the_thread->budget_algorithm = budget_algorithm;
           the_thread->budget_callout = budget_callout;
          
           switch (   api->schedpolicy  ) {
           case SCHED_OTHER:
           case SCHED_FIFO:
           case SCHED_RR:
           the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
          
           the_thread->real_priority =
           _POSIX_Priority_To_core(   api->schedparam.sched_priority  );
          
           _Thread_Change_priority(  
           the_thread,  
           the_thread->real_priority,  
           true
            );
           break;
          
           case SCHED_SPORADIC:
           api->ss_high_priority = api->schedparam.sched_priority;
           _Watchdog_Remove(   &api->Sporadic_timer  );
           _POSIX_Threads_Sporadic_budget_TSR(   0,   the_thread  );
           break;
           }
          
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return ESRCH;
          }

posix/src/pthreadsigmask.c

       1  /*
           * 3.3.5 Examine and Change Blocked Signals,   P1003.1b-1993,   p. 73
           *
           * NOTE: P1003.1c/D10,   p. 37 adds pthread_sigmask(   ).
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pthreadsigmask.c,  v 1.9 2010/06/29 00:34:11 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <signal.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/seterr.h>
          
      29  int pthread_sigmask(  
           int how,  
           const sigset_t *set,  
           sigset_t *oset
           )
          {
           POSIX_API_Control *api;
          
           if (   !set && !oset  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
          
           if (   oset  )
           *oset = api->signals_blocked;
          
           if (   !set  )
           return 0;
          
           switch (   how  ) {
           case SIG_BLOCK:
           api->signals_blocked |= *set;
           break;
           case SIG_UNBLOCK:
           api->signals_blocked &= ~*set;
           break;
           case SIG_SETMASK:
           api->signals_blocked = *set;
           break;
           default:
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           /* XXX are there critical section problems here? */
          
           /* XXX evaluate the new set */
          
           if (   ~api->signals_blocked &
           (  api->signals_pending | _POSIX_signals_Pending )  ) {
           _Thread_Dispatch(   );
           }
          
           return 0;
          }

posix/src/ptimer.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * ptimer.c,  v 1.1 1996/06/03 16:29:58 joel Exp
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          #include <limits.h> /* _POSIX_PATH_MAX */
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          
          #include <rtems/posix/time.h>
          
          /************************************/
          /* These includes are now necessary */
          /************************************/
          
          #include <unistd.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/types.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/score/wkspace.h>
          #include <pthread.h>
          #include <stdio.h>
          #include <signal.h>
          
          #include <rtems/posix/timer.h>
          
          /*
           * _POSIX_Timer_Manager_initialization
           *
           * Description:
           *
           * Initialize the internal structure in which the data of all
           * the timers are stored
           */
          
      54  void _POSIX_Timer_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_POSIX_Timer_Information,   /* object information table */
           OBJECTS_POSIX_API,   /* object API */
           OBJECTS_POSIX_TIMERS,   /* object class */
           Configuration_POSIX_API.maximum_timers,  
           /* maximum objects of this class */
           sizeof(   POSIX_Timer_Control  ),  
           /* size of this object's control block */
           true,   /* true if names for this object are strings */
           _POSIX_PATH_MAX /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

posix/src/rwlockattrdestroy.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rwlockattrdestroy.c,  v 1.3 2009/02/03 10:10:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/mutex.h>
          
          /*PAGE
           *
           * RWLock Initialization Attributes
           */
          
      32  int pthread_rwlockattr_destroy(  
           pthread_rwlockattr_t *attr
           )
          {
           if (   !attr || attr->is_initialized == false  )
           return EINVAL;
          
           attr->is_initialized = false;
           return 0;
          }

posix/src/rwlockattrgetpshared.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rwlockattrgetpshared.c,  v 1.2 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          /*PAGE
           *
           * RWLock Attributes Get Process Shared
           */
          
      24  int pthread_rwlockattr_getpshared(  
           const pthread_rwlockattr_t *attr,  
           int *pshared
           )
          {
           if (   !attr  )
           return EINVAL;
          
           if (   !attr->is_initialized  )
           return EINVAL;
          
           *pshared = attr->process_shared;
           return 0;
          }

posix/src/rwlockattrinit.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rwlockattrinit.c,  v 1.3 2009/02/03 10:10:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          
          /*PAGE
           *
           * RWLock Attributes Initialization
           */
          
      26  int pthread_rwlockattr_init(  
           pthread_rwlockattr_t *attr
           )
          {
           if (   !attr  )
           return EINVAL;
          
           attr->is_initialized = true;
           attr->process_shared = PTHREAD_PROCESS_PRIVATE;
           return 0;
          }

posix/src/rwlockattrsetpshared.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rwlockattrsetpshared.c,  v 1.2 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          /*PAGE
           *
           * RWLock Attributes Set Process Shared
           */
          
      24  int pthread_rwlockattr_setpshared(  
           pthread_rwlockattr_t *attr,  
           int pshared
           )
          {
           if (   !attr  )
           return EINVAL;
          
           if (   !attr->is_initialized  )
           return EINVAL;
          
           switch (   pshared  ) {
           case PTHREAD_PROCESS_SHARED:
           case PTHREAD_PROCESS_PRIVATE:
           attr->process_shared = pshared;
           return 0;
          
           default:
           return EINVAL;
           }
          }

posix/src/sched_getparam.c

       1  /*
           * 13.3.2 Set Scheduling Parameters,   P1003.1b-1993,   p. 253
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sched_getparam.c,  v 1.3 2009/02/06 21:02:31 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sched.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          
      24  int sched_getparam(  
           pid_t pid __attribute__(  (  unused ) ),  
           struct sched_param *param __attribute__(  (  unused ) )
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/sched_getprioritymax.c

       1  /*
           * 13.3.6 Get Scheduling Parameter Limits,   P1003.1b-1993,   p. 258
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sched_getprioritymax.c,  v 1.1 2007/12/13 16:52:21 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sched.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/priority.h>
          
      25  int sched_get_priority_max(  
           int policy
           )
          {
           switch (   policy  ) {
           case SCHED_OTHER:
           case SCHED_FIFO:
           case SCHED_RR:
           case SCHED_SPORADIC:
           break;
          
           default:
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           return POSIX_SCHEDULER_MAXIMUM_PRIORITY;
          }

posix/src/sched_getprioritymin.c

       1  /*
           * 13.3.6 Get Scheduling Parameter Limits,   P1003.1b-1993,   p. 258
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sched_getprioritymin.c,  v 1.1 2007/12/13 16:52:21 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sched.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/priority.h>
          
      25  int sched_get_priority_min(  
           int policy
           )
          {
           switch (   policy  ) {
           case SCHED_OTHER:
           case SCHED_FIFO:
           case SCHED_RR:
           case SCHED_SPORADIC:
           break;
          
           default:
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           return POSIX_SCHEDULER_MINIMUM_PRIORITY;
          }

posix/src/sched_getscheduler.c

       1  /*
           * 13.3.4 Get Scheduling Policy,   P1003.1b-1993,   p. 256
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sched_getscheduler.c,  v 1.2 2009/01/02 10:04:24 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sched.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/thread.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
      28  int sched_getscheduler(  
           pid_t pid __attribute__(  (  unused ) )
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/sched_rr_get_interval.c

       1  /*
           * 13.3.6 Get Scheduling Parameter Limits,   P1003.1b-1993,   p. 258
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sched_rr_get_interval.c,  v 1.3 2010/04/02 06:38:02 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <unistd.h> /* getpid */
          #include <sched.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/timespec.h>
          #include <rtems/seterr.h>
          
      28  int sched_rr_get_interval(  
           pid_t pid,  
           struct timespec *interval
           )
          {
           /*
           * Only supported for the "calling process" (  i.e. this node ).
           */
          
           if (   pid && pid != getpid(   )  )
           rtems_set_errno_and_return_minus_one(   ESRCH  );
          
           if (   !interval  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           _Timespec_From_ticks(   _Thread_Ticks_per_timeslice,   interval  );
           return 0;
          }

posix/src/sched_setparam.c

       1  /*
           * 13.3.1 Set Scheduling Parameters,   P1003.1b-1993,   p. 252
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sched_setparam.c,  v 1.2 2009/01/02 10:04:24 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sched.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/thread.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
      28  int sched_setparam(  
           pid_t pid __attribute__(  (  unused ) ),  
           const struct sched_param *param __attribute__(  (  unused ) )
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/sched_setscheduler.c

       1  /*
           * 13.3.3 Set Scheduling Policy and Scheduling Parameters,  
           * P1003.1b-1993,   p. 254
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sched_setscheduler.c,  v 1.2 2009/01/02 10:04:24 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sched.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/thread.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
      29  int sched_setscheduler(  
           pid_t pid __attribute__(  (  unused ) ),  
           int policy __attribute__(  (  unused ) ),  
           const struct sched_param *param __attribute__(  (  unused ) )
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/sched_yield.c

       1  /*
           * 13.3.5 Yield Processor,   P1003.1b-1993,   p. 257
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sched_yield.c,  v 1.1 2007/12/13 16:52:21 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sched.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/thread.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/time.h>
          
      28  int sched_yield(   void  )
          {
           _Thread_Disable_dispatch(   );
           _Thread_Yield_processor(   );
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/semaphore.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semaphore.c,  v 1.19 2009/02/03 10:10:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * _POSIX_Semaphore_Manager_initialization
           *
           * This routine initializes all semaphore manager related data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      42  void _POSIX_Semaphore_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_POSIX_Semaphore_Information,   /* object information table */
           OBJECTS_POSIX_API,   /* object API */
           OBJECTS_POSIX_SEMAPHORES,   /* object class */
           Configuration_POSIX_API.maximum_semaphores,  
           /* maximum objects of this class */
           sizeof(   POSIX_Semaphore_Control  ),  
           /* size of this object's control block */
           true,   /* true if names for this object are strings */
           _POSIX_PATH_MAX /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

posix/src/semaphorecreatesupp.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semaphorecreatesupp.c,  v 1.16 2009/08/06 19:26:56 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          #include <string.h> /* strlen */
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /* pure ANSI mode does not have this prototype */
      32  size_t strnlen(  const char *,   size_t );
          
          /*
           * _POSIX_Semaphore_Create_support
           *
           * This routine does the actual creation and initialization of
           * a poxix semaphore. It is a support routine for sem_init and
           * sem_open.
           */
      41  int _POSIX_Semaphore_Create_support(  
           const char *name,  
           int pshared,  
           unsigned int value,  
           POSIX_Semaphore_Control **the_sem
           )
          {
           POSIX_Semaphore_Control *the_semaphore;
           CORE_semaphore_Attributes *the_sem_attr;
           char *name_p = (  char * )name;
          
           /* Sharing semaphores among processes is not currently supported */
           if (  pshared != 0 )
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          
           if (   name  ) {
           if (   strnlen(   name,   NAME_MAX  ) >= NAME_MAX  )
           rtems_set_errno_and_return_minus_one(   ENAMETOOLONG  );
           }
          
           _Thread_Disable_dispatch(   );
          
           the_semaphore = _POSIX_Semaphore_Allocate(   );
          
           if (   !the_semaphore  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   ENOSPC  );
           }
          
           the_semaphore->process_shared = pshared;
          
           if (   name  ) {
           the_semaphore->named = true;
           the_semaphore->open_count = 1;
           the_semaphore->linked = true;
           } else {
           the_semaphore->named = false;
           the_semaphore->open_count = 0;
           the_semaphore->linked = false;
           }
          
           the_sem_attr = &the_semaphore->Semaphore.Attributes;
          
           /*
           * POSIX does not appear to specify what the discipline for
           * blocking tasks on this semaphore should be. It could somehow
           * be derived from the current scheduling policy. One
           * thing is certain,   no matter what we decide,   it won't be
           * the same as all other POSIX implementations. : )
           */
           the_sem_attr->discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
          
           /*
           * This effectively disables limit checking.
           */
           the_sem_attr->maximum_count = 0xFFFFFFFF;
          
           _CORE_semaphore_Initialize(   &the_semaphore->Semaphore,   the_sem_attr,   value  );
          
           /*
           * Make the semaphore available for use.
           */
           _Objects_Open_string(  
           &_POSIX_Semaphore_Information,  
           &the_semaphore->Object,  
           name_p
            );
          
           *the_sem = the_semaphore;
          
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/semaphoredeletesupp.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semaphoredeletesupp.c,  v 1.7 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * _POSIX_Semaphore_Delete
           */
          
      35  void _POSIX_Semaphore_Delete(  
           POSIX_Semaphore_Control *the_semaphore
           )
          {
           if (   !the_semaphore->linked && !the_semaphore->open_count  ) {
           _Objects_Close(   &_POSIX_Semaphore_Information,   &the_semaphore->Object  );
          
           _CORE_semaphore_Flush(  
           &the_semaphore->Semaphore,  
           NULL,  
           -1
            );
          
           _POSIX_Semaphore_Free(   the_semaphore  );
           }
          }

posix/src/semaphorenametoid.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semaphorenametoid.c,  v 1.13 2009/01/05 20:26:01 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * _POSIX_Semaphore_Name_to_id
           *
           * Look up the specified name and attempt to locate the id
           * for the associated semaphore.
           */
          
      38  int _POSIX_Semaphore_Name_to_id(  
           const char *name,  
           sem_t *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
           Objects_Id the_id;
          
           if (   !name  )
           return EINVAL;
          
           if (   !name[0]  )
           return EINVAL;
          
           status = _Objects_Name_to_id_string(  
           &_POSIX_Semaphore_Information,  
           name,  
           &the_id
            );
           *id = the_id;
          
           if (   status == OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL  )
           return 0;
          
           return ENOENT;
          }

posix/src/semaphoretranslatereturncode.c

       1  /*
           * POSIX Semaphore Error Translation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semaphoretranslatereturncode.c,  v 1.2 2008/07/18 18:45:56 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/coresem.h>
          
          /*
           * _POSIX_Semaphore_Translate_core_semaphore_return_code
           *
           * Input parameters:
           * the_semaphore_status - semaphore status code to translate
           *
           * Output parameters:
           * status code - translated POSIX status code
           *
           */
          
          static int _POSIX_Semaphore_Return_codes[CORE_SEMAPHORE_STATUS_LAST + 1] = {
           0,   /* CORE_SEMAPHORE_STATUS_SUCCESSFUL */
           EAGAIN,   /* CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT */
           EAGAIN,   /* CORE_SEMAPHORE_WAS_DELETED */
           ETIMEDOUT,   /* CORE_SEMAPHORE_TIMEOUT */
           /* The next error can not occur since we set the maximum
           * count to the largest value the count can hold.
           */
           ENOSYS,   /* CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED */
          };
          
          
      47  int _POSIX_Semaphore_Translate_core_semaphore_return_code(  
           CORE_semaphore_Status the_semaphore_status
           )
          {
           /*
           * Internal consistency check for bad status from SuperCore
           */
           #if defined(  RTEMS_DEBUG )
           if (   the_semaphore_status > CORE_SEMAPHORE_STATUS_LAST  )
           return EINVAL;
           #endif
           return _POSIX_Semaphore_Return_codes[the_semaphore_status];
          }

posix/src/semaphorewaitsupp.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semaphorewaitsupp.c,  v 1.13 2008/09/04 15:23:12 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * _POSIX_Semaphore_Wait_support
           */
          
      35  int _POSIX_Semaphore_Wait_support(  
           sem_t *sem,  
           bool blocking,  
           Watchdog_Interval timeout
           )
          {
           POSIX_Semaphore_Control *the_semaphore;
           Objects_Locations location;
          
           the_semaphore = _POSIX_Semaphore_Get(   sem,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _CORE_semaphore_Seize(  
           &the_semaphore->Semaphore,  
           the_semaphore->Object.id,  
           blocking,  
           timeout
            );
           _Thread_Enable_dispatch(   );
          
           if (   !_Thread_Executing->Wait.return_code  )
           return 0;
          
           rtems_set_errno_and_return_minus_one(  
           _POSIX_Semaphore_Translate_core_semaphore_return_code(  
           _Thread_Executing->Wait.return_code
            )
            );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }

posix/src/semclose.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semclose.c,  v 1.10 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          
          /*PAGE
           *
           * sem_close
           *
           * Routine to close a semaphore that has been opened or initialized.
           *
           * 11.2.4 Close a Named Semaphore,   P1003.1b-1993,   p.224
           */
          
      40  int sem_close(  
           sem_t *sem
           )
          {
           register POSIX_Semaphore_Control *the_semaphore;
           Objects_Locations location;
          
           the_semaphore = _POSIX_Semaphore_Get(   sem,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           the_semaphore->open_count -= 1;
           _POSIX_Semaphore_Delete(   the_semaphore  );
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }

posix/src/semdestroy.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semdestroy.c,  v 1.11 2009/02/03 10:10:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 11.2.2 Destroy an Unnamed Semaphore,   P1003.1b-1993,   p.220
           */
          
      35  int sem_destroy(  
           sem_t *sem
           )
          {
           register POSIX_Semaphore_Control *the_semaphore;
           Objects_Locations location;
          
           the_semaphore = _POSIX_Semaphore_Get(   sem,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           /*
           * Undefined operation on a named semaphore.
           */
          
           if (   the_semaphore->named == true  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           _POSIX_Semaphore_Delete(   the_semaphore  );
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }

posix/src/semgetvalue.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semgetvalue.c,  v 1.9 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 11.2.8 Get the Value of a Semaphore,   P1003.1b-1993,   p.229
           */
          
      35  int sem_getvalue(  
           sem_t *sem,  
           int *sval
           )
          {
           register POSIX_Semaphore_Control *the_semaphore;
           Objects_Locations location;
          
           the_semaphore = _POSIX_Semaphore_Get(   sem,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           *sval = _CORE_semaphore_Get_count(   &the_semaphore->Semaphore  );
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }

posix/src/seminit.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: seminit.c,  v 1.8 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 11.2.1 Initialize an Unnamed Semaphore,   P1003.1b-1993,   p.219
           */
          
      35  int sem_init(  
           sem_t *sem,  
           int pshared,  
           unsigned int value
           )
          {
           int status;
           POSIX_Semaphore_Control *the_semaphore;
          
           if (   !sem  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           status = _POSIX_Semaphore_Create_support(  
           NULL,  
           pshared,  
           value,  
           &the_semaphore
            );
          
           if (   status != -1  )
           *sem = the_semaphore->Object.id;
          
           return status;
          }

posix/src/semopen.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semopen.c,  v 1.15 2009/05/03 23:10:02 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * sem_open
           *
           * Opens a named semaphore. Used in conjunction with the sem_close
           * and sem_unlink commands.
           *
           * 11.2.3 Initialize/Open a Named Semaphore,   P1003.1b-1993,   p.221
           *
           * NOTE: When oflag is O_CREAT,   then optional third and fourth
           * parameters must be present.
           */
          
      43  sem_t *sem_open(  
           const char *name,  
           int oflag,  
           ...
           /* mode_t mode,   */
           /* unsigned int value */
           )
          {
           va_list arg;
           mode_t mode;
           unsigned int value = 0;
           int status;
           sem_t the_semaphore_id;
           sem_t *id;
           POSIX_Semaphore_Control *the_semaphore;
           Objects_Locations location;
          
           _Thread_Disable_dispatch(   );
          
           if (   oflag & O_CREAT  ) {
           va_start(  arg,   oflag );
           mode = (  mode_t ) va_arg(   arg,   unsigned int  );
           value = va_arg(   arg,   unsigned int  );
           va_end(  arg );
           }
          
           status = _POSIX_Semaphore_Name_to_id(   name,   &the_semaphore_id  );
          
           /*
           * If the name to id translation worked,   then the semaphore exists
           * and we can just return a pointer to the id. Otherwise we may
           * need to check to see if this is a "semaphore does not exist"
           * or some other miscellaneous error on the name.
           */
          
           if (   status  ) {
          
           /*
           * Unless provided a valid name that did not already exist
           * and we are willing to create then it is an error.
           */
          
           if (   !(   status == ENOENT && (  oflag & O_CREAT )  )  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one_cast(   status,   sem_t *  );
           }
           } else {
          
           /*
           * Check for existence with creation.
           */
          
           if (   (  oflag & (  O_CREAT | O_EXCL ) ) == (  O_CREAT | O_EXCL )  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one_cast(   EEXIST,   sem_t *  );
           }
          
           the_semaphore = _POSIX_Semaphore_Get(   &the_semaphore_id,   &location  );
           the_semaphore->open_count += 1;
           _Thread_Enable_dispatch(   );
           _Thread_Enable_dispatch(   );
           goto return_id;
           }
          
           /*
           * At this point,   the semaphore does not exist and everything has been
           * checked. We should go ahead and create a semaphore.
           */
          
           status =_POSIX_Semaphore_Create_support(  
           name,  
           false,   /* not shared across processes */
           value,  
           &the_semaphore
            );
          
           /*
           * errno was set by Create_support,   so don't set it again.
           */
          
           _Thread_Enable_dispatch(   );
          
           if (   status == -1  )
           return SEM_FAILED;
          
          return_id:
           #if defined(  RTEMS_USE_16_BIT_OBJECT )
           the_semaphore->Semaphore_id = the_semaphore->Object.id;
           id = &the_semaphore->Semaphore_id;
           #else
           id = (  sem_t * )&the_semaphore->Object.id;
           #endif
           return id;
          }

posix/src/sempost.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sempost.c,  v 1.10 2007/12/17 16:19:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 11.2.7 Unlock a Semaphore,   P1003.1b-1993,   p.227
           */
          
      35  int sem_post(  
           sem_t *sem
           )
          {
           register POSIX_Semaphore_Control *the_semaphore;
           Objects_Locations location;
          
           the_semaphore = _POSIX_Semaphore_Get(   sem,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _CORE_semaphore_Surrender(  
           &the_semaphore->Semaphore,  
           the_semaphore->Object.id,  
          #if defined(  RTEMS_MULTIPROCESSING )
           NULL /* XXX need to define a routine to handle this case */
          #else
           NULL
          #endif
            );
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }

posix/src/semtimedwait.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semtimedwait.c,  v 1.15 2010/08/23 21:31:27 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 11.2.6 Lock a Semaphore,   P1003.1b-1993,   p.226
           *
           * NOTE: P1003.4b/D8 adds sem_timedwait(   ),   p. 27
           */
          
      37  int sem_timedwait(  
           sem_t *sem,  
           const struct timespec *abstime
           )
          {
           Watchdog_Interval ticks;
           bool do_wait = true;
           POSIX_Absolute_timeout_conversion_results_t status;
           int lock_status;
          
           /*
           * POSIX requires that blocking calls with timeouts that take
           * an absolute timeout must ignore issues with the absolute
           * time provided if the operation would otherwise succeed.
           * So we check the abstime provided,   and hold on to whether it
           * is valid or not. If it isn't correct and in the future,  
           * then we do a polling operation and convert the UNSATISFIED
           * status into the appropriate error.
           *
           * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID,  
           * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST,   or POSIX_ABSOLUTE_TIMEOUT_IS_NOW,  
           * then we should not wait.
           */
           status = _POSIX_Absolute_timeout_to_ticks(   abstime,   &ticks  );
           if (   status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE  )
           do_wait = false;
          
           lock_status = _POSIX_Semaphore_Wait_support(   sem,   do_wait,   ticks  );
          
           /*
           * This service only gives us the option to block. We used a polling
           * attempt to obtain if the abstime was not in the future. If we did
           * not obtain the semaphore,   then not look at the status immediately,  
           * make sure the right reason is returned.
           */
           if (   !do_wait && (  lock_status == EBUSY )  ) {
           if (   lock_status == POSIX_ABSOLUTE_TIMEOUT_INVALID  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           if (   lock_status == POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
           lock_status == POSIX_ABSOLUTE_TIMEOUT_IS_NOW  )
           rtems_set_errno_and_return_minus_one(   ETIMEDOUT  );
           }
          
           return lock_status;
          }

posix/src/semtrywait.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semtrywait.c,  v 1.6 2009/02/03 10:10:57 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 11.2.6 Lock a Semaphore,   P1003.1b-1993,   p.226
           *
           * NOTE: P1003.4b/D8 adds sem_timedwait(   ),   p. 27
           */
          
      37  int sem_trywait(  
           sem_t *sem
           )
          {
           return _POSIX_Semaphore_Wait_support(  sem,   false,   THREAD_QUEUE_WAIT_FOREVER );
          }

posix/src/semunlink.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semunlink.c,  v 1.14 2009/02/03 10:10:57 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * sem_unlink
           *
           * Unlinks a named semaphore,   sem_close must also be called to remove
           * the semaphore.
           *
           * 11.2.5 Remove a Named Semaphore,   P1003.1b-1993,   p.225
           */
          
      40  int sem_unlink(  
           const char *name
           )
          {
           int status;
           register POSIX_Semaphore_Control *the_semaphore;
           sem_t the_semaphore_id;
          
           _Thread_Disable_dispatch(   );
          
           status = _POSIX_Semaphore_Name_to_id(   name,   &the_semaphore_id  );
           if (   status != 0  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   status  );
           }
          
           the_semaphore = (  POSIX_Semaphore_Control * ) _Objects_Get_local_object(  
           &_POSIX_Semaphore_Information,  
           _Objects_Get_index(   the_semaphore_id  )
            );
          
           the_semaphore->linked = false;
           _POSIX_Semaphore_Namespace_remove(   the_semaphore  );
           _POSIX_Semaphore_Delete(   the_semaphore  );
          
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/semwait.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semwait.c,  v 1.7 2009/02/03 10:10:57 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdarg.h>
          
          #include <errno.h>
          #include <fcntl.h>
          #include <pthread.h>
          #include <semaphore.h>
          #include <limits.h>
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/time.h>
          #include <rtems/seterr.h>
          
          /*PAGE
           *
           * 11.2.6 Lock a Semaphore,   P1003.1b-1993,   p.226
           *
           * NOTE: P1003.4b/D8 adds sem_timedwait(   ),   p. 27
           */
          
      37  int sem_wait(  
           sem_t *sem
           )
          {
           return _POSIX_Semaphore_Wait_support(   sem,   true,   THREAD_QUEUE_WAIT_FOREVER  );
          }

posix/src/setcancelstate.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: setcancelstate.c,  v 1.10 2009/07/21 14:16:00 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/posix/cancel.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/threadsup.h>
          
          /*
           * 18.2.2 Setting Cancelability State,   P1003.1c/Draft 10,   p. 183
           */
          
      31  int pthread_setcancelstate(  
           int state,  
           int *oldstate
           )
          {
           POSIX_API_Control *thread_support;
          
           /*
           * Don't even think about deleting a resource from an ISR.
           * Besides this request is supposed to be for _Thread_Executing
           * and the ISR context is not a thread.
           */
          
           if (   _ISR_Is_in_progress(   )  )
           return EPROTO;
          
           if (   !oldstate  )
           return EINVAL;
          
           if (   state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE  )
           return EINVAL;
          
           thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
          
           _Thread_Disable_dispatch(   );
           *oldstate = thread_support->cancelability_state;
           thread_support->cancelability_state = state;
          
           _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch(  _Thread_Executing );
          
           /*
           * _Thread_Enable_dispatch is invoked by above call.
           */
          
           return 0;
          }

posix/src/setcanceltype.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: setcanceltype.c,  v 1.11 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/posix/cancel.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/threadsup.h>
          
          /*
           * 18.2.2 Setting Cancelability State,   P1003.1c/Draft 10,   p. 183
           */
          
      31  int pthread_setcanceltype(  
           int type,  
           int *oldtype
           )
          {
           POSIX_API_Control *thread_support;
          
           /*
           * Don't even think about deleting a resource from an ISR.
           * Besides this request is supposed to be for _Thread_Executing
           * and the ISR context is not a thread.
           */
          
           if (   _ISR_Is_in_progress(   )  )
           return EPROTO;
          
           if (   !oldtype  )
           return EINVAL;
          
           if (   type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS  )
           return EINVAL;
          
           thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
          
           _Thread_Disable_dispatch(   );
           *oldtype = thread_support->cancelability_type;
           thread_support->cancelability_type = type;
          
           _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch(  _Thread_Executing );
          
           /*
           * _Thread_Enable_dispatch is invoked by above call.
           */
           return 0;
          }

posix/src/setitimer.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: setitimer.c,  v 1.2 2009/05/15 17:43:02 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <sys/time.h>
          #include <errno.h>
          #include <rtems/seterr.h>
          
      21  int setitimer(  
           int which,  
           const struct itimerval *value,  
           struct itimerval *ovalue
           )
          {
           if (   !value  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           if (   !ovalue  )
           rtems_set_errno_and_return_minus_one(   EFAULT  );
          
           switch (   which  ) {
           case ITIMER_REAL:
           case ITIMER_VIRTUAL:
           case ITIMER_PROF:
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
           default:
           break;
           }
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }
          

posix/src/sigaction.c

       1  /*
           * 3.3.4 Examine and Change Signal Action,   P1003.1b-1993,   p. 70
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigaction.c,  v 1.12 2009/08/05 21:39:49 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <signal.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/seterr.h>
          #include <rtems/score/isr.h>
          
          /*
           * PARAMETERS_PASSING_S is defined in ptimer.c
           */
          
      32  extern void PARAMETERS_PASSING_S (  int num_signal,   const struct sigaction inf );
          
      34  int sigaction(  
           int sig,  
           const struct sigaction *act,  
           struct sigaction *oact
           )
          {
           ISR_Level level;
          
           if (   oact  )
           *oact = _POSIX_signals_Vectors[ sig ];
          
           if (   !sig  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   !is_valid_signo(  sig )  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /*
           * Some signals cannot be ignored (  P1003.1b-1993,   pp. 70-72 and references.
           *
           * NOTE: Solaris documentation claims to "silently enforce" this which
           * contradicts the POSIX specification.
           */
          
           if (   sig == SIGKILL  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /*
           * Evaluate the new action structure and set the global signal vector
           * appropriately.
           */
          
           if (   act  ) {
          
           /*
           * Unless the user is installing the default signal actions,   then
           * we can just copy the provided sigaction structure into the vectors.
           */
          
           _ISR_Disable(   level  );
           if (   act->sa_handler == SIG_DFL  ) {
           _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ];
           } else {
           _POSIX_signals_Clear_process_signals(   sig  );
           _POSIX_signals_Vectors[ sig ] = *act;
           }
           _ISR_Enable(   level  );
           }
          
           /*
           * No need to evaluate or dispatch because:
           *
           * + If we were ignoring the signal before,   none could be pending
           * now (  signals not posted when SIG_IGN ).
           * + If we are now ignoring a signal that was previously pending,  
           * we clear the pending signal indicator.
           */
          
           return 0;
          }

posix/src/sigaddset.c

       1  /*
           * 3.3.3 Manipulate Signal Sets,   P1003.1b-1993,   p. 69
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigaddset.c,  v 1.8 2009/12/04 15:47:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/sigset.h>
          #include <rtems/seterr.h>
          
      24  int sigaddset(  
           sigset_t *set,  
           int signo
           )
          {
           if (   !set  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   !signo  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   !is_valid_signo(  signo )  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           *set |= signo_to_mask(  signo );
           return 0;
          }

posix/src/sigdelset.c

       1  /*
           * 3.3.3 Manipulate Signal Sets,   P1003.1b-1993,   p. 69
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigdelset.c,  v 1.8 2009/12/04 15:47:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/sigset.h>
          #include <rtems/seterr.h>
          
          /*
           * 3.3.3 Manipulate Signal Sets,   P1003.1b-1993,   p. 69
           */
          
      28  int sigdelset(  
           sigset_t *set,  
           int signo
           )
          {
           if (   !set  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   !signo  )
           return 0;
          
           if (   !is_valid_signo(  signo )  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           *set &= ~signo_to_mask(  signo );
           return 0;
          }

posix/src/sigemptyset.c

       1  /*
           * 3.3.3 Manipulate Signal Sets,   P1003.1b-1993,   p. 69
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigemptyset.c,  v 1.8 2009/12/04 15:47:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/sigset.h>
          #include <rtems/seterr.h>
          
      24  int sigemptyset(  
           sigset_t *set
           )
          {
           if (   !set  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           *set = 0;
           return 0;
          }

posix/src/sigfillset.c

       1  /*
           * 3.3.3 Manipulate Signal Sets,   P1003.1b-1993,   p. 69
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigfillset.c,  v 1.8 2009/12/04 15:47:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/sigset.h>
          #include <rtems/seterr.h>
          
      24  int sigfillset(  
           sigset_t *set
           )
          {
           if (   !set  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           *set = SIGNAL_ALL_MASK;
           return 0;
          }

posix/src/sigismember.c

       1  /*
           * 3.3.3 Manipulate Signal Sets,   P1003.1b-1993,   p. 69
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigismember.c,  v 1.8 2009/12/04 15:47:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/sigset.h>
          #include <rtems/seterr.h>
          
      24  int sigismember(  
           const sigset_t *set,  
           int signo
           )
          {
           if (   !set  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   !signo  )
           return 0;
          
           if (   !is_valid_signo(  signo )  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   *set & signo_to_mask(  signo )  )
           return 1;
          
           return 0;
          }

posix/src/signal_2.c

       1  /*
           * signal(  2 ) - Install signal handler
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: signal_2.c,  v 1.4 2003/09/04 18:54:26 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <signal.h>
          #include <errno.h>
          
          typedef void (  *sighandler_t )(  int );
          
      23  sighandler_t signal(  
           int signum,  
           sighandler_t handler
           )
          {
           struct sigaction s;
           struct sigaction old;
          
           s.sa_handler = handler ;
           sigemptyset(  &s.sa_mask );
          
           /*
           * Depending on which system we want to behave like,   one of
           * the following versions should be chosen.
           */
          
          /* #define signal_like_linux */
          
          #if defined(  signal_like_linux )
           s.sa_flags = SA_RESTART | SA_INTERRUPT | SA_NOMASK;
           s.sa_restorer= NULL ;
          #elif defined(  signal_like_SVR4 )
           s.sa_flags = SA_RESTART;
          #else
           s.sa_flags = 0;
          #endif
          
           sigaction(   signum,   &s,   &old  );
           return (  sighandler_t ) old.sa_handler;
          }

posix/src/sigpending.c

       1  /*
           * 3.3.6 Examine Pending Signals,   P1003.1b-1993,   p. 75
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigpending.c,  v 1.6 2003/09/04 18:54:26 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <signal.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/seterr.h>
          
      26  int sigpending(  
           sigset_t *set
           )
          {
           POSIX_API_Control *api;
          
           if (   !set  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
          
           *set = api->signals_pending | _POSIX_signals_Pending;
          
           return 0;
          }

posix/src/sigprocmask.c

       1  /*
           * 3.3.5 Examine and Change Blocked Signals,   P1003.1b-1993,   p. 73
           *
           * NOTE: P1003.1c/D10,   p. 37 adds pthread_sigmask(   ).
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigprocmask.c,  v 1.6 2009/12/10 07:17:48 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <signal.h>
          
      23  int sigprocmask(  
           int how,  
           const sigset_t *set,  
           sigset_t *oset
           )
          {
           /*
           * P1003.1c/Draft 10,   p. 38 maps sigprocmask to pthread_sigmask.
           */
          
          #if defined(  RTEMS_POSIX_API )
           return pthread_sigmask(   how,   set,   oset  );
          #else
           return -1;
          #endif
          }

posix/src/sigqueue.c

       1  /*
           * 3.3.9 Queue a Signal to a Process,   P1003.1b-1993,   p. 78
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigqueue.c,  v 1.5 2004/04/15 13:24:47 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          
      25  int sigqueue(  
           pid_t pid,  
           int signo,  
           const union sigval value
           )
          {
           return killinfo(   pid,   signo,   &value  );
          }

posix/src/sigsuspend.c

       1  /*
           * 3.3.7 Wait for a Signal,   P1003.1b-1993,   p. 75
           *
           * COPYRIGHT (  c ) 1989-2004.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigsuspend.c,  v 1.7 2010/07/27 17:37:54 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <assert.h>
          #include <signal.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/seterr.h>
          
      27  int sigsuspend(  
           const sigset_t *sigmask
           )
          {
           sigset_t saved_signals_blocked;
           sigset_t current_unblocked_signals;
           int status;
           POSIX_API_Control *api;
          
           api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
          
           /*
           * We use SIG_BLOCK and not SIG_SETMASK because there may be
           * signals which might be pending,   which might get caught here.
           * We want the signals to be caught inside sigtimedwait.
           */
           status = sigprocmask(   SIG_BLOCK,   sigmask,   &saved_signals_blocked  );
          
           current_unblocked_signals = ~(  *sigmask );
           status = sigtimedwait(   &current_unblocked_signals,   NULL,   NULL  );
          
           (  void ) sigprocmask(   SIG_SETMASK,   &saved_signals_blocked,   NULL  );
          
           /*
           * sigtimedwait(   ) returns the signal number while sigsuspend(   )
           * is supposed to return -1 and EINTR when a signal is caught.
           */
           #if defined(  RTEMS_DEBUG )
           assert(   status != -1  );
           #endif
          
           rtems_set_errno_and_return_minus_one(   EINTR  );
          }

posix/src/sigtimedwait.c

       1  /*
           * 3.3.8 Synchronously Accept a Signal,   P1003.1b-1993,   p. 76
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigtimedwait.c,  v 1.18 2010/07/27 16:34:26 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <signal.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/seterr.h>
          #include <rtems/posix/time.h>
          #include <rtems/score/isr.h>
          
      29  int _POSIX_signals_Get_lowest(  
           sigset_t set
           )
          {
           int signo;
          
           for (   signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++  ) {
           if (   set & signo_to_mask(   signo  )  ) {
           goto found_it;
           }
           }
          
           /*
           * We assume SIGHUP == 1 and is the first non-real-time signal.
           */
          
           #if (  SIGHUP != 1 )
           #error "Assumption that SIGHUP==1 violated!!"
           #endif
           for (   signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++  ) {
           if (   set & signo_to_mask(   signo  )  ) {
           goto found_it;
           }
           }
          
           /*
           * This is structured this way to eliminate the need to have
           * a return 0. This routine will NOT be called unless a signal
           * is pending in the set passed in.
           */
          found_it:
           return signo;
          }
          
      63  int sigtimedwait(  
           const sigset_t *set,  
           siginfo_t *info,  
           const struct timespec *timeout
           )
          {
           Thread_Control *the_thread;
           POSIX_API_Control *api;
           Watchdog_Interval interval;
           siginfo_t signal_information;
           siginfo_t *the_info;
           int signo;
           ISR_Level level;
          
           /*
           * Error check parameters before disabling interrupts.
           */
           if (   !set  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /* NOTE: This is very specifically a RELATIVE not ABSOLUTE time
           * in the Open Group specification.
           */
          
           interval = 0;
           if (   timeout  ) {
          
           if (   !_Timespec_Is_valid(   timeout  )  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           interval = _Timespec_To_ticks(   timeout  );
          
           if (   !interval  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           /*
           * Initialize local variables.
           */
          
           the_info = (   info  ) ? info : &signal_information;
          
           the_thread = _Thread_Executing;
          
           api = the_thread->API_Extensions[ THREAD_API_POSIX ];
          
           /*
           * What if they are already pending?
           */
          
           /* API signals pending? */
          
           _ISR_Disable(   level  );
           if (   *set & api->signals_pending  ) {
           /* XXX real info later */
           the_info->si_signo = _POSIX_signals_Get_lowest(   api->signals_pending  );
           _POSIX_signals_Clear_signals(  
           api,  
           the_info->si_signo,  
           the_info,  
           false,  
           false
            );
           _ISR_Enable(   level  );
          
           the_info->si_code = SI_USER;
           the_info->si_value.sival_int = 0;
           return the_info->si_signo;
           }
          
           /* Process pending signals? */
          
           if (   *set & _POSIX_signals_Pending  ) {
           signo = _POSIX_signals_Get_lowest(   _POSIX_signals_Pending  );
           _POSIX_signals_Clear_signals(   api,   signo,   the_info,   true,   false  );
           _ISR_Enable(   level  );
          
           the_info->si_signo = signo;
           the_info->si_code = SI_USER;
           the_info->si_value.sival_int = 0;
           return signo;
           }
          
           the_info->si_signo = -1;
          
           _Thread_Disable_dispatch(   );
           the_thread->Wait.queue = &_POSIX_signals_Wait_queue;
           the_thread->Wait.return_code = EINTR;
           the_thread->Wait.option = *set;
           the_thread->Wait.return_argument = the_info;
           _Thread_queue_Enter_critical_section(   &_POSIX_signals_Wait_queue  );
           _ISR_Enable(   level  );
           _Thread_queue_Enqueue(   &_POSIX_signals_Wait_queue,   interval  );
           _Thread_Enable_dispatch(   );
          
           /*
           * When the thread is set free by a signal,   it is need to eliminate
           * the signal.
           */
          
           _POSIX_signals_Clear_signals(   api,   the_info->si_signo,   the_info,   false,   false  );
          
           /* Set errno only if return code is not EINTR or
           * if EINTR was caused by a signal being caught,   which
           * was not in our set.
           */
          
           if (   (  _Thread_Executing->Wait.return_code != EINTR )
           || !(  *set & signo_to_mask(   the_info->si_signo  ) )  ) {
           errno = _Thread_Executing->Wait.return_code;
           return -1;
           }
          
           return the_info->si_signo;
          }

posix/src/sigwait.c

       1  /*
           * 3.3.8 Synchronously Accept a Signal,   P1003.1b-1993,   p. 76
           *
           * NOTE: P1003.1c/D10,   p. 39 adds sigwait(   ).
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigwait.c,  v 1.5 2004/04/15 13:24:47 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <signal.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          
      28  int sigwait(  
           const sigset_t *set,  
           int *sig
           )
          {
           int status;
          
           status = sigtimedwait(   set,   NULL,   NULL  );
          
           if (   status != -1  ) {
           if (   sig  )
           *sig = status;
           return 0;
           }
          
           return errno;
          }

posix/src/sigwaitinfo.c

       1  /*
           * 3.3.8 Synchronously Accept a Signal,   P1003.1b-1993,   p. 76
           *
           * NOTE: P1003.1c/D10,   p. 39 adds sigwait(   ).
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sigwaitinfo.c,  v 1.5 2004/04/15 13:24:47 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <signal.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          
      27  int sigwaitinfo(  
           const sigset_t *set,  
           siginfo_t *info
           )
          {
           return sigtimedwait(   set,   info,   NULL  );
          }

posix/src/sleep.c

       1  /*
           * 3.4.3 Delay Process Execution,   P1003.1b-1993,   p. 81
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sleep.c,  v 1.5 2008/12/05 06:44:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_SLEEP
          #include <time.h>
          #include <unistd.h>
          
          #include <rtems/system.h>
          
          
      25  unsigned int sleep(  
           unsigned int seconds
           )
          {
           struct timespec tp;
           struct timespec tm;
          
           tp.tv_sec = seconds;
           tp.tv_nsec = 0;
          
           nanosleep(   &tp,   &tm  );
          
           return tm.tv_sec; /* seconds remaining */
          }
          
          #endif

posix/src/sysconf.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sysconf.c,  v 1.16 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <unistd.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <rtems/score/tod.h>
          #include <rtems/libio_.h>
          
          #include <sys/param.h>
          
          /*PAGE
           *
           * 4.8.1 Get Configurable System Variables,   P1003.1b-1993,   p. 95
           */
          
      32  long sysconf(  
           int name
           )
          {
           if (   name == _SC_CLK_TCK  )
           return (  TOD_MICROSECONDS_PER_SECOND /
           rtems_configuration_get_microseconds_per_tick(   ) );
          
           if (   name == _SC_OPEN_MAX  )
           return rtems_libio_number_iops;
          
           if (   name == _SC_GETPW_R_SIZE_MAX  )
           return 1024;
          
           if (   name == _SC_PAGESIZE  )
           return PAGE_SIZE;
          
          #if defined(  __sparc__ )
           if (   name == 515  ) /* Solaris _SC_STACK_PROT */
           return 0;
          #endif
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }

posix/src/testcancel.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: testcancel.c,  v 1.8 2008/09/04 15:23:12 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/posix/cancel.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/threadsup.h>
          
          /*PAGE
           *
           * 18.2.2 Setting Cancelability State,   P1003.1c/Draft 10,   p. 183
           */
          
      33  void pthread_testcancel(   void  )
          {
           POSIX_API_Control *thread_support;
           bool cancel = false;
          
           /*
           * Don't even think about deleting a resource from an ISR.
           * Besides this request is supposed to be for _Thread_Executing
           * and the ISR context is not a thread.
           */
          
           if (   _ISR_Is_in_progress(   )  )
           return;
          
           thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
          
           _Thread_Disable_dispatch(   );
           if (   thread_support->cancelability_state == PTHREAD_CANCEL_ENABLE &&
           thread_support->cancelation_requested  )
           cancel = true;
           _Thread_Enable_dispatch(   );
          
           if (   cancel  )
           _POSIX_Thread_Exit(   _Thread_Executing,   PTHREAD_CANCELED  );
          }

posix/src/timercreate.c

       1  /*
           * 14.2.2 Create a Per-Process Timer,   P1003.1b-1993,   p. 264
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timercreate.c,  v 1.3 2009/11/30 15:44:21 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          #include <signal.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <rtems/score/thread.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/timer.h>
          
      29  int timer_create(  
           clockid_t clock_id,  
           struct sigevent *evp,  
           timer_t *timerid
           )
          {
           POSIX_Timer_Control *ptimer;
          
           if (   clock_id != CLOCK_REALTIME  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   !timerid  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /*
           * The data of the structure evp are checked in order to verify if they
           * are coherent.
           */
          
           if (  evp != NULL ) {
           /* The structure has data */
           if (   (   evp->sigev_notify != SIGEV_NONE  ) &&
           (   evp->sigev_notify != SIGEV_SIGNAL  )  ) {
           /* The value of the field sigev_notify is not valid */
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           if (   !evp->sigev_signo  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           if (   !is_valid_signo(  evp->sigev_signo )  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           _Thread_Disable_dispatch(   ); /* to prevent deletion */
          
           /*
           * Allocate a timer
           */
           ptimer = _POSIX_Timer_Allocate(   );
           if (   !ptimer  ) {
           _Thread_Enable_dispatch(   );
           rtems_set_errno_and_return_minus_one(   EAGAIN  );
           }
          
           /* The data of the created timer are stored to use them later */
          
           ptimer->state = POSIX_TIMER_STATE_CREATE_NEW;
           ptimer->thread_id = _Thread_Executing->Object.id;
          
           if (   evp != NULL  ) {
           ptimer->inf.sigev_notify = evp->sigev_notify;
           ptimer->inf.sigev_signo = evp->sigev_signo;
           ptimer->inf.sigev_value = evp->sigev_value;
           }
          
           ptimer->overrun = 0;
           ptimer->timer_data.it_value.tv_sec = 0;
           ptimer->timer_data.it_value.tv_nsec = 0;
           ptimer->timer_data.it_interval.tv_sec = 0;
           ptimer->timer_data.it_interval.tv_nsec = 0;
          
           _Watchdog_Initialize(   &ptimer->Timer,   NULL,   0,   NULL  );
           _Objects_Open_u32(  &_POSIX_Timer_Information,   &ptimer->Object,   0 );
          
           *timerid = ptimer->Object.id;
           _Thread_Enable_dispatch(   );
           return 0;
          }

posix/src/timerdelete.c

       1  /*
           * 14.2.3 Delete a Per_process Timer,   P1003.1b-1993,   p. 266
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timerdelete.c,  v 1.1 2007/12/17 16:01:42 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          #include <pthread.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <rtems/score/thread.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/timer.h>
          
          
      29  int timer_delete(  
           timer_t timerid
           )
          {
           /*
           * IDEA: This function must probably stop the timer first and then delete it
           *
           * It will have to do a call to rtems_timer_cancel and then another
           * call to rtems_timer_delete.
           * The call to rtems_timer_delete will be probably unnecessary,  
           * because rtems_timer_delete stops the timer before deleting it.
           */
           POSIX_Timer_Control *ptimer;
           Objects_Locations location;
          
           ptimer = _POSIX_Timer_Get(   timerid,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _Objects_Close(   &_POSIX_Timer_Information,   &ptimer->Object  );
           ptimer->state = POSIX_TIMER_STATE_FREE;
           (  void ) _Watchdog_Remove(   &ptimer->Timer  );
           _POSIX_Timer_Free(   ptimer  );
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }

posix/src/timergetoverrun.c

       1  /*
           * 14.2.4 Per-Process Timers,   P1003.1b-1993,   p. 267
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timergetoverrun.c,  v 1.1 2007/12/17 16:01:42 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <rtems/score/thread.h>
          #include <rtems/posix/timer.h>
          
          /*
           * timer_getoverrun
           *
           * The expiration of a timer must increase by one a counter.
           * After the signal handler associated to the timer finishes
           * its execution,   _POSIX_Timer_TSR will have to set this counter to 0.
           */
      33  int timer_getoverrun(  
           timer_t timerid
           )
          {
           int overrun;
           POSIX_Timer_Control *ptimer;
           Objects_Locations location;
          
           ptimer = _POSIX_Timer_Get(   timerid,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           overrun = ptimer->overrun;
           ptimer->overrun = 0;
           _Thread_Enable_dispatch(   );
           return overrun;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }

posix/src/timergettime.c

       1  /*
           * 14.2.4 Per-Process Timers,   P1003.1b-1993,   p. 267
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timergettime.c,  v 1.3 2008/01/18 16:31:56 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/timespec.h>
          #include <rtems/posix/timer.h>
          
          /*
           * - When a timer is initialized,   the value of the time in
           * that moment is stored.
           * - When this function is called,   it returns the difference
           * between the current time and the initialization time.
           */
          
      35  int timer_gettime(  
           timer_t timerid,  
           struct itimerspec *value
           )
          {
           POSIX_Timer_Control *ptimer;
           Objects_Locations location;
           struct timespec current_time;
           Watchdog_Interval left;
          
           if (   !value  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /* Reads the current time */
           _TOD_Get(   &current_time  );
          
           ptimer = _POSIX_Timer_Get(   timerid,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           /* Calculates the time left before the timer finishes */
          
           left =
           (  ptimer->Timer.start_time + ptimer->Timer.initial ) - /* expire */
           _Watchdog_Ticks_since_boot; /* now */
          
           _Timespec_From_ticks(   left,   &value->it_value  );
          
           value->it_interval = ptimer->timer_data.it_interval;
          
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }

posix/src/timerinserthelper.c

       1  /*
           * Helper routine for POSIX timers
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timerinserthelper.c,  v 1.2 2008/09/04 15:23:12 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/posix/timer.h>
          #include <rtems/posix/ptimer.h>
          
      27  bool _POSIX_Timer_Insert_helper(  
           Watchdog_Control *timer,  
           Watchdog_Interval ticks,  
           Objects_Id id,  
           Watchdog_Service_routine_entry TSR,  
           void *arg
           )
          {
           ISR_Level level;
          
           (  void ) _Watchdog_Remove(   timer  );
           _ISR_Disable(   level  );
          
           /*
           * Check to see if the watchdog has just been inserted by a
           * higher priority interrupt. If so,   abandon this insert.
           */
           if (   timer->state != WATCHDOG_INACTIVE  ) {
           _ISR_Enable(   level  );
           return false;
           }
          
           /*
           * OK. Now we now the timer was not rescheduled by an interrupt
           * so we can atomically initialize it as in use.
           */
           _Watchdog_Initialize(   timer,   TSR,   id,   arg  );
           _Watchdog_Insert_ticks(   timer,   ticks  );
           _ISR_Enable(   level  );
           return true;
          }

posix/src/timersettime.c

       1  /*
           * 14.2.4 Per-Process Timers,   P1003.1b-1993,   p. 267
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timersettime.c,  v 1.10 2010/06/22 15:36:06 jennifer Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <errno.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/ptimer.h>
          #include <rtems/posix/timer.h>
          
      29  int timer_settime(  
           timer_t timerid,  
           int flags,  
           const struct itimerspec *value,  
           struct itimerspec *ovalue
           )
          {
           POSIX_Timer_Control *ptimer;
           Objects_Locations location;
           bool activated;
           uint32_t initial_period;
           struct itimerspec normalize;
          
           if (   !value  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          
           /*
           * First,   it verifies if the structure "value" is correct
           * if the number of nanoseconds is not correct return EINVAL
           */
           if (   !_Timespec_Is_valid(   &(  value->it_value )  )  ) {
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
           if (   !_Timespec_Is_valid(   &(  value->it_interval )  )  ) {
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           if (   flags != TIMER_ABSTIME && flags != POSIX_TIMER_RELATIVE  ) {
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           }
          
           normalize = *value;
          
           /* Convert absolute to relative time */
           if (  flags == TIMER_ABSTIME ) {
           struct timespec now;
           _TOD_Get(   &now  );
           /* Check for seconds in the past */
           if (   _Timespec_Greater_than(   &now,   &normalize.it_value  )  )
           rtems_set_errno_and_return_minus_one(   EINVAL  );
           _Timespec_Subtract(   &now,   &normalize.it_value,   &normalize.it_value  );
           }
          
           /* If the function reaches this point,   then it will be necessary to do
           * something with the structure of times of the timer: to stop,   start
           * or start it again
           */
          
           ptimer = _POSIX_Timer_Get(   timerid,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           /* First,   it verifies if the timer must be stopped */
           if (   normalize.it_value.tv_sec == 0 && normalize.it_value.tv_nsec == 0  ) {
           /* Stop the timer */
           (  void ) _Watchdog_Remove(   &ptimer->Timer  );
           /* The old data of the timer are returned */
           if (   ovalue  )
           *ovalue = ptimer->timer_data;
           /* The new data are set */
           ptimer->timer_data = normalize;
           /* Indicates that the timer is created and stopped */
           ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
           /* Returns with success */
           _Thread_Enable_dispatch(   );
           return 0;
           }
          
           /* Convert from seconds and nanoseconds to ticks */
           ptimer->ticks = _Timespec_To_ticks(   &value->it_interval  );
           initial_period = _Timespec_To_ticks(   &normalize.it_value  );
          
          
           activated = _POSIX_Timer_Insert_helper(  
           &ptimer->Timer,  
           initial_period,  
           ptimer->Object.id,  
           _POSIX_Timer_TSR,  
           ptimer
            );
           if (   !activated  ) {
           _Thread_Enable_dispatch(   );
           return 0;
           }
          
           /*
           * The timer has been started and is running. So we return the
           * old ones in "ovalue"
           */
           if (   ovalue  )
           *ovalue = ptimer->timer_data;
           ptimer->timer_data = normalize;
          
           /* Indicate that the time is running */
           ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
           _TOD_Get(   &ptimer->time  );
           _Thread_Enable_dispatch(   );
           return 0;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           rtems_set_errno_and_return_minus_one(   EINVAL  );
          }

posix/src/timertsr.c

       1  /*
           * _POSIX_Timer_TSR
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timertsr.c,  v 1.3 2009/01/02 10:04:24 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          #include <pthread.h>
          #include <signal.h>
          
          #include <rtems/system.h>
          #include <rtems/seterr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/posix/time.h>
          #include <rtems/posix/ptimer.h>
          #include <rtems/posix/timer.h>
          
          /*
           * This is the operation that is run when a timer expires
           */
      33  void _POSIX_Timer_TSR(  
           Objects_Id timer __attribute__(  (  unused ) ),  
           void *data )
          {
           POSIX_Timer_Control *ptimer;
           bool activated;
          
           ptimer = (  POSIX_Timer_Control * )data;
          
           /* Increment the number of expirations. */
           ptimer->overrun = ptimer->overrun + 1;
          
           /* The timer must be reprogrammed */
           if (   (   ptimer->timer_data.it_interval.tv_sec != 0  ) ||
           (   ptimer->timer_data.it_interval.tv_nsec != 0  )  ) {
           activated = _POSIX_Timer_Insert_helper(  
           &ptimer->Timer,  
           ptimer->ticks,  
           ptimer->Object.id,  
           _POSIX_Timer_TSR,  
           ptimer
            );
           if (   !activated  )
           return;
          
           /* Store the time when the timer was started again */
           _TOD_Get(   &ptimer->time  );
          
           /* The state really did not change but just to be safe */
           ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
           } else {
           /* Indicates that the timer is stopped */
           ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
           }
          
           /*
           * The sending of the signal to the process running the handling function
           * specified for that signal is simulated
           */
          
           if (   pthread_kill (   ptimer->thread_id,   ptimer->inf.sigev_signo  )  ) {
           /* XXX error handling */
           }
          
           /* After the signal handler returns,   the count of expirations of the
           * timer must be set to 0.
           */
           ptimer->overrun = 0;
          }

posix/src/ualarm.c

       1  /*
           * 3.4.1 Schedule Alarm,   P1003.1b-1993,   p. 79
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ualarm.c,  v 1.12 2010/04/30 08:37:27 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <pthread.h>
          /* #include <errno.h> */
          
          #include <rtems/system.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * _POSIX_signals_Ualarm_TSR
           */
          
      31  void _POSIX_signals_Ualarm_TSR(  
           Objects_Id id __attribute__(  (  unused ) ),  
           void *argument __attribute__(  (  unused ) )
           )
          {
           /*
           * Send a SIGALRM but if there is a problem,   ignore it.
           * It's OK,   there isn't a way this should fail.
           */
           (  void ) kill(   getpid(   ),   SIGALRM  );
          
           /*
           * If the reset interval is non-zero,   reschedule ourselves.
           */
           _Watchdog_Reset(   &_POSIX_signals_Ualarm_timer  );
          }
          
      48  useconds_t ualarm(  
           useconds_t useconds,  
           useconds_t interval
           )
          {
           useconds_t remaining = 0;
           Watchdog_Control *the_timer;
           Watchdog_Interval ticks;
           struct timespec tp;
          
           the_timer = &_POSIX_signals_Ualarm_timer;
          
           /*
           * Initialize the timer used to implement alarm(   ).
           */
          
           if (   !the_timer->routine  ) {
           _Watchdog_Initialize(   the_timer,   _POSIX_signals_Ualarm_TSR,   0,   NULL  );
           } else {
           Watchdog_States state;
          
           state = _Watchdog_Remove(   the_timer  );
           if (   (  state == WATCHDOG_ACTIVE ) || (  state == WATCHDOG_REMOVE_IT )  ) {
           /*
           * The stop_time and start_time fields are snapshots of ticks since
           * boot. Since alarm(   ) is dealing in seconds,   we must account for
           * this.
           */
          
           ticks = the_timer->initial;
           ticks -= (  the_timer->stop_time - the_timer->start_time );
           /* remaining is now in ticks */
          
           _Timespec_From_ticks(   ticks,   &tp  );
           remaining = tp.tv_sec * TOD_MICROSECONDS_PER_SECOND;
           remaining += tp.tv_nsec / 1000;
           }
           }
          
           /*
           * If useconds is non-zero,   then the caller wants to schedule
           * the alarm repeatedly at that interval. If the interval is
           * less than a single clock tick,   then fudge it to a clock tick.
           */
           if (   useconds  ) {
           Watchdog_Interval ticks;
          
           tp.tv_sec = useconds / TOD_MICROSECONDS_PER_SECOND;
           tp.tv_nsec = (  useconds % TOD_MICROSECONDS_PER_SECOND ) * 1000;
           ticks = _Timespec_To_ticks(   &tp  );
           if (   ticks == 0  )
           ticks = 1;
          
           _Watchdog_Insert_ticks(   the_timer,   _Timespec_To_ticks(   &tp  )  );
           }
          
           return remaining;
          }

posix/src/usleep.c

       1  /*
           * 3.4.3 Delay Process Execution,   P1003.1b-1993,   p. 81
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: usleep.c,  v 1.4 2008/12/05 06:44:40 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifndef HAVE_USLEEP
          
          #include <time.h>
          #include <unistd.h>
          
          #include <rtems/system.h>
          #include <rtems/score/tod.h>
          
          
      27  int usleep(  
           useconds_t useconds
           )
          {
           struct timespec tp;
           struct timespec tm;
           unsigned remaining;
          
           tp.tv_sec = useconds / TOD_MICROSECONDS_PER_SECOND;
           tp.tv_nsec = (  useconds % TOD_MICROSECONDS_PER_SECOND ) * 1000;
          
           nanosleep(   &tp,   &tm  );
          
           remaining = tm.tv_sec * TOD_MICROSECONDS_PER_SECOND;
           remaining += tm.tv_nsec / 1000;
           return remaining; /* seconds remaining */
          }
          
          #endif

posix/src/vfork.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: vfork.c,  v 1.1 2008/11/20 16:56:53 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <unistd.h>
          
      19  pid_t vfork(  void )
          {
           return -1;
          }
          

posix/src/wait.c

       1  /*
           * waitpid(   ) - POSIX 1003.1b 3.2.1
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: wait.c,  v 1.4 2007/12/13 16:52:21 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/wait.h>
          #include <errno.h>
          #include <rtems/seterr.h>
          
      23  int wait(  
           int *stat_loc
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

posix/src/waitpid.c

       1  /*
           * waitpid(   ) - POSIX 1003.1 3.2.1
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: waitpid.c,  v 1.6 2007/12/13 16:52:21 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          #include <sys/wait.h>
          #include <errno.h>
          #include <rtems/seterr.h>
          
      23  int waitpid(  
           pid_t pid,  
           int *stat_loc,  
           int options
           )
          {
           rtems_set_errno_and_return_minus_one(   ENOSYS  );
          }

rtems/src/attr.c

       1  /*
           * Body for Attribute Routines
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: attr.c,  v 1.9 2008/06/13 15:06:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/stack.h>
          #include <rtems/rtems/modes.h>
          
          uint32_t rtems_interrupt_mask = RTEMS_INTERRUPT_MASK;
          
      26  rtems_attribute rtems_interrupt_level_attribute(  
           uint32_t level
           )
          {
           return RTEMS_INTERRUPT_LEVEL(  level );
          }

rtems/src/barrier.c

       1  /*
           * Barrier Manager
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Barrier Manager.
           *
           * Directives provided are:
           *
           * + create a barrier
           * + get an ID of a barrier
           * + delete a barrier
           * + acquire a barrier
           * + release a barrier
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barrier.c,  v 1.3 2009/01/06 05:05:02 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/barrier.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          
          /**
           * @brief _Barrier_Manager_initialization
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      48  void _Barrier_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_Barrier_Information,   /* object information table */
           OBJECTS_CLASSIC_API,   /* object API */
           OBJECTS_RTEMS_BARRIERS,   /* object class */
           Configuration_RTEMS_API.maximum_barriers,  
           /* maximum objects of this class */
           sizeof(   Barrier_Control  ),   /* size of this object's control block */
           false,   /* true if the name is a string */
           RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

rtems/src/barriercreate.c

       1  /*
           * Barrier Manager -- Create a Barrier Instance
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barriercreate.c,  v 1.1 2006/09/25 13:38:23 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/barrier.h>
          
          /*
           * rtems_barrier_create
           *
           * This directive creates a barrier. A barrier id is returned.
           *
           * Input parameters:
           * name - user defined barrier name
           * attribute_set - barrier attributes
           * maximum_waiters - number of threads before automatic release
           * priority_ceiling - barrier's ceiling priority
           * id - pointer to barrier id
           *
           * Output parameters:
           * id - barrier id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      44  rtems_status_code rtems_barrier_create(  
           rtems_name name,  
           rtems_attribute attribute_set,  
           uint32_t maximum_waiters,  
           rtems_id *id
           )
          {
           Barrier_Control *the_barrier;
           CORE_barrier_Attributes the_attributes;
          
           if (   !rtems_is_name_valid(   name  )  )
           return RTEMS_INVALID_NAME;
          
           if (   !id  )
           return RTEMS_INVALID_ADDRESS;
          
           /* Initialize core barrier attributes */
           if (   _Attributes_Is_barrier_automatic(   attribute_set  )  ) {
           the_attributes.discipline = CORE_BARRIER_AUTOMATIC_RELEASE;
           if (   maximum_waiters == 0  )
           return RTEMS_INVALID_NUMBER;
           } else
           the_attributes.discipline = CORE_BARRIER_MANUAL_RELEASE;
           the_attributes.maximum_count = maximum_waiters;
          
           _Thread_Disable_dispatch(   ); /* prevents deletion */
          
           the_barrier = _Barrier_Allocate(   );
          
           if (   !the_barrier  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_TOO_MANY;
           }
          
           the_barrier->attribute_set = attribute_set;
          
           _CORE_barrier_Initialize(   &the_barrier->Barrier,   &the_attributes  );
          
           _Objects_Open(  
           &_Barrier_Information,  
           &the_barrier->Object,  
           (  Objects_Name ) name
            );
          
           *id = the_barrier->Object.id;
          
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/barrierdata.c

       1  /*
           * Barrier Manager -- Instantiate Data
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barrierdata.c,  v 1.1 2007/05/21 23:19:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate barrier data */
          #define RTEMS_BARRIER_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/rtems/barrier.h>
          

rtems/src/barrierdelete.c

       1  /*
           * Barrier Manager -- Delete a Barrier
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barrierdelete.c,  v 1.3 2007/11/30 21:49:40 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/barrier.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*
           * rtems_barrier_delete
           *
           * This directive allows a thread to delete a barrier specified by
           * the barrier id. The barrier is freed back to the inactive
           * barrier chain.
           *
           * Input parameters:
           * id - barrier id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      41  rtems_status_code rtems_barrier_delete(  
           rtems_id id
           )
          {
           Barrier_Control *the_barrier;
           Objects_Locations location;
          
           the_barrier = _Barrier_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _CORE_barrier_Flush(  
           &the_barrier->Barrier,  
           NULL,  
           CORE_BARRIER_WAS_DELETED
            );
          
           _Objects_Close(   &_Barrier_Information,   &the_barrier->Object  );
          
           _Barrier_Free(   the_barrier  );
          
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/barrierident.c

       1  /*
           * Barrier Manager Name to ID
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barrierident.c,  v 1.2 2008/01/23 22:57:43 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/barrier.h>
          
          /*
           * rtems_barrier_ident
           *
           * This directive returns the system ID associated with
           * the barrier name.
           *
           * Input parameters:
           * name - user defined barrier name
           * id - pointer to barrier id
           *
           * Output parameters:
           * *id - barrier id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      41  rtems_status_code rtems_barrier_ident(  
           rtems_name name,  
           rtems_id *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
          
           status = _Objects_Name_to_id_u32(  
           &_Barrier_Information,  
           name,  
           OBJECTS_SEARCH_LOCAL_NODE,  
           id
            );
          
           return _Status_Object_name_errors_to_status[ status ];
          }

rtems/src/barrierrelease.c

       1  /*
           * Barrier Manager -- Release Tasks Waitng at a Barrier
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barrierrelease.c,  v 1.5 2007/11/30 21:49:40 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/barrier.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*
           * rtems_barrier_release
           *
           * This directive releases all threads waiting at a barrier.
           *
           * Input parameters:
           * id - barrier id
           * released - pointer to number of threads unblocked
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           * *released - number of threads unblocked
           */
          
      40  rtems_status_code rtems_barrier_release(  
           rtems_id id,  
           uint32_t *released
           )
          {
           Barrier_Control *the_barrier;
           Objects_Locations location;
          
           if (   !released  )
           return RTEMS_INVALID_ADDRESS;
          
           the_barrier = _Barrier_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           *released = _CORE_barrier_Release(   &the_barrier->Barrier,   id,   NULL  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/barriertranslatereturncode.c

       1  /*
           * Barrier Manager -- Translate SuperCore Status
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barriertranslatereturncode.c,  v 1.2 2007/11/30 21:49:40 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/barrier.h>
          
          /*
           * _Barrier_Translate_core_barrier_return_code
           *
           * Input parameters:
           * the_barrier_status - barrier status code to translate
           *
           * Output parameters:
           * rtems status code - translated RTEMS status code
           *
           */
          
          rtems_status_code _Barrier_Translate_core_barrier_return_code_[] = {
           RTEMS_SUCCESSFUL,   /* CORE_BARRIER_STATUS_SUCCESSFUL */
           RTEMS_SUCCESSFUL,   /* CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED */
           RTEMS_OBJECT_WAS_DELETED,   /* CORE_BARRIER_WAS_DELETED */
           RTEMS_TIMEOUT /* CORE_BARRIER_TIMEOUT */
          };
          
      41  rtems_status_code _Barrier_Translate_core_barrier_return_code (  
           CORE_barrier_Status the_barrier_status
           )
          {
           /*
           * Internal consistency check for bad status from SuperCore
           */
           #if defined(  RTEMS_DEBUG )
           if (   the_barrier_status > CORE_BARRIER_STATUS_LAST  )
           return RTEMS_INTERNAL_ERROR;
           #endif
           return _Barrier_Translate_core_barrier_return_code_[the_barrier_status];
          }

rtems/src/barrierwait.c

       1  /*
           * Barrier Manager -- Wait at a Barrier
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: barrierwait.c,  v 1.5 2009/01/06 05:05:02 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/barrier.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*
           * rtems_barrier_wait
           *
           * This directive allows a thread to wait at a barrier.
           *
           * Input parameters:
           * id - barrier id
           * timeout - number of ticks to wait (  0 means wait forever )
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      39  rtems_status_code rtems_barrier_wait(  
           rtems_id id,  
           rtems_interval timeout
           )
          {
           Barrier_Control *the_barrier;
           Objects_Locations location;
          
           the_barrier = _Barrier_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _CORE_barrier_Wait(  
           &the_barrier->Barrier,  
           id,  
           true,  
           timeout,  
           NULL
            );
           _Thread_Enable_dispatch(   );
           return _Barrier_Translate_core_barrier_return_code(  
           _Thread_Executing->Wait.return_code  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/clockget.c

       1  /*
           * Clock Manager
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockget.c,  v 1.11 2009/11/30 15:59:55 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*
           * rtems_clock_get
           *
           * This directive returns the current date and time. If the time has
           * not been set by a tm_set then an error is returned.
           *
           * Input parameters:
           * option - which value to return
           * time_buffer - pointer to output buffer (  a time and date structure
           * or an interval )
           *
           * Output parameters:
           * time_buffer - output filled in
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      43  rtems_status_code rtems_clock_get(  
           rtems_clock_get_options option,  
           void *time_buffer
           )
          {
           if (   !time_buffer  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   option == RTEMS_CLOCK_GET_TOD  )
           return rtems_clock_get_tod(   (  rtems_time_of_day * )time_buffer  );
          
           if (   option == RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH  )
           return rtems_clock_get_seconds_since_epoch(  (  rtems_interval * )time_buffer );
          
           if (   option == RTEMS_CLOCK_GET_TICKS_SINCE_BOOT  ) {
           rtems_interval *interval = (  rtems_interval * )time_buffer;
          
           *interval = rtems_clock_get_ticks_since_boot(   );
           return RTEMS_SUCCESSFUL;
           }
          
           if (   option == RTEMS_CLOCK_GET_TICKS_PER_SECOND  ) {
           rtems_interval *interval = (  rtems_interval * )time_buffer;
          
           *interval = rtems_clock_get_ticks_per_second(   );
           return RTEMS_SUCCESSFUL;
           }
          
           if (   option == RTEMS_CLOCK_GET_TIME_VALUE  )
           return rtems_clock_get_tod_timeval(   (  struct timeval * )time_buffer  );
          
           return RTEMS_INVALID_NUMBER;
          
          }

rtems/src/clockgetsecondssinceepoch.c

       1  /*
           * Clock Manager - Get Seconds Since Epoch
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockgetsecondssinceepoch.c,  v 1.2 2008/12/08 19:41:30 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
      26  rtems_status_code rtems_clock_get_seconds_since_epoch(  
           rtems_interval *the_interval
           )
          {
           if (   !the_interval  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !_TOD_Is_set  )
           return RTEMS_NOT_DEFINED;
          
           *the_interval = _TOD_Seconds_since_epoch(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/clockgettickspersecond.c

       1  /*
           * Clock Manager - Get Ticks Per Second
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockgettickspersecond.c,  v 1.2 2008/12/16 17:35:59 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
      27  rtems_interval rtems_clock_get_ticks_per_second(  void )
          {
           return TOD_MICROSECONDS_PER_SECOND /
           rtems_configuration_get_microseconds_per_tick(   );
          }

rtems/src/clockgettickssinceboot.c

       1  /*
           * Clock Manager - Get Ticks Since Boot
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockgettickssinceboot.c,  v 1.1 2008/03/11 20:07:49 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
      26  rtems_interval rtems_clock_get_ticks_since_boot(  void )
          {
           return _Watchdog_Ticks_since_boot;
          }

rtems/src/clockgettod.c

       1  /*
           * Clock Manager - rtems_clock_get_tod
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockgettod.c,  v 1.3 2009/11/30 15:59:55 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
      27  rtems_status_code rtems_clock_get_tod(  
           rtems_time_of_day *time_buffer
           )
          {
           rtems_time_of_day *tmbuf = time_buffer;
           struct tm time;
           struct timeval now;
          
           if (   !time_buffer  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !_TOD_Is_set  )
           return RTEMS_NOT_DEFINED;
          
           /* Obtain the current time */
           _TOD_Get_timeval(   &now  );
          
           /* Split it into a closer format */
           gmtime_r(   &now.tv_sec,   &time  );
          
           /* Now adjust it to the RTEMS format */
           tmbuf->year = time.tm_year + 1900;
           tmbuf->month = time.tm_mon + 1;
           tmbuf->day = time.tm_mday;
           tmbuf->hour = time.tm_hour;
           tmbuf->minute = time.tm_min;
           tmbuf->second = time.tm_sec;
           tmbuf->ticks = now.tv_usec /
           rtems_configuration_get_microseconds_per_tick(   );
          
           return RTEMS_SUCCESSFUL;
          }

rtems/src/clockgettodtimeval.c

       1  /*
           * Clock Manager - Get TOD in Time Value Format
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockgettodtimeval.c,  v 1.1 2008/03/11 20:07:49 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
      26  rtems_status_code rtems_clock_get_tod_timeval(  
           struct timeval *time
           )
          {
           if (   !time  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !_TOD_Is_set  )
           return RTEMS_NOT_DEFINED;
          
           _TOD_Get_timeval(   time  );
          
           return RTEMS_SUCCESSFUL;
          }

rtems/src/clockgetuptime.c

       1  /*
           * Clock Manager - get uptime
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockgetuptime.c,  v 1.3 2009/11/30 15:59:55 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/timestamp.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_clock_get_uptime
           *
           * This directive obtains the system uptime. A timestamp is the seconds
           * and nanoseconds since boot.
           *
           * Input parameters:
           * timestamp - pointer to the timestamp
           *
           * Output parameters:
           * *uptime - filled in
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
      42  rtems_status_code rtems_clock_get_uptime(  
           struct timespec *uptime
           )
          {
           if (   !uptime  )
           return RTEMS_INVALID_ADDRESS;
          
           _TOD_Get_uptime_as_timespec(   uptime  );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/clockset.c

       1  /*
           * Clock Manager
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clockset.c,  v 1.8 2009/11/30 15:59:55 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_clock_set
           *
           * This directive sets the date and time for this node.
           *
           * Input parameters:
           * time_buffer - pointer to the time and date structure
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      41  rtems_status_code rtems_clock_set(  
           rtems_time_of_day *time_buffer
           )
          {
           struct timespec newtime;
          
           if (   !time_buffer  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   _TOD_Validate(   time_buffer  )  ) {
           newtime.tv_sec = _TOD_To_seconds(   time_buffer  );
           newtime.tv_nsec = time_buffer->ticks *
           rtems_configuration_get_nanoseconds_per_tick(   );
          
           _Thread_Disable_dispatch(   );
           _TOD_Set(   &newtime  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           return RTEMS_INVALID_CLOCK;
          }

rtems/src/clocksetnsecshandler.c

       1  /*
           * Clock Manager
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clocksetnsecshandler.c,  v 1.1 2007/03/28 19:56:14 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_clock_set_nanoseconds_extension
           *
           * This directive sets the BSP provided nanoseconds since last tick
           * extension.
           *
           * Input parameters:
           * routine - pointer to the extension routine
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
      40  rtems_status_code rtems_clock_set_nanoseconds_extension(  
           rtems_nanoseconds_extension_routine routine
           )
          {
           if (   !routine  )
           return RTEMS_INVALID_ADDRESS;
          
           _Watchdog_Nanoseconds_since_tick_handler = routine;
           return RTEMS_SUCCESSFUL;
          }

rtems/src/clocktick.c

       1  /*
           * Clock Manager
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clocktick.c,  v 1.4 2005/01/18 09:03:43 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_clock_tick
           *
           * This directive notifies the executve that a tick has occurred.
           * When the tick occurs the time manager updates and maintains
           * the calendar time,   timeslicing,   and any timeout delays.
           *
           * Input parameters: NONE
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - always succeeds
           *
           * NOTE: This routine only works for leap-years through 2099.
           */
          
      42  rtems_status_code rtems_clock_tick(   void  )
          {
           _TOD_Tickle_ticks(   );
          
           _Watchdog_Tickle_ticks(   );
          
           _Thread_Tickle_timeslice(   );
          
           if (   _Thread_Is_context_switch_necessary(   ) &&
           _Thread_Is_dispatching_enabled(   )  )
           _Thread_Dispatch(   );
          
           return RTEMS_SUCCESSFUL;
          }

rtems/src/clocktodtoseconds.c

       1  /*
           * Time of Day (  TOD ) Handler - Classic TOD to Seconds
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clocktodtoseconds.c,  v 1.9 2009/05/04 11:09:05 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/clock.h>
          
          /*
           * The following array contains the number of days in all months
           * up to the month indicated by the index of the second dimension.
           * The first dimension should be 1 for leap years,   and 0 otherwise.
           */
          const uint16_t _TOD_Days_to_date[2][13] = {
           { 0,   0,   31,   59,   90,   120,   151,   181,   212,   243,   273,   304,   334 },  
           { 0,   0,   31,   60,   91,   121,   152,   182,   213,   244,   274,   305,   335 }
          };
          
          /*
           * The following array contains the number of days in the years
           * since the last leap year. The index should be 0 for leap
           * years,   and the number of years since the beginning of a leap
           * year otherwise.
           */
          const uint16_t _TOD_Days_since_last_leap_year[4] = { 0,   366,   731,   1096 };
          
          
          
          /*PAGE
           *
           * _TOD_To_seconds
           *
           * This routine returns the seconds from the epoch until the
           * current date and time.
           *
           * Input parameters:
           * the_tod - pointer to the time and date structure
           *
           * Output parameters:
           * returns - seconds since epoch until the_tod
           */
          
      55  uint32_t _TOD_To_seconds(  
           const rtems_time_of_day *the_tod
           )
          {
           uint32_t time;
           uint32_t year_mod_4;
          
           time = the_tod->day - 1;
           year_mod_4 = the_tod->year & 3;
          
           if (   year_mod_4 == 0  )
           time += _TOD_Days_to_date[ 1 ][ the_tod->month ];
           else
           time += _TOD_Days_to_date[ 0 ][ the_tod->month ];
          
           time += (   (  the_tod->year - TOD_BASE_YEAR ) / 4  ) *
           (   (  TOD_DAYS_PER_YEAR * 4 ) + 1 );
          
           time += _TOD_Days_since_last_leap_year[ year_mod_4 ];
          
           time *= TOD_SECONDS_PER_DAY;
          
           time += (  (  the_tod->hour * TOD_MINUTES_PER_HOUR ) + the_tod->minute )
           * TOD_SECONDS_PER_MINUTE;
          
           time += the_tod->second;
          
           time += TOD_SECONDS_1970_THROUGH_1988;
          
           return(   time  );
          }

rtems/src/clocktodvalidate.c

       1  /*
           * Time of Day (  TOD ) Handler -- Validate Classic TOD
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: clocktodvalidate.c,  v 1.14 2009/11/30 15:59:55 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/clock.h>
          
          /*
           * The following array contains the number of days in all months.
           * The first dimension should be 1 for leap years,   and 0 otherwise.
           * The second dimension should range from 1 to 12 for January to
           * February,   respectively.
           */
          const uint32_t _TOD_Days_per_month[ 2 ][ 13 ] = {
           { 0,   31,   28,   31,   30,   31,   30,   31,   31,   30,   31,   30,   31 },  
           { 0,   31,   29,   31,   30,   31,   30,   31,   31,   30,   31,   30,   31 }
          };
          
          /*PAGE
           *
           * _TOD_Validate
           *
           * This kernel routine checks the validity of a date and time structure.
           *
           * Input parameters:
           * the_tod - pointer to a time and date structure
           *
           * Output parameters:
           * true - if the date,   time,   and tick are valid
           * false - if the the_tod is invalid
           *
           * NOTE: This routine only works for leap-years through 2099.
           */
          
      50  bool _TOD_Validate(  
           const rtems_time_of_day *the_tod
           )
          {
           uint32_t days_in_month;
           uint32_t ticks_per_second;
          
           ticks_per_second = TOD_MICROSECONDS_PER_SECOND /
           rtems_configuration_get_microseconds_per_tick(   );
           if (  (  !the_tod ) ||
           (  the_tod->ticks >= ticks_per_second ) ||
           (  the_tod->second >= TOD_SECONDS_PER_MINUTE ) ||
           (  the_tod->minute >= TOD_MINUTES_PER_HOUR ) ||
           (  the_tod->hour >= TOD_HOURS_PER_DAY ) ||
           (  the_tod->month == 0 ) ||
           (  the_tod->month > TOD_MONTHS_PER_YEAR ) ||
           (  the_tod->year < TOD_BASE_YEAR ) ||
           (  the_tod->day == 0 )  )
           return false;
          
           if (   (  the_tod->year % 4 ) == 0  )
           days_in_month = _TOD_Days_per_month[ 1 ][ the_tod->month ];
           else
           days_in_month = _TOD_Days_per_month[ 0 ][ the_tod->month ];
          
           if (   the_tod->day > days_in_month  )
           return false;
          
           return true;
          }

rtems/src/dpmem.c

       1  /*
           * Dual Port Memory Manager
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: dpmem.c,  v 1.21 2009/01/06 05:05:02 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/rtems/dpmem.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * _Dual_ported_memory_Manager_initialization
           *
           * This routine initializes all dual-ported memory manager related
           * data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      39  void _Dual_ported_memory_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_Dual_ported_memory_Information,   /* object information table */
           OBJECTS_CLASSIC_API,   /* object API */
           OBJECTS_RTEMS_PORTS,   /* object class */
           Configuration_RTEMS_API.maximum_ports,  
           /* maximum objects of this class */
           sizeof(   Dual_ported_memory_Control  ),  
           /* size of this object's control block */
           false,   /* true if names of this object are strings */
           RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

rtems/src/dpmemcreate.c

       1  /*
           * Dual Port Memory Manager
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: dpmemcreate.c,  v 1.11 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/rtems/dpmem.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/dpmem.h>
          
          /*PAGE
           *
           * rtems_port_create
           *
           * This directive creates a port into a dual-ported memory area.
           *
           * Input parameters:
           * name - user defined port name
           * internal_start - internal start address of port
           * external_start - external start address of port
           * length - physical length in bytes
           * id - address of port id to set
           *
           * Output parameters:
           * id - port id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      46  rtems_status_code rtems_port_create(  
           rtems_name name,  
           void *internal_start,  
           void *external_start,  
           uint32_t length,  
           rtems_id *id
           )
          {
           register Dual_ported_memory_Control *the_port;
          
           if (   !rtems_is_name_valid(   name  )  )
           return RTEMS_INVALID_NAME;
          
           if (   !id  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !_Addresses_Is_aligned(   internal_start  ) ||
           !_Addresses_Is_aligned(   external_start  )  )
           return RTEMS_INVALID_ADDRESS;
          
           _Thread_Disable_dispatch(   ); /* to prevent deletion */
          
           the_port = _Dual_ported_memory_Allocate(   );
          
           if (   !the_port  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_TOO_MANY;
           }
          
           the_port->internal_base = internal_start;
           the_port->external_base = external_start;
           the_port->length = length - 1;
          
           _Objects_Open(  
           &_Dual_ported_memory_Information,  
           &the_port->Object,  
           (  Objects_Name ) name
            );
          
           *id = the_port->Object.id;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/dpmemdata.c

       1  /*
           * Dual Port Memory Manager -- Instantiate Data
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: dpmemdata.c,  v 1.1 2007/05/21 23:19:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate semaphore data */
          #define RTEMS_DPMEM_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/rtems/dpmem.h>

rtems/src/dpmemdelete.c

       1  /*
           * Dual Port Memory Manager
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: dpmemdelete.c,  v 1.7 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/rtems/dpmem.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/dpmem.h>
          
          /*PAGE
           *
           * rtems_port_delete
           *
           * This directive allows a thread to delete a dual-ported memory area
           * specified by the dual-ported memory identifier.
           *
           * Input parameters:
           * id - dual-ported memory area id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      42  rtems_status_code rtems_port_delete(  
           rtems_id id
           )
          {
           register Dual_ported_memory_Control *the_port;
           Objects_Locations location;
          
           the_port = _Dual_ported_memory_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _Objects_Close(   &_Dual_ported_memory_Information,   &the_port->Object  );
           _Dual_ported_memory_Free(   the_port  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* this error cannot be returned */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/dpmemexternal2internal.c

       1  /*
           * Dual Port Memory Manager
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: dpmemexternal2internal.c,  v 1.9 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/rtems/dpmem.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/dpmem.h>
          
          /*PAGE
           *
           * rtems_port_external_to_internal
           *
           * This directive converts an external dual-ported memory address to an
           * internal dual-ported memory address. If the given external address
           * is an invalid dual-ported address,   then the internal address is set
           * to the given external address.
           *
           * Input parameters:
           * id - id of dp memory object
           * external - external address
           * internal - pointer of internal address to set
           *
           * Output parameters:
           * internal - internal address
           * RTEMS_SUCCESSFUL - always succeeds
           */
          
      46  rtems_status_code rtems_port_external_to_internal(  
           rtems_id id,  
           void *external,  
           void **internal
           )
          {
           register Dual_ported_memory_Control *the_port;
           Objects_Locations location;
           uint32_t ending;
          
           if (   !internal  )
           return RTEMS_INVALID_ADDRESS;
          
           the_port = _Dual_ported_memory_Get(   id,   &location  );
           switch (   location  ) {
           case OBJECTS_LOCAL:
           ending = _Addresses_Subtract(   external,   the_port->external_base  );
           if (   ending > the_port->length  )
           *internal = external;
           else
           *internal = _Addresses_Add_offset(   the_port->internal_base,  
           ending  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* this error cannot be returned */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/dpmemident.c

       1  /*
           * Dual Port Memory Manager
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: dpmemident.c,  v 1.9 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/rtems/dpmem.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/dpmem.h>
          
          /*PAGE
           *
           * rtems_port_ident
           *
           * This directive returns the system ID associated with
           * the port name.
           *
           * Input parameters:
           * name - user defined port name
           * id - pointer to port id
           *
           * Output parameters:
           * *id - port id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      44  rtems_status_code rtems_port_ident(  
           rtems_name name,  
           rtems_id *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
          
           status = _Objects_Name_to_id_u32(  
           &_Dual_ported_memory_Information,  
           name,  
           OBJECTS_SEARCH_ALL_NODES,  
           id
            );
          
           return _Status_Object_name_errors_to_status[ status ];
          }

rtems/src/dpmeminternal2external.c

       1  /*
           * Dual Port Memory Manager
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: dpmeminternal2external.c,  v 1.9 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/rtems/dpmem.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/dpmem.h>
          
          /*PAGE
           *
           * rtems_port_internal_to_external
           *
           * This directive converts an internal dual-ported memory address to an
           * external dual-ported memory address. If the given internal address
           * is an invalid dual-ported address,   then the external address is set
           * to the given internal address.
           *
           * Input parameters:
           * id - id of dual-ported memory object
           * internal - internal address to set
           * external - pointer to external address
           *
           * Output parameters:
           * external - external address
           * RTEMS_SUCCESSFUL - always succeeds
           */
          
      46  rtems_status_code rtems_port_internal_to_external(  
           rtems_id id,  
           void *internal,  
           void **external
           )
          {
           register Dual_ported_memory_Control *the_port;
           Objects_Locations location;
           uint32_t ending;
          
           if (   !external  )
           return RTEMS_INVALID_ADDRESS;
          
           the_port = _Dual_ported_memory_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           ending = _Addresses_Subtract(   internal,   the_port->internal_base  );
           if (   ending > the_port->length  )
           *external = internal;
           else
           *external = _Addresses_Add_offset(   the_port->external_base,  
           ending  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* this error cannot be returned */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/event.c

       1  /*
           * Event Manager
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: event.c,  v 1.24 2008/01/22 18:28:53 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/event.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/tasks.h>
          
          /*PAGE
           *
           * _Event_Manager_initialization
           *
           * DESCRIPTION:
           *
           * This routine performs the initialization necessary for this manager.
           */
          
      37  void _Event_Manager_initialization(   void  )
          {
           _Event_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
          
           /*
           * Register the MP Process Packet routine.
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
           _MPCI_Register_packet_processor(   MP_PACKET_EVENT,   _Event_MP_Process_packet  );
          #endif
          }

rtems/src/eventdata.c

       1  /*
           * Event Manager -- Instantiate Data
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: eventdata.c,  v 1.1 2007/05/21 23:19:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate RTEMS event data */
          #define RTEMS_EVENT_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/rtems/event.h>

rtems/src/eventmp.c

       1  /*
           * Multiprocessing Support for the Event Manager
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: eventmp.c,  v 1.14 2008/01/29 21:52:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/event.h>
          #include <rtems/score/mpci.h>
          #include <rtems/score/mppkt.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * _Event_MP_Send_process_packet
           *
           * This subprogram is not needed since there are no process
           * packets to be sent by this manager.
           *
           */
          
          /*PAGE
           *
           * _Event_MP_Send_request_packet
           *
           */
          
      44  rtems_status_code _Event_MP_Send_request_packet (  
           Event_MP_Remote_operations operation,  
           Objects_Id event_id,  
           rtems_event_set event_in
           )
          {
           Event_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case EVENT_MP_SEND_REQUEST:
          
           the_packet = _Event_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_EVENT;
           the_packet->Prefix.length = sizeof (   Event_MP_Packet  );
           the_packet->Prefix.to_convert = sizeof (   Event_MP_Packet  );
           the_packet->operation = operation;
           the_packet->Prefix.id = event_id;
           the_packet->event_in = event_in;
          
           return (  rtems_status_code )
           _MPCI_Send_request_packet(  
           _Objects_Get_node(   event_id  ),  
           &the_packet->Prefix,  
           STATES_READY
            );
          
           break;
          
           case EVENT_MP_SEND_RESPONSE:
           break;
          
           }
           /*
           * The following line is included to satisfy compilers which
           * produce warnings when a function does not end with a return.
           */
           return RTEMS_SUCCESSFUL;
          }
          
          /*PAGE
           *
           * _Event_MP_Send_response_packet
           *
           */
          
      90  void _Event_MP_Send_response_packet (  
           Event_MP_Remote_operations operation,  
           Thread_Control *the_thread
           )
          {
           Event_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case EVENT_MP_SEND_RESPONSE:
          
           the_packet = (   Event_MP_Packet * ) the_thread->receive_packet;
          
          /*
           * The packet being returned already contains the class,   length,   and
           * to_convert fields,   therefore they are not set in this routine.
           */
           the_packet->operation = operation;
           the_packet->Prefix.id = the_packet->Prefix.source_tid;
          
           _MPCI_Send_response_packet(  
           _Objects_Get_node(   the_packet->Prefix.source_tid  ),  
           &the_packet->Prefix
            );
           break;
          
           case EVENT_MP_SEND_REQUEST:
           break;
          
           }
          }
          
          /*PAGE
           *
           *
           * _Event_MP_Process_packet
           *
           */
          
     129  void _Event_MP_Process_packet (  
           rtems_packet_prefix *the_packet_prefix
           )
          {
           Event_MP_Packet *the_packet;
           Thread_Control *the_thread;
          
           the_packet = (  Event_MP_Packet * ) the_packet_prefix;
          
           switch (   the_packet->operation  ) {
          
           case EVENT_MP_SEND_REQUEST:
          
           the_packet->Prefix.return_code = rtems_event_send(  
           the_packet->Prefix.id,  
           the_packet->event_in
            );
          
           _Event_MP_Send_response_packet(  
           EVENT_MP_SEND_RESPONSE,  
           _Thread_Executing
            );
           break;
          
           case EVENT_MP_SEND_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
          
           break;
          
           }
          }
          
          /*PAGE
           *
           * _Event_MP_Send_object_was_deleted
           *
           * This subprogram is not needed since there are no objects
           * deleted by this manager.
           *
           */
          
          /*PAGE
           *
           * _Event_MP_Send_extract_proxy
           *
           * This subprogram is not needed since there are no objects
           * deleted by this manager.
           *
           */
          
          /*PAGE
           *
           * _Event_MP_Get_packet
           *
           */
          
     188  Event_MP_Packet *_Event_MP_Get_packet (   void  )
          {
           return (   (  Event_MP_Packet * ) _MPCI_Get_packet(   )  );
          }
          
          /* end of file */

rtems/src/eventreceive.c

       1  /*
           * Event Manager
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: eventreceive.c,  v 1.5 2005/01/18 09:03:43 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/event.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/tasks.h>
          
          /*PAGE
           *
           * rtems_event_receive
           *
           * This directive allows a thread to receive a set of events.
           *
           * Input parameters:
           * event_in - input event condition
           * option_set - options
           * ticks - number of ticks to wait (  0 means wait forever )
           * event_out - pointer to output event set
           *
           * Output parameters:
           * event out - event set
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      46  rtems_status_code rtems_event_receive(  
           rtems_event_set event_in,  
           rtems_option option_set,  
           rtems_interval ticks,  
           rtems_event_set *event_out
           )
          {
           RTEMS_API_Control *api;
          
           if (   !event_out  )
           return RTEMS_INVALID_ADDRESS;
          
           api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
          
           if (   _Event_sets_Is_empty(   event_in  )  ) {
           *event_out = api->pending_events;
           return RTEMS_SUCCESSFUL;
           }
          
           _Thread_Disable_dispatch(   );
           _Event_Seize(   event_in,   option_set,   ticks,   event_out  );
           _Thread_Enable_dispatch(   );
           return(   _Thread_Executing->Wait.return_code  );
          }

rtems/src/eventseize.c

       1  /*
           * Event Manager
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: eventseize.c,  v 1.9 2009/07/21 23:09:07 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/event.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/tasks.h>
          
          /*PAGE
           *
           * _Event_Seize
           *
           * This routine attempts to satisfy the requested event condition
           * for the running thread.
           *
           * Input parameters:
           * event_in - the event condition to satisfy
           * option_set - acquire event options
           * ticks - interval to wait
           * event_out - pointer to event set output area
           *
           * Output parameters: NONE
           * *event_out - event set output area filled in
           *
           * INTERRUPT LATENCY:
           * available
           * wait
           * check sync
           */
          
      50  void _Event_Seize(  
           rtems_event_set event_in,  
           rtems_option option_set,  
           rtems_interval ticks,  
           rtems_event_set *event_out
           )
          {
           Thread_Control *executing;
           rtems_event_set seized_events;
           rtems_event_set pending_events;
           ISR_Level level;
           RTEMS_API_Control *api;
           Thread_blocking_operation_States sync_state;
          
           executing = _Thread_Executing;
           executing->Wait.return_code = RTEMS_SUCCESSFUL;
          
           api = executing->API_Extensions[ THREAD_API_RTEMS ];
          
           _ISR_Disable(   level  );
           pending_events = api->pending_events;
           seized_events = _Event_sets_Get(   pending_events,   event_in  );
          
           if (   !_Event_sets_Is_empty(   seized_events  ) &&
           (  seized_events == event_in || _Options_Is_any(   option_set  ) )  ) {
           api->pending_events =
           _Event_sets_Clear(   pending_events,   seized_events  );
           _ISR_Enable(   level  );
           *event_out = seized_events;
           return;
           }
          
           if (   _Options_Is_no_wait(   option_set  )  ) {
           _ISR_Enable(   level  );
           executing->Wait.return_code = RTEMS_UNSATISFIED;
           *event_out = seized_events;
           return;
           }
          
           /*
           * Note what we are waiting for BEFORE we enter the critical section.
           * The interrupt critical section management code needs this to be
           * set properly when we are marked as in the event critical section.
           *
           * NOTE: Since interrupts are disabled,   this isn't that much of an
           * issue but better safe than sorry.
           */
           executing->Wait.option = (  uint32_t ) option_set;
           executing->Wait.count = (  uint32_t ) event_in;
           executing->Wait.return_argument = event_out;
          
           _Event_Sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
          
           _ISR_Enable(   level  );
          
           if (   ticks  ) {
           _Watchdog_Initialize(  
           &executing->Timer,  
           _Event_Timeout,  
           executing->Object.id,  
           NULL
            );
           _Watchdog_Insert_ticks(   &executing->Timer,   ticks  );
           }
          
           _Thread_Set_state(   executing,   STATES_WAITING_FOR_EVENT  );
          
           _ISR_Disable(   level  );
          
           sync_state = _Event_Sync_state;
           _Event_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
           if (   sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED  ) {
           _ISR_Enable(   level  );
           return;
           }
          
           /*
           * An interrupt completed the thread's blocking request.
           * The blocking thread was satisfied by an ISR or timed out.
           *
           * WARNING! Returning with interrupts disabled!
           */
           _Thread_blocking_operation_Cancel(   sync_state,   executing,   level  );
          }

rtems/src/eventsend.c

       1  /*
           * Event Manager
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: eventsend.c,  v 1.8 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/event.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/tasks.h>
          
          /*PAGE
           *
           * rtems_event_send
           *
           * This directive allows a thread send an event set to another thread.
           *
           * Input parameters:
           * id - thread id
           * event - event set
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      43  rtems_status_code rtems_event_send(  
           rtems_id id,  
           rtems_event_set event_in
           )
          {
           register Thread_Control *the_thread;
           Objects_Locations location;
           RTEMS_API_Control *api;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
           _Event_sets_Post(   event_in,   &api->pending_events  );
           _Event_Surrender(   the_thread  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           return(  
           _Event_MP_Send_request_packet(  
           EVENT_MP_SEND_REQUEST,  
           id,  
           event_in
            )
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/eventsurrender.c

       1  /*
           * Event Manager
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: eventsurrender.c,  v 1.12 2009/11/30 15:59:55 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/event.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/tasks.h>
          
          /*PAGE
           *
           * _Event_Surrender
           *
           * This routines remove a thread from the specified threadq.
           *
           * Input parameters:
           * the_thread - pointer to thread to be dequeued
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * before flash
           * after flash
           * check sync
           */
          
      45  void _Event_Surrender(  
           Thread_Control *the_thread
           )
          {
           ISR_Level level;
           rtems_event_set pending_events;
           rtems_event_set event_condition;
           rtems_event_set seized_events;
           rtems_option option_set;
           RTEMS_API_Control *api;
          
           api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
          
           option_set = (  rtems_option ) the_thread->Wait.option;
          
           _ISR_Disable(   level  );
           pending_events = api->pending_events;
           event_condition = (  rtems_event_set ) the_thread->Wait.count;
          
           seized_events = _Event_sets_Get(   pending_events,   event_condition  );
          
           /*
           * No events were seized in this operation
           */
           if (   _Event_sets_Is_empty(   seized_events  )  ) {
           _ISR_Enable(   level  );
           return;
           }
          
           /*
           * If we are in an ISR and sending to the current thread,   then
           * we have a critical section issue to deal with.
           */
           if (   _ISR_Is_in_progress(   ) &&
           _Thread_Is_executing(   the_thread  ) &&
           (  (  _Event_Sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT ) ||
           (  _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) )  ) {
           if (   seized_events == event_condition || _Options_Is_any(  option_set )  ) {
           api->pending_events = _Event_sets_Clear(   pending_events,  seized_events  );
           the_thread->Wait.count = 0;
           *(  rtems_event_set * )the_thread->Wait.return_argument = seized_events;
           _Event_Sync_state = THREAD_BLOCKING_OPERATION_SATISFIED;
           }
           _ISR_Enable(   level  );
           return;
           }
          
           /*
           * Otherwise,   this is a normal send to another thread
           */
           if (   _States_Is_waiting_for_event(   the_thread->current_state  )  ) {
           if (   seized_events == event_condition || _Options_Is_any(   option_set  )  ) {
           api->pending_events = _Event_sets_Clear(   pending_events,   seized_events  );
           the_thread->Wait.count = 0;
           *(  rtems_event_set * )the_thread->Wait.return_argument = seized_events;
          
           _ISR_Flash(   level  );
          
           if (   !_Watchdog_Is_active(   &the_thread->Timer  )  ) {
           _ISR_Enable(   level  );
           _Thread_Unblock(   the_thread  );
           } else {
           _Watchdog_Deactivate(   &the_thread->Timer  );
           _ISR_Enable(   level  );
           (  void ) _Watchdog_Remove(   &the_thread->Timer  );
           _Thread_Unblock(   the_thread  );
           }
           return;
           }
           }
           _ISR_Enable(   level  );
          }

rtems/src/eventtimeout.c

       1  /*
           * Event Manager
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: eventtimeout.c,  v 1.11 2009/07/21 23:09:07 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/event.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/tasks.h>
          
          /*PAGE
           *
           * _Event_Timeout
           *
           * This routine processes a thread which timeouts while waiting to
           * receive an event_set. It is called by the watchdog handler.
           *
           * Input parameters:
           * id - thread id
           *
           * Output parameters: NONE
           */
          
      41  void _Event_Timeout(  
           Objects_Id id,  
           void *ignored
           )
          {
           Thread_Control *the_thread;
           Objects_Locations location;
           ISR_Level level;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           /*
           * If the event manager is not synchronized,   then it is either
           * "nothing happened",   "timeout",   or "satisfied". If the_thread
           * is the executing thread,   then it is in the process of blocking
           * and it is the thread which is responsible for the synchronization
           * process.
           *
           * If it is not satisfied,   then it is "nothing happened" and
           * this is the "timeout" transition. After a request is satisfied,  
           * a timeout is not allowed to occur.
           */
           _ISR_Disable(   level  );
           #if defined(  RTEMS_DEBUG )
           if (   !the_thread->Wait.count  ) { /* verify thread is waiting */
           _Thread_Unnest_dispatch(   );
           _ISR_Enable(   level  );
           return;
           }
           #endif
          
           the_thread->Wait.count = 0;
           if (   _Thread_Is_executing(   the_thread  )  ) {
           if (   _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED  )
           _Event_Sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT;
           }
          
           the_thread->Wait.return_code = RTEMS_TIMEOUT;
           _ISR_Enable(   level  );
           _Thread_Unblock(   the_thread  );
           _Thread_Unnest_dispatch(   );
           break;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* impossible */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          }

rtems/src/intrbody.c

       1  /*
           * Bodies for Inlined Interrupt Manager Routines
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: intrbody.c,  v 1.7 2008/09/04 17:45:00 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/score/isr.h>
          #include <rtems/rtems/intr.h>
          
          /*
           * Real body for rtems_interrupt_disable
           */
          
          #undef rtems_interrupt_disable
          
      30  rtems_interrupt_level rtems_interrupt_disable(   void  )
          {
           rtems_interrupt_level previous_level;
          
           _ISR_Disable(   previous_level  );
          
           return previous_level;
          }
          
          /*
           * Real body for rtems_interrupt_enable
           */
          
          #undef rtems_interrupt_enable
          
      45  void rtems_interrupt_enable(  
           rtems_interrupt_level previous_level
           )
          {
           _ISR_Enable(   previous_level  );
          }
          
          /*
           * Real body for rtems_interrupt_flash
           */
          
          #undef rtems_interrupt_flash
          
      58  void rtems_interrupt_flash(  
           rtems_interrupt_level previous_level
           )
          {
           _ISR_Flash(   previous_level  );
          }
          
          /*
           * Real body for rtems_interrupt_is_in_progress
           */
          
          #undef rtems_interrupt_is_in_progress
          
      71  bool rtems_interrupt_is_in_progress(   void  )
          {
           return _ISR_Is_in_progress(   );
          }

rtems/src/intrcatch.c

       1  /*
           * Interrupt Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: intrcatch.c,  v 1.5 2009/08/05 15:36:49 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/score/isr.h>
          #include <rtems/rtems/intr.h>
          
          #if (  CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE )
          
          /* rtems_interrupt_catch
           *
           * This directive allows a thread to specify what action to take when
           * catching signals.
           *
           * Input parameters:
           * new_isr_handler - address of interrupt service routine (  isr )
           * vector - interrupt vector number
           * old_isr_handler - address at which to store previous ISR address
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - always succeeds
           * *old_isr_handler - previous ISR address
           */
          
      41  rtems_status_code rtems_interrupt_catch(  
           rtems_isr_entry new_isr_handler,  
           rtems_vector_number vector,  
           rtems_isr_entry *old_isr_handler
           )
          {
           if (   !_ISR_Is_vector_number_valid(   vector  )  )
           return RTEMS_INVALID_NUMBER;
          
           if (   !_ISR_Is_valid_user_handler(   (  void * ) new_isr_handler  )  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !_ISR_Is_valid_user_handler(   (  void * ) old_isr_handler  )  )
           return RTEMS_INVALID_ADDRESS;
          
           _ISR_Install_vector(  
           vector,   (  proc_ptr )new_isr_handler,   (  proc_ptr * )old_isr_handler  );
          
           return RTEMS_SUCCESSFUL;
          }
          #endif

rtems/src/mp.c

       1  /*
           * Multiprocessing Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mp.c,  v 1.14 2005/01/18 09:03:43 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/mp.h>
          #include <rtems/score/mpci.h>
          
          /*PAGE
           *
           * _Multiprocessing_Manager_initialization
           *
           */
          
      30  void _Multiprocessing_Manager_initialization (   void  )
          {
          }
          
          /*PAGE
           *
           * rtems_multiprocessing_announce
           *
           */
          
      40  void rtems_multiprocessing_announce (   void  )
          {
           _MPCI_Announce(   );
          }
          
          /* end of file */

rtems/src/msg.c

       1  /*
           * Message Queue Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msg.c,  v 1.33 2009/11/30 15:59:55 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * _Message_queue_Manager_initialization
           *
           * This routine initializes all message queue manager related
           * data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      50  void _Message_queue_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_Message_queue_Information,   /* object information table */
           OBJECTS_CLASSIC_API,   /* object API */
           OBJECTS_RTEMS_MESSAGE_QUEUES,   /* object class */
           Configuration_RTEMS_API.maximum_message_queues,  
           /* maximum objects of this class */
           sizeof(   Message_queue_Control  ),  
           /* size of this object's control block */
           false,   /* true if names of this object are strings */
           RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           true,   /* true if this is a global object class */
           _Message_queue_MP_Send_extract_proxy
           /* Proxy extraction support callout */
          #endif
            );
          
           /*
           * Register the MP Process Packet routine.
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
           _MPCI_Register_packet_processor(  
           MP_PACKET_MESSAGE_QUEUE,  
           _Message_queue_MP_Process_packet
            );
          #endif
          
          }

rtems/src/msgdata.c

       1  /*
           * Barrier Manager -- Instantiate Data
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgdata.c,  v 1.1 2007/05/21 23:19:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate message queue data */
          #define RTEMS_MESSAGE_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/rtems/message.h>
          

rtems/src/msgmp.c

       1  /*
           * Multiprocessing Support for the Message Queue Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgmp.c,  v 1.27 2009/01/06 05:05:03 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/message.h>
          #include <rtems/score/mpci.h>
          #include <rtems/rtems/msgmp.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * _Message_queue_MP_Send_process_packet
           *
           */
          
      36  void _Message_queue_MP_Send_process_packet (  
           Message_queue_MP_Remote_operations operation,  
           Objects_Id message_queue_id,  
           rtems_name name,  
           Objects_Id proxy_id
           )
          {
           Message_queue_MP_Packet *the_packet;
           uint32_t node;
          
           switch (   operation  ) {
          
           case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
           case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
           case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
          
           the_packet = _Message_queue_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_MESSAGE_QUEUE;
           the_packet->Prefix.length = sizeof (   Message_queue_MP_Packet  );
           the_packet->Prefix.to_convert = sizeof (   Message_queue_MP_Packet  );
           the_packet->operation = operation;
           the_packet->Prefix.id = message_queue_id;
           the_packet->name = name;
           the_packet->proxy_id = proxy_id;
          
           if (   operation == MESSAGE_QUEUE_MP_EXTRACT_PROXY  )
           node = _Objects_Get_node(   message_queue_id  );
           else
           node = MPCI_ALL_NODES;
          
           _MPCI_Send_process_packet(   node,   &the_packet->Prefix  );
           break;
          
           case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
           case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
           case MESSAGE_QUEUE_MP_SEND_REQUEST:
           case MESSAGE_QUEUE_MP_SEND_RESPONSE:
           case MESSAGE_QUEUE_MP_URGENT_REQUEST:
           case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
           case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
           case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
           case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
           case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
           case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
           case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
           break;
          
           }
          }
          
          /*PAGE
           *
           * _Message_queue_MP_Send_request_packet
           *
           */
          
      92  rtems_status_code _Message_queue_MP_Send_request_packet (  
           Message_queue_MP_Remote_operations operation,  
           Objects_Id message_queue_id,  
           const void *buffer,  
           size_t *size_p,  
           rtems_option option_set,  
           rtems_interval timeout
           )
          {
           Message_queue_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case MESSAGE_QUEUE_MP_SEND_REQUEST:
           case MESSAGE_QUEUE_MP_URGENT_REQUEST:
           case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
           case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
           case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
          
           the_packet = _Message_queue_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_MESSAGE_QUEUE;
           the_packet->Prefix.length = sizeof(  Message_queue_MP_Packet );
           if (   size_p  )
           the_packet->Prefix.length += *size_p;
           the_packet->Prefix.to_convert = sizeof(  Message_queue_MP_Packet );
          
           /*
           * make sure message is not too big for our MPCI driver
           * We have to check it here instead of waiting for MPCI because
           * we are about to slam in the payload
           */
          
           if (  the_packet->Prefix.length > _MPCI_table->maximum_packet_size ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_INVALID_SIZE;
           }
          
           if (  ! _Options_Is_no_wait(  option_set ) )
           the_packet->Prefix.timeout = timeout;
          
           the_packet->operation = operation;
           the_packet->Prefix.id = message_queue_id;
           the_packet->option_set = option_set;
          
           /*
           * Copy the data into place if needed
           */
          
           if (  buffer ) {
           the_packet->Buffer.size = *size_p;
           _CORE_message_queue_Copy_buffer(  
           buffer,  
           the_packet->Buffer.buffer,  
           *size_p
            );
           }
          
           return (  rtems_status_code ) _MPCI_Send_request_packet(  
           _Objects_Get_node(  message_queue_id ),  
           &the_packet->Prefix,  
           STATES_WAITING_FOR_MESSAGE
            );
           break;
          
           case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
          
           the_packet = _Message_queue_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_MESSAGE_QUEUE;
           the_packet->Prefix.length = sizeof(  Message_queue_MP_Packet );
           the_packet->Prefix.to_convert = sizeof(  Message_queue_MP_Packet );
          
           if (  ! _Options_Is_no_wait(  option_set ) )
           the_packet->Prefix.timeout = timeout;
          
           the_packet->operation = MESSAGE_QUEUE_MP_RECEIVE_REQUEST;
           the_packet->Prefix.id = message_queue_id;
           the_packet->option_set = option_set;
           the_packet->size = 0; /* just in case of an error */
          
           _Thread_Executing->Wait.return_argument_second.immutable_object = buffer;
           _Thread_Executing->Wait.return_argument = size_p;
          
           return (  rtems_status_code ) _MPCI_Send_request_packet(  
           _Objects_Get_node(  message_queue_id ),  
           &the_packet->Prefix,  
           STATES_WAITING_FOR_MESSAGE
            );
           break;
          
           case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
           case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
           case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
           case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
           case MESSAGE_QUEUE_MP_SEND_RESPONSE:
           case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
           case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
           case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
           case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
           break;
           }
          
           return RTEMS_SUCCESSFUL;
          }
          
          /*PAGE
           *
           * _Message_queue_MP_Send_response_packet
           *
           */
          
     202  void _Message_queue_MP_Send_response_packet (  
           Message_queue_MP_Remote_operations operation,  
           Objects_Id message_queue_id,  
           Thread_Control *the_thread
           )
          {
           Message_queue_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
           case MESSAGE_QUEUE_MP_SEND_RESPONSE:
           case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
           case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
           case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
           case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
          
           the_packet = (   Message_queue_MP_Packet * ) the_thread->receive_packet;
          
          /*
           * The packet being returned already contains the class,   length,   and
           * to_convert fields,   therefore they are not set in this routine.
           *
           * Exception: MESSAGE_QUEUE_MP_RECEIVE_RESPONSE needs payload length
           * added to 'length'
           */
           the_packet->operation = operation;
           the_packet->Prefix.id = the_packet->Prefix.source_tid;
          
           if (  operation == MESSAGE_QUEUE_MP_RECEIVE_RESPONSE )
           the_packet->Prefix.length += the_packet->size;
          
           _MPCI_Send_response_packet(  
           _Objects_Get_node(   the_packet->Prefix.source_tid  ),  
           &the_packet->Prefix
            );
           break;
          
           case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
           case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
           case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
           case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
           case MESSAGE_QUEUE_MP_SEND_REQUEST:
           case MESSAGE_QUEUE_MP_URGENT_REQUEST:
           case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
           case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
           case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
           break;
          
           }
          }
          
          /*PAGE
           *
           *
           * _Message_queue_MP_Process_packet
           *
           */
          
     261  void _Message_queue_MP_Process_packet (  
           rtems_packet_prefix *the_packet_prefix
           )
          {
           Message_queue_MP_Packet *the_packet;
           Thread_Control *the_thread;
           bool ignored;
          
           the_packet = (  Message_queue_MP_Packet * ) the_packet_prefix;
          
           switch (   the_packet->operation  ) {
          
           case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
          
           ignored = _Objects_MP_Allocate_and_open(  
           &_Message_queue_Information,  
           the_packet->name,  
           the_packet->Prefix.id,  
           true
            );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
          
           _Objects_MP_Close(   &_Message_queue_Information,   the_packet->Prefix.id  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
          
           the_thread = _Thread_MP_Find_proxy(   the_packet->proxy_id  );
          
           if (  ! _Thread_Is_null(   the_thread  )  )
           _Thread_queue_Extract(   the_thread->Wait.queue,   the_thread  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
          
           the_packet->Prefix.return_code = rtems_message_queue_receive(  
           the_packet->Prefix.id,  
           the_packet->Buffer.buffer,  
           &the_packet->size,  
           the_packet->option_set,  
           the_packet->Prefix.timeout
            );
          
           if (   the_packet->Prefix.return_code != RTEMS_PROXY_BLOCKING  )
           _Message_queue_MP_Send_response_packet(  
           MESSAGE_QUEUE_MP_RECEIVE_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
          
           case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           if (  the_packet->Prefix.return_code == RTEMS_SUCCESSFUL ) {
           *(  size_t * ) the_thread->Wait.return_argument =
           the_packet->size;
          
           _CORE_message_queue_Copy_buffer(  
           the_packet->Buffer.buffer,  
           the_thread->Wait.return_argument_second.mutable_object,  
           the_packet->size
            );
           }
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case MESSAGE_QUEUE_MP_SEND_REQUEST:
          
           the_packet->Prefix.return_code = rtems_message_queue_send(  
           the_packet->Prefix.id,  
           the_packet->Buffer.buffer,  
           the_packet->Buffer.size
            );
          
           _Message_queue_MP_Send_response_packet(  
           MESSAGE_QUEUE_MP_SEND_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
          
           case MESSAGE_QUEUE_MP_SEND_RESPONSE:
           case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case MESSAGE_QUEUE_MP_URGENT_REQUEST:
          
           the_packet->Prefix.return_code = rtems_message_queue_urgent(  
           the_packet->Prefix.id,  
           the_packet->Buffer.buffer,  
           the_packet->Buffer.size
            );
          
           _Message_queue_MP_Send_response_packet(  
           MESSAGE_QUEUE_MP_URGENT_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
          
           case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
          
           the_packet->Prefix.return_code = rtems_message_queue_broadcast(  
           the_packet->Prefix.id,  
           the_packet->Buffer.buffer,  
           the_packet->Buffer.size,  
           &the_packet->count
            );
          
           _Message_queue_MP_Send_response_packet(  
           MESSAGE_QUEUE_MP_BROADCAST_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
          
           case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
           case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
           case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           *(  uint32_t * ) the_thread->Wait.return_argument = the_packet->count;
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
          
           the_packet->Prefix.return_code = rtems_message_queue_flush(  
           the_packet->Prefix.id,  
           &the_packet->count
            );
          
           _Message_queue_MP_Send_response_packet(  
           MESSAGE_QUEUE_MP_FLUSH_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
          
           case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
          
           the_packet->Prefix.return_code = rtems_message_queue_get_number_pending(  
           the_packet->Prefix.id,  
           &the_packet->count
            );
          
           _Message_queue_MP_Send_response_packet(  
           MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
          
           }
          }
          
          /*PAGE
           *
           * _Message_queue_MP_Send_object_was_deleted
           *
           */
          
     440  void _Message_queue_MP_Send_object_was_deleted (  
           Thread_Control *the_proxy
           )
          {
           the_proxy->receive_packet->return_code = RTEMS_OBJECT_WAS_DELETED;
          
           _Message_queue_MP_Send_response_packet(  
           MESSAGE_QUEUE_MP_RECEIVE_RESPONSE,  
           the_proxy->Wait.id,  
           the_proxy
            );
          }
          
          /*PAGE
           *
           * _Message_queue_MP_Send_extract_proxy
           *
           */
          
     459  void _Message_queue_MP_Send_extract_proxy (  
           void *argument
           )
          {
           Thread_Control *the_thread = (  Thread_Control * )argument;
          
           _Message_queue_MP_Send_process_packet(  
           MESSAGE_QUEUE_MP_EXTRACT_PROXY,  
           the_thread->Wait.id,  
           (  rtems_name ) 0,  
           the_thread->Object.id
            );
          }
          
          /*PAGE
           *
           * _Message_queue_MP_Get_packet
           *
           */
          
     479  Message_queue_MP_Packet *_Message_queue_MP_Get_packet (   void  )
          {
           return (   (  Message_queue_MP_Packet * ) _MPCI_Get_packet(   )  );
          }
          
          
          /*PAGE
           *
           * _Message_queue_Core_message_queue_mp_support
           *
           * Input parameters:
           * the_thread - the remote thread the message was submitted to
           * id - id of the message queue
           *
           * Output parameters: NONE
           */
          
     496  void _Message_queue_Core_message_queue_mp_support (  
           Thread_Control *the_thread,  
           Objects_Id id
           )
          {
           the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL;
          
           _Message_queue_MP_Send_response_packet(  
           MESSAGE_QUEUE_MP_RECEIVE_RESPONSE,  
           id,  
           the_thread
            );
          }
          
          /* end of file */

rtems/src/msgqallocate.c

       1  /*
           * Message Queue Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgqallocate.c,  v 1.7 2008/08/05 13:32:38 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * _Message_queue_Allocate
           *
           * Allocate a message queue and the space for its messages
           *
           * Input parameters:
           * the_message_queue - the message queue to allocate message buffers
           * count - maximum message and reserved buffer count
           * max_message_size - maximum size of each message
           *
           * Output parameters:
           * the_message_queue - set if successful,   NULL otherwise
           */
          
      52  Message_queue_Control *_Message_queue_Allocate(  void )
          {
           return (  Message_queue_Control * )
           _Objects_Allocate(  &_Message_queue_Information );
          }

rtems/src/msgqbroadcast.c

       1  /*
           * Message Queue Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgqbroadcast.c,  v 1.12 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * rtems_message_queue_broadcast
           *
           * This directive sends a message for every thread waiting on the queue
           * designated by id.
           *
           * Input parameters:
           * id - pointer to message queue
           * buffer - pointer to message buffer
           * size - size of message to broadcast
           * count - pointer to area to store number of threads made ready
           *
           * Output parameters:
           * count - number of threads made ready
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      56  rtems_status_code rtems_message_queue_broadcast(  
           rtems_id id,  
           const void *buffer,  
           size_t size,  
           uint32_t *count
           )
          {
           register Message_queue_Control *the_message_queue;
           Objects_Locations location;
           CORE_message_queue_Status core_status;
          
           if (   !buffer  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !count  )
           return RTEMS_INVALID_ADDRESS;
          
           the_message_queue = _Message_queue_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           core_status = _CORE_message_queue_Broadcast(  
           &the_message_queue->message_queue,  
           buffer,  
           size,  
           id,  
           #if defined(  RTEMS_MULTIPROCESSING )
           _Message_queue_Core_message_queue_mp_support,  
           #else
           NULL,  
           #endif
           count
            );
          
           _Thread_Enable_dispatch(   );
           return
           _Message_queue_Translate_core_message_queue_return_code(   core_status  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Executing->Wait.return_argument = count;
          
           return
           _Message_queue_MP_Send_request_packet(  
           MESSAGE_QUEUE_MP_BROADCAST_REQUEST,  
           id,  
           buffer,  
           &size,  
           0,   /* option_set not used */
           MPCI_DEFAULT_TIMEOUT
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
           return RTEMS_INVALID_ID;
          }

rtems/src/msgqcreate.c

       1  /*
           * Message Queue Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgqcreate.c,  v 1.15 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * rtems_message_queue_create
           *
           * This directive creates a message queue by allocating and initializing
           * a message queue data structure.
           *
           * Input parameters:
           * name - user defined queue name
           * count - maximum message and reserved buffer count
           * max_message_size - maximum size of each message
           * attribute_set - process method
           * id - pointer to queue
           *
           * Output parameters:
           * id - queue id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      57  rtems_status_code rtems_message_queue_create(  
           rtems_name name,  
           uint32_t count,  
           size_t max_message_size,  
           rtems_attribute attribute_set,  
           rtems_id *id
           )
          {
           register Message_queue_Control *the_message_queue;
           CORE_message_queue_Attributes the_msgq_attributes;
          #if defined(  RTEMS_MULTIPROCESSING )
           bool is_global;
          #endif
          
           if (   !rtems_is_name_valid(   name  )  )
           return RTEMS_INVALID_NAME;
          
           if (   !id  )
           return RTEMS_INVALID_ADDRESS;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   (  is_global = _Attributes_Is_global(   attribute_set  )  ) &&
           !_System_state_Is_multiprocessing  )
           return RTEMS_MP_NOT_CONFIGURED;
          #endif
          
           if (   count == 0  )
           return RTEMS_INVALID_NUMBER;
          
           if (   max_message_size == 0  )
           return RTEMS_INVALID_SIZE;
          
          #if defined(  RTEMS_MULTIPROCESSING )
          #if 1
           /*
           * I am not 100% sure this should be an error.
           * It seems reasonable to create a que with a large max size,  
           * and then just send smaller msgs from remote (  or all ) nodes.
           */
          
           if (   is_global && (  _MPCI_table->maximum_packet_size < max_message_size )  )
           return RTEMS_INVALID_SIZE;
          #endif
          #endif
          
           _Thread_Disable_dispatch(   ); /* protects object pointer */
          
           the_message_queue = _Message_queue_Allocate(   );
          
           if (   !the_message_queue  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_TOO_MANY;
           }
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   is_global &&
           !(   _Objects_MP_Allocate_and_open(   &_Message_queue_Information,  
           name,   the_message_queue->Object.id,   false  )  )  ) {
           _Message_queue_Free(   the_message_queue  );
           _Thread_Enable_dispatch(   );
           return RTEMS_TOO_MANY;
           }
          #endif
          
           the_message_queue->attribute_set = attribute_set;
          
           if (  _Attributes_Is_priority(   attribute_set  )  )
           the_msgq_attributes.discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY;
           else
           the_msgq_attributes.discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
          
           if (   ! _CORE_message_queue_Initialize(  
           &the_message_queue->message_queue,  
           &the_msgq_attributes,  
           count,  
           max_message_size
            )  ) {
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   is_global  )
           _Objects_MP_Close(  
           &_Message_queue_Information,   the_message_queue->Object.id );
          #endif
          
           _Message_queue_Free(   the_message_queue  );
           _Thread_Enable_dispatch(   );
           return RTEMS_UNSATISFIED;
           }
          
           _Objects_Open(  
           &_Message_queue_Information,  
           &the_message_queue->Object,  
           (  Objects_Name ) name
            );
          
           *id = the_message_queue->Object.id;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   is_global  )
           _Message_queue_MP_Send_process_packet(  
           MESSAGE_QUEUE_MP_ANNOUNCE_CREATE,  
           the_message_queue->Object.id,  
           name,  
           0
            );
          #endif
          
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/msgqdelete.c

       1  /*
           * Message Queue Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgqdelete.c,  v 1.7 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * rtems_message_queue_delete
           *
           * This directive allows a thread to delete the message queue specified
           * by the given queue identifier.
           *
           * Input parameters:
           * id - queue id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      52  rtems_status_code rtems_message_queue_delete(  
           rtems_id id
           )
          {
           register Message_queue_Control *the_message_queue;
           Objects_Locations location;
          
           the_message_queue = _Message_queue_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _Objects_Close(   &_Message_queue_Information,  
           &the_message_queue->Object  );
          
           _CORE_message_queue_Close(  
           &the_message_queue->message_queue,  
           #if defined(  RTEMS_MULTIPROCESSING )
           _Message_queue_MP_Send_object_was_deleted,  
           #else
           NULL,  
           #endif
           CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED
            );
          
           _Message_queue_Free(   the_message_queue  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Attributes_Is_global(   the_message_queue->attribute_set  )  ) {
           _Objects_MP_Close(  
           &_Message_queue_Information,  
           the_message_queue->Object.id
            );
          
           _Message_queue_MP_Send_process_packet(  
           MESSAGE_QUEUE_MP_ANNOUNCE_DELETE,  
           the_message_queue->Object.id,  
           0,   /* Not used */
           0
            );
           }
          #endif
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Dispatch(   );
           return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/msgqflush.c

       1  /*
           * Message Queue Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgqflush.c,  v 1.9 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * rtems_message_queue_flush
           *
           * This directive removes all pending messages from a queue and returns
           * the number of messages removed. If no messages were present then
           * a count of zero is returned.
           *
           * Input parameters:
           * id - queue id
           * count - return area for count
           *
           * Output parameters:
           * count - number of messages removed (   0 = empty queue  )
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      55  rtems_status_code rtems_message_queue_flush(  
           rtems_id id,  
           uint32_t *count
           )
          {
           register Message_queue_Control *the_message_queue;
           Objects_Locations location;
          
           if (   !count  )
           return RTEMS_INVALID_ADDRESS;
          
           the_message_queue = _Message_queue_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           *count = _CORE_message_queue_Flush(   &the_message_queue->message_queue  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Executing->Wait.return_argument = count;
          
           return
           _Message_queue_MP_Send_request_packet(  
           MESSAGE_QUEUE_MP_FLUSH_REQUEST,  
           id,  
           0,   /* buffer not used */
           0,   /* size */
           0,   /* option_set not used */
           MPCI_DEFAULT_TIMEOUT
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/msgqgetnumberpending.c

       1  /*
           * Message Queue Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgqgetnumberpending.c,  v 1.9 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * rtems_message_queue_get_number_pending
           *
           * This directive returns the number of messages pending.
           *
           * Input parameters:
           * id - queue id
           * count - return area for count
           *
           * Output parameters:
           * count - number of messages removed (   0 = empty queue  )
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      53  rtems_status_code rtems_message_queue_get_number_pending(  
           rtems_id id,  
           uint32_t *count
           )
          {
           register Message_queue_Control *the_message_queue;
           Objects_Locations location;
          
           if (   !count  )
           return RTEMS_INVALID_ADDRESS;
          
           the_message_queue = _Message_queue_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           *count = the_message_queue->message_queue.number_of_pending_messages;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Executing->Wait.return_argument = count;
          
           return _Message_queue_MP_Send_request_packet(  
           MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST,  
           id,  
           0,   /* buffer not used */
           0,   /* size */
           0,   /* option_set not used */
           MPCI_DEFAULT_TIMEOUT
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/msgqident.c

       1  /*
           * Message Queue Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgqident.c,  v 1.11 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * rtems_message_queue_ident
           *
           * This directive returns the system ID associated with
           * the message queue name.
           *
           * Input parameters:
           * name - user defined message queue name
           * node - node(  s ) to be searched
           * id - pointer to message queue id
           *
           * Output parameters:
           * *id - message queue id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      55  rtems_status_code rtems_message_queue_ident(  
           rtems_name name,  
           uint32_t node,  
           rtems_id *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
          
           status = _Objects_Name_to_id_u32(  
           &_Message_queue_Information,  
           name,  
           node,  
           id
            );
          
           return _Status_Object_name_errors_to_status[ status ];
          }

rtems/src/msgqreceive.c

       1  /*
           * Message Queue Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgqreceive.c,  v 1.16 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * rtems_message_queue_receive
           *
           * This directive dequeues a message from the designated message queue
           * and copies it into the requesting thread's buffer.
           *
           * Input parameters:
           * id - queue id
           * buffer - pointer to message buffer
           * size - size of message receive
           * option_set - options on receive
           * timeout - number of ticks to wait
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      56  rtems_status_code rtems_message_queue_receive(  
           rtems_id id,  
           void *buffer,  
           size_t *size,  
           rtems_option option_set,  
           rtems_interval timeout
           )
          {
           register Message_queue_Control *the_message_queue;
           Objects_Locations location;
           bool wait;
          
           if (   !buffer  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !size  )
           return RTEMS_INVALID_ADDRESS;
          
           the_message_queue = _Message_queue_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   _Options_Is_no_wait(   option_set  )  )
           wait = false;
           else
           wait = true;
          
           _CORE_message_queue_Seize(  
           &the_message_queue->message_queue,  
           the_message_queue->Object.id,  
           buffer,  
           size,  
           wait,  
           timeout
            );
           _Thread_Enable_dispatch(   );
           return _Message_queue_Translate_core_message_queue_return_code(  
           _Thread_Executing->Wait.return_code
            );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           return _Message_queue_MP_Send_request_packet(  
           MESSAGE_QUEUE_MP_RECEIVE_REQUEST,  
           id,  
           buffer,  
           size,  
           option_set,  
           timeout
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/msgqsend.c

       1  /*
           * Message Queue Manager - rtems_message_queue_send
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgqsend.c,  v 1.13 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*
           *
           * rtems_message_queue_send
           *
           * This routine implements the directive rtems_message_queue_send. It sends a
           * message to the specified message queue.
           *
           * Input parameters:
           * id - pointer to message queue
           * buffer - pointer to message buffer
           * size - size of message to send
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
          #define MESSAGE_QUEUE_MP_HANDLER _Message_queue_Core_message_queue_mp_support
          #else
          #define MESSAGE_QUEUE_MP_HANDLER NULL
          #endif
          
      59  rtems_status_code rtems_message_queue_send(  
           rtems_id id,  
           const void *buffer,  
           size_t size
           )
          {
           register Message_queue_Control *the_message_queue;
           Objects_Locations location;
           CORE_message_queue_Status status;
          
           if (   !buffer  )
           return RTEMS_INVALID_ADDRESS;
          
           the_message_queue = _Message_queue_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           status = _CORE_message_queue_Send(  
           &the_message_queue->message_queue,  
           buffer,  
           size,  
           id,  
           MESSAGE_QUEUE_MP_HANDLER,  
           false,   /* sender does not block */
           0 /* no timeout */
            );
          
           _Thread_Enable_dispatch(   );
          
           /*
           * Since this API does not allow for blocking sends,   we can directly
           * return the returned status.
           */
          
           return _Message_queue_Translate_core_message_queue_return_code(  status );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           return _Message_queue_MP_Send_request_packet(  
           MESSAGE_QUEUE_MP_SEND_REQUEST,  
           id,  
           buffer,  
           &size,  
           0,   /* option_set */
           MPCI_DEFAULT_TIMEOUT
            );
           break;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
           return RTEMS_INVALID_ID;
          }

rtems/src/msgqtranslatereturncode.c

       1  /*
           * Message Queue Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgqtranslatereturncode.c,  v 1.9 2008/09/05 21:39:16 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * _Message_queue_Translate_core_message_queue_return_code
           *
           * Input parameters:
           * the_message_queue_status - message_queue status code to translate
           *
           * Output parameters:
           * rtems status code - translated RTEMS status code
           *
           */
          
          rtems_status_code _Message_queue_Translate_core_return_code_[] = {
           RTEMS_SUCCESSFUL,   /* CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL */
           RTEMS_INVALID_SIZE,   /* CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE */
           RTEMS_TOO_MANY,   /* CORE_MESSAGE_QUEUE_STATUS_TOO_MANY */
           RTEMS_UNSATISFIED,   /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED */
           RTEMS_UNSATISFIED,   /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT */
           RTEMS_OBJECT_WAS_DELETED,   /* CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED */
           RTEMS_TIMEOUT /* CORE_MESSAGE_QUEUE_STATUS_TIMEOUT */
          };
          
      59  rtems_status_code _Message_queue_Translate_core_message_queue_return_code (  
           uint32_t status
           )
          {
           /*
           * Check for proxy blocking first since it is out of range
           * from the external status codes.
           */
           #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Thread_Is_proxy_blocking(  status )  )
           return RTEMS_PROXY_BLOCKING;
           #endif
          
           /*
           * Internal consistency check for bad status from SuperCore
           */
           #if defined(  RTEMS_DEBUG )
           if (   status > CORE_MESSAGE_QUEUE_STATUS_TIMEOUT  )
           return RTEMS_INTERNAL_ERROR;
           #endif
          
           return _Message_queue_Translate_core_return_code_[status];
          }

rtems/src/msgqurgent.c

       1  /*
           * Message Queue Manager - rtems_message_queue_urgent
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: msgqurgent.c,  v 1.13 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/rtems/message.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * rtems_message_queue_urgent
           *
           * This routine implements the directives rtems_message_queue_urgent. It
           * prepends a message to the specified message queue.
           *
           * Input parameters:
           * id - pointer to message queue
           * buffer - pointer to message buffer
           * size - size of message to send urgently
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
          #define MESSAGE_QUEUE_MP_HANDLER _Message_queue_Core_message_queue_mp_support
          #else
          #define MESSAGE_QUEUE_MP_HANDLER NULL
          #endif
          
      59  rtems_status_code rtems_message_queue_urgent(  
           rtems_id id,  
           const void *buffer,  
           size_t size
           )
          {
           register Message_queue_Control *the_message_queue;
           Objects_Locations location;
           CORE_message_queue_Status status;
          
           if (   !buffer  )
           return RTEMS_INVALID_ADDRESS;
          
           the_message_queue = _Message_queue_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           status = _CORE_message_queue_Urgent(  
           &the_message_queue->message_queue,  
           buffer,  
           size,  
           id,  
           MESSAGE_QUEUE_MP_HANDLER,  
           false,   /* sender does not block */
           0 /* no timeout */
            );
           _Thread_Enable_dispatch(   );
          
           /*
           * Since this API does not allow for blocking sends,   we can directly
           * return the returned status.
           */
          
           return _Message_queue_Translate_core_message_queue_return_code(  status );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           return _Message_queue_MP_Send_request_packet(  
           MESSAGE_QUEUE_MP_URGENT_REQUEST,  
           id,  
           buffer,  
           &size,  
           0,   /* option_set */
           MPCI_DEFAULT_TIMEOUT
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/part.c

       1  /*
           * Partition Manager
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: part.c,  v 1.23 2009/01/06 05:05:03 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/part.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * _Partition_Manager_initialization
           *
           * This routine initializes all partition manager related
           * data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      40  void _Partition_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_Partition_Information,   /* object information table */
           OBJECTS_CLASSIC_API,   /* object API */
           OBJECTS_RTEMS_PARTITIONS,   /* object class */
           Configuration_RTEMS_API.maximum_partitions,  
           /* maximum objects of this class */
           sizeof(   Partition_Control  ),   /* size of this object's control block */
           false,   /* true if the name is a string */
           RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           true,   /* true if this is a global object class */
           _Partition_MP_Send_extract_proxy /* Proxy extraction support callout */
          #endif
            );
          
           /*
           * Register the MP Process Packet routine.
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
           _MPCI_Register_packet_processor(  
           MP_PACKET_PARTITION,  
           _Partition_MP_Process_packet
            );
          #endif
          
          }

rtems/src/partcreate.c

       1  /*
           * Partition Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: partcreate.c,  v 1.11 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/part.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_partition_create
           *
           * This directive creates a partiton of fixed sized buffers from the
           * given contiguous memory area.
           *
           * Input parameters:
           * name - user defined partition name
           * starting_address - physical start address of partition
           * length - physical length in bytes
           * buffer_size - size of buffers in bytes
           * attribute_set - partition attributes
           * id - pointer to partition id
           *
           * Output parameters:
           * id - partition id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      49  rtems_status_code rtems_partition_create(  
           rtems_name name,  
           void *starting_address,  
           uint32_t length,  
           uint32_t buffer_size,  
           rtems_attribute attribute_set,  
           rtems_id *id
           )
          {
           register Partition_Control *the_partition;
          
           if (   !rtems_is_name_valid(   name  )  )
           return RTEMS_INVALID_NAME;
          
           if (   !starting_address  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !id  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   length == 0 || buffer_size == 0 || length < buffer_size ||
           !_Partition_Is_buffer_size_aligned(   buffer_size  )  )
           return RTEMS_INVALID_SIZE;
          
           if (   !_Addresses_Is_aligned(   starting_address  )  )
           return RTEMS_INVALID_ADDRESS;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Attributes_Is_global(   attribute_set  ) &&
           !_System_state_Is_multiprocessing  )
           return RTEMS_MP_NOT_CONFIGURED;
          #endif
          
           _Thread_Disable_dispatch(   ); /* prevents deletion */
          
           the_partition = _Partition_Allocate(   );
          
           if (   !the_partition  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_TOO_MANY;
           }
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Attributes_Is_global(   attribute_set  ) &&
           !(   _Objects_MP_Allocate_and_open(   &_Partition_Information,   name,  
           the_partition->Object.id,   false  )  )  ) {
           _Partition_Free(   the_partition  );
           _Thread_Enable_dispatch(   );
           return RTEMS_TOO_MANY;
           }
          #endif
          
           the_partition->starting_address = starting_address;
           the_partition->length = length;
           the_partition->buffer_size = buffer_size;
           the_partition->attribute_set = attribute_set;
           the_partition->number_of_used_blocks = 0;
          
           _Chain_Initialize(   &the_partition->Memory,   starting_address,  
           length / buffer_size,   buffer_size  );
          
           _Objects_Open(  
           &_Partition_Information,  
           &the_partition->Object,  
           (  Objects_Name ) name
            );
          
           *id = the_partition->Object.id;
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Attributes_Is_global(   attribute_set  )  )
           _Partition_MP_Send_process_packet(  
           PARTITION_MP_ANNOUNCE_CREATE,  
           the_partition->Object.id,  
           name,  
           0 /* Not used */
            );
          #endif
          
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/partdata.c

       1  /*
           * Partition Manager -- Instantiate Data
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: partdata.c,  v 1.1 2007/05/21 23:19:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate RTEMS partition data */
          #define RTEMS_PART_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/rtems/part.h>

rtems/src/partdelete.c

       1  /*
           * Partition Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: partdelete.c,  v 1.8 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/part.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_partition_delete
           *
           * This directive allows a thread to delete a partition specified by
           * the partition identifier,   provided that none of its buffers are
           * still allocated.
           *
           * Input parameters:
           * id - partition id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      44  rtems_status_code rtems_partition_delete(  
           rtems_id id
           )
          {
           register Partition_Control *the_partition;
           Objects_Locations location;
          
           the_partition = _Partition_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   the_partition->number_of_used_blocks == 0  ) {
           _Objects_Close(   &_Partition_Information,   &the_partition->Object  );
           _Partition_Free(   the_partition  );
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Attributes_Is_global(   the_partition->attribute_set  )  ) {
          
           _Objects_MP_Close(  
           &_Partition_Information,  
           the_partition->Object.id
            );
          
           _Partition_MP_Send_process_packet(  
           PARTITION_MP_ANNOUNCE_DELETE,  
           the_partition->Object.id,  
           0,   /* Not used */
           0 /* Not used */
            );
           }
          #endif
          
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_RESOURCE_IN_USE;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Dispatch(   );
           return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/partgetbuffer.c

       1  /*
           * Partition Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: partgetbuffer.c,  v 1.8 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/part.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_partition_get_buffer
           *
           * This directive will obtain a buffer from a buffer partition.
           *
           * Input parameters:
           * id - partition id
           * buffer - pointer to buffer address
           *
           * Output parameters:
           * buffer - pointer to buffer address filled in
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      44  rtems_status_code rtems_partition_get_buffer(  
           rtems_id id,  
           void **buffer
           )
          {
           register Partition_Control *the_partition;
           Objects_Locations location;
           void *the_buffer;
          
           if (   !buffer  )
           return RTEMS_INVALID_ADDRESS;
          
           the_partition = _Partition_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           the_buffer = _Partition_Allocate_buffer(   the_partition  );
           if (   the_buffer  ) {
           the_partition->number_of_used_blocks += 1;
           _Thread_Enable_dispatch(   );
           *buffer = the_buffer;
           return RTEMS_SUCCESSFUL;
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_UNSATISFIED;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Executing->Wait.return_argument = buffer;
           return(  
           _Partition_MP_Send_request_packet(  
           PARTITION_MP_GET_BUFFER_REQUEST,  
           id,  
           0 /* Not used */
            )
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/partident.c

       1  /*
           * Partition Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: partident.c,  v 1.10 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/part.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_partition_ident
           *
           * This directive returns the system ID associated with
           * the partition name.
           *
           * Input parameters:
           * name - user defined partition name
           * node - node(  s ) to be searched
           * id - pointer to partition id
           *
           * Output parameters:
           * *id - partition id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      46  rtems_status_code rtems_partition_ident(  
           rtems_name name,  
           uint32_t node,  
           rtems_id *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
          
           status = _Objects_Name_to_id_u32(   &_Partition_Information,   name,   node,   id  );
          
           return _Status_Object_name_errors_to_status[ status ];
          }

rtems/src/partmp.c

       1  /*
           * Multiprocessing Support for the Partition Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: partmp.c,  v 1.18 2009/01/06 05:05:03 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/score/mpci.h>
          #include <rtems/score/mppkt.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/part.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * _Partition_MP_Send_process_packet
           *
           */
          
      35  void _Partition_MP_Send_process_packet (  
           Partition_MP_Remote_operations operation,  
           Objects_Id partition_id,  
           rtems_name name,  
           Objects_Id proxy_id
           )
          {
           Partition_MP_Packet *the_packet;
           uint32_t node;
          
           switch (   operation  ) {
          
           case PARTITION_MP_ANNOUNCE_CREATE:
           case PARTITION_MP_ANNOUNCE_DELETE:
           case PARTITION_MP_EXTRACT_PROXY:
          
           the_packet = _Partition_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_PARTITION;
           the_packet->Prefix.length = sizeof (   Partition_MP_Packet  );
           the_packet->Prefix.to_convert = sizeof (   Partition_MP_Packet  );
           the_packet->operation = operation;
           the_packet->Prefix.id = partition_id;
           the_packet->name = name;
           the_packet->proxy_id = proxy_id;
          
           if (   operation == PARTITION_MP_EXTRACT_PROXY  )
           node = _Objects_Get_node(   partition_id  );
           else
           node = MPCI_ALL_NODES;
          
           _MPCI_Send_process_packet(   node,   &the_packet->Prefix  );
           break;
          
           case PARTITION_MP_GET_BUFFER_REQUEST:
           case PARTITION_MP_GET_BUFFER_RESPONSE:
           case PARTITION_MP_RETURN_BUFFER_REQUEST:
           case PARTITION_MP_RETURN_BUFFER_RESPONSE:
           break;
           }
          }
          
          /*PAGE
           *
           * _Partition_MP_Send_request_packet
           *
           */
          
      82  rtems_status_code _Partition_MP_Send_request_packet (  
           Partition_MP_Remote_operations operation,  
           Objects_Id partition_id,  
           void *buffer
           )
          {
           Partition_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case PARTITION_MP_GET_BUFFER_REQUEST:
           case PARTITION_MP_RETURN_BUFFER_REQUEST:
          
           the_packet = _Partition_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_PARTITION;
           the_packet->Prefix.length = sizeof (   Partition_MP_Packet  );
           the_packet->Prefix.to_convert = sizeof (   Partition_MP_Packet  );
           the_packet->operation = operation;
           the_packet->Prefix.id = partition_id;
           the_packet->buffer = buffer;
          
           return
           _MPCI_Send_request_packet(  
           _Objects_Get_node(   partition_id  ),  
           &the_packet->Prefix,  
           STATES_READY /* Not used */
            );
          
           break;
          
           case PARTITION_MP_ANNOUNCE_CREATE:
           case PARTITION_MP_ANNOUNCE_DELETE:
           case PARTITION_MP_EXTRACT_PROXY:
           case PARTITION_MP_GET_BUFFER_RESPONSE:
           case PARTITION_MP_RETURN_BUFFER_RESPONSE:
           break;
          
           }
           /*
           * The following line is included to satisfy compilers which
           * produce warnings when a function does not end with a return.
           */
           return RTEMS_SUCCESSFUL;
          }
          
          /*PAGE
           *
           * _Partition_MP_Send_response_packet
           *
           */
          
     133  void _Partition_MP_Send_response_packet (  
           Partition_MP_Remote_operations operation,  
           Objects_Id partition_id,  
           Thread_Control *the_thread
           )
          {
           Partition_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case PARTITION_MP_GET_BUFFER_RESPONSE:
           case PARTITION_MP_RETURN_BUFFER_RESPONSE:
          
           the_packet = (   Partition_MP_Packet * ) the_thread->receive_packet;
          
          /*
           * The packet being returned already contains the class,   length,   and
           * to_convert fields,   therefore they are not set in this routine.
           */
           the_packet->operation = operation;
           the_packet->Prefix.id = the_packet->Prefix.source_tid;
          
           _MPCI_Send_response_packet(  
           _Objects_Get_node(   the_packet->Prefix.source_tid  ),  
           &the_packet->Prefix
            );
           break;
          
           case PARTITION_MP_ANNOUNCE_CREATE:
           case PARTITION_MP_ANNOUNCE_DELETE:
           case PARTITION_MP_EXTRACT_PROXY:
           case PARTITION_MP_GET_BUFFER_REQUEST:
           case PARTITION_MP_RETURN_BUFFER_REQUEST:
           break;
          
           }
          }
          
          /*PAGE
           *
           *
           * _Partition_MP_Process_packet
           *
           */
          
     178  void _Partition_MP_Process_packet (  
           rtems_packet_prefix *the_packet_prefix
           )
          {
           Partition_MP_Packet *the_packet;
           Thread_Control *the_thread;
           bool ignored;
          
           the_packet = (  Partition_MP_Packet * ) the_packet_prefix;
          
           switch (   the_packet->operation  ) {
          
           case PARTITION_MP_ANNOUNCE_CREATE:
          
           ignored = _Objects_MP_Allocate_and_open(  
           &_Partition_Information,  
           the_packet->name,  
           the_packet->Prefix.id,  
           true
            );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case PARTITION_MP_ANNOUNCE_DELETE:
          
           _Objects_MP_Close(   &_Partition_Information,   the_packet->Prefix.id  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case PARTITION_MP_EXTRACT_PROXY:
          
           the_thread = _Thread_MP_Find_proxy(   the_packet->proxy_id  );
          
           if (   ! _Thread_Is_null(   the_thread  )  )
           _Thread_queue_Extract(   the_thread->Wait.queue,   the_thread  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case PARTITION_MP_GET_BUFFER_REQUEST:
          
           the_packet->Prefix.return_code = rtems_partition_get_buffer(  
           the_packet->Prefix.id,  
           &the_packet->buffer
            );
          
           _Partition_MP_Send_response_packet(  
           PARTITION_MP_GET_BUFFER_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
          
           case PARTITION_MP_GET_BUFFER_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           *(  void ** )the_thread->Wait.return_argument = the_packet->buffer;
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case PARTITION_MP_RETURN_BUFFER_REQUEST:
          
           the_packet->Prefix.return_code = rtems_partition_return_buffer(  
           the_packet->Prefix.id,  
           the_packet->buffer
            );
          
           _Partition_MP_Send_response_packet(  
           PARTITION_MP_RETURN_BUFFER_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
          
           case PARTITION_MP_RETURN_BUFFER_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           }
          }
          
          /*PAGE
           *
           * _Partition_MP_Send_object_was_deleted
           *
           * This routine is not needed by the Partition since a partition
           * cannot be deleted when buffers are in use.
           *
           */
          
          /*PAGE
           *
           * _Partition_MP_Send_extract_proxy
           *
           */
          
     281  void _Partition_MP_Send_extract_proxy (  
           void *argument
           )
          {
           Thread_Control *the_thread = (  Thread_Control * )argument;
          
           _Partition_MP_Send_process_packet(  
           PARTITION_MP_EXTRACT_PROXY,  
           the_thread->Wait.id,  
           (  rtems_name ) 0,  
           the_thread->Object.id
            );
          
          }
          
          /*PAGE
           *
           * _Partition_MP_Get_packet
           *
           */
          
     302  Partition_MP_Packet *_Partition_MP_Get_packet (   void  )
          {
           return (   (  Partition_MP_Packet * ) _MPCI_Get_packet(   )  );
          }
          
          /* end of file */

rtems/src/partreturnbuffer.c

       1  /*
           * Partition Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: partreturnbuffer.c,  v 1.7 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/address.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/part.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_partition_return_buffer
           *
           * This directive will return the given buffer to the specified
           * buffer partition.
           *
           * Input parameters:
           * id - partition id
           * buffer - pointer to buffer address
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      44  rtems_status_code rtems_partition_return_buffer(  
           rtems_id id,  
           void *buffer
           )
          {
           register Partition_Control *the_partition;
           Objects_Locations location;
          
           the_partition = _Partition_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   _Partition_Is_buffer_valid(   buffer,   the_partition  )  ) {
           _Partition_Free_buffer(   the_partition,   buffer  );
           the_partition->number_of_used_blocks -= 1;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_INVALID_ADDRESS;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           return _Partition_MP_Send_request_packet(  
           PARTITION_MP_RETURN_BUFFER_REQUEST,  
           id,  
           buffer
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/ratemon.c

       1  /*
           * Rate Monotonic Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemon.c,  v 1.24 2009/01/06 05:02:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * _Rate_monotonic_Manager_initialization
           *
           * This routine initializes all Rate Monotonic Manager related
           * data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           *
           * NOTE: The Rate Monotonic Manager is built on top of the Watchdog
           * Handler.
           */
          
      43  void _Rate_monotonic_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_Rate_monotonic_Information,   /* object information table */
           OBJECTS_CLASSIC_API,   /* object API */
           OBJECTS_RTEMS_PERIODS,   /* object class */
           Configuration_RTEMS_API.maximum_periods,  
           /* maximum objects of this class */
           sizeof(   Rate_monotonic_Control  ),  /* size of this object's control block */
           false,   /* true if the name is a string */
           RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

rtems/src/ratemoncancel.c

       1  /*
           * Rate Monotonic Manager -- Cancel a Period
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemoncancel.c,  v 1.10 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * rtems_rate_monotonic_cancel
           *
           * This directive allows a thread to cancel a rate monotonic timer.
           *
           * Input parameters:
           * id - rate monotonic id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful and caller is not the owning thread
           * error code - if unsuccessful
           */
          
      40  rtems_status_code rtems_rate_monotonic_cancel(  
           rtems_id id
           )
          {
           Rate_monotonic_Control *the_period;
           Objects_Locations location;
          
           the_period = _Rate_monotonic_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   !_Thread_Is_executing(   the_period->owner  )  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_NOT_OWNER_OF_RESOURCE;
           }
           (  void ) _Watchdog_Remove(   &the_period->Timer  );
           the_period->state = RATE_MONOTONIC_INACTIVE;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/ratemoncreate.c

       1  /*
           * Rate Monotonic Manager -- Create a Period
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemoncreate.c,  v 1.10 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * rtems_rate_monotonic_create
           *
           * This directive creates a rate monotonic timer and performs
           * some initialization.
           *
           * Input parameters:
           * name - name of period
           * id - pointer to rate monotonic id
           *
           * Output parameters:
           * id - rate monotonic id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      43  rtems_status_code rtems_rate_monotonic_create(  
           rtems_name name,  
           rtems_id *id
           )
          {
           Rate_monotonic_Control *the_period;
          
           if (   !rtems_is_name_valid(   name  )  )
           return RTEMS_INVALID_NAME;
          
           if (   !id  )
           return RTEMS_INVALID_ADDRESS;
          
           _Thread_Disable_dispatch(   ); /* to prevent deletion */
          
           the_period = _Rate_monotonic_Allocate(   );
          
           if (   !the_period  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_TOO_MANY;
           }
          
           the_period->owner = _Thread_Executing;
           the_period->state = RATE_MONOTONIC_INACTIVE;
          
           _Watchdog_Initialize(   &the_period->Timer,   NULL,   0,   NULL  );
          
           _Rate_monotonic_Reset_statistics(   the_period  );
          
           _Objects_Open(  
           &_Rate_monotonic_Information,  
           &the_period->Object,  
           (  Objects_Name ) name
            );
          
           *id = the_period->Object.id;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/ratemondata.c

       1  /*
           * Rate Monotonic Manager -- Instantiate Data
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemondata.c,  v 1.1 2007/05/21 23:19:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate RTEMS period data */
          #define RTEMS_RATEMON_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/rtems/ratemon.h>

rtems/src/ratemondelete.c

       1  /*
           * Rate Monotonic Manager -- Delete a Period
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemondelete.c,  v 1.9 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * rtems_rate_monotonic_delete
           *
           * This directive allows a thread to delete a rate monotonic timer.
           *
           * Input parameters:
           * id - rate monotonic id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      40  rtems_status_code rtems_rate_monotonic_delete(  
           rtems_id id
           )
          {
           Rate_monotonic_Control *the_period;
           Objects_Locations location;
          
           the_period = _Rate_monotonic_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _Objects_Close(   &_Rate_monotonic_Information,   &the_period->Object  );
           (  void ) _Watchdog_Remove(   &the_period->Timer  );
           the_period->state = RATE_MONOTONIC_INACTIVE;
           _Rate_monotonic_Free(   the_period  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/ratemongetstatistics.c

       1  /*
           * Rate Monotonic Manager -- Get Statistics
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemongetstatistics.c,  v 1.7 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * rtems_rate_monotonic_get_statistics
           *
           * This directive allows a thread to obtain statistics information on a
           * period.
           *
           * Input parameters:
           * id - rate monotonic id
           * statistics - pointer to statistics control block
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           *
           */
          
      43  rtems_status_code rtems_rate_monotonic_get_statistics(  
           rtems_id id,  
           rtems_rate_monotonic_period_statistics *statistics
           )
          {
           Objects_Locations location;
           Rate_monotonic_Control *the_period;
           rtems_rate_monotonic_period_statistics *dst;
           Rate_monotonic_Statistics *src;
          
           if (   !statistics  )
           return RTEMS_INVALID_ADDRESS;
          
           the_period = _Rate_monotonic_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           dst = statistics;
           src = &the_period->Statistics;
           dst->count = src->count;
           dst->missed_count = src->missed_count;
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           _Timestamp_To_timespec(   &src->min_cpu_time,   &dst->min_cpu_time  );
           _Timestamp_To_timespec(   &src->max_cpu_time,   &dst->max_cpu_time  );
           _Timestamp_To_timespec(   &src->total_cpu_time,   &dst->total_cpu_time  );
           _Timestamp_To_timespec(   &src->min_wall_time,   &dst->min_wall_time  );
           _Timestamp_To_timespec(   &src->max_wall_time,   &dst->max_wall_time  );
           _Timestamp_To_timespec(   &src->total_wall_time,   &dst->total_wall_time  );
           #else
           dst->min_cpu_time = src->min_cpu_time;
           dst->max_cpu_time = src->max_cpu_time;
           dst->total_cpu_time = src->total_cpu_time;
           dst->min_wall_time = src->min_wall_time;
           dst->max_wall_time = src->max_wall_time;
           dst->total_wall_time = src->total_wall_time;
           #endif
          
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/ratemongetstatus.c

       1  /*
           * Rate Monotonic Manager -- Get Status
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemongetstatus.c,  v 1.18 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/score/thread.h>
          
          #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           #include <rtems/score/timespec.h>
          #endif
          
          /*PAGE
           *
           * rtems_rate_monotonic_get_status
           *
           * This directive allows a thread to obtain status information on a
           * period.
           *
           * Input parameters:
           * id - rate monotonic id
           * status - pointer to status control block
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           *
           */
          
      47  rtems_status_code rtems_rate_monotonic_get_status(  
           rtems_id id,  
           rtems_rate_monotonic_period_status *status
           )
          {
           Thread_CPU_usage_t executed;
           Objects_Locations location;
           Rate_monotonic_Period_time_t since_last_period;
           Rate_monotonic_Control *the_period;
           bool valid_status;
          
           if (   !status  )
           return RTEMS_INVALID_ADDRESS;
          
           the_period = _Rate_monotonic_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           status->owner = the_period->owner->Object.id;
           status->state = the_period->state;
          
           /*
           * If the period is inactive,   there is no information.
           */
           if (   status->state == RATE_MONOTONIC_INACTIVE  ) {
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           _Timespec_Set_to_zero(   &status->since_last_period  );
           _Timespec_Set_to_zero(   &status->executed_since_last_period  );
           #else
           status->since_last_period = 0;
           status->executed_since_last_period = 0;
           #endif
          
           } else {
          
           /*
           * Grab the current status.
           */
           valid_status =
           _Rate_monotonic_Get_status(  
           the_period,   &since_last_period,   &executed
            );
           if (  !valid_status ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_NOT_DEFINED;
           }
          
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           _Timestamp_To_timespec(  
           &since_last_period,   &status->since_last_period
            );
           _Timestamp_To_timespec(  
           &executed,   &status->executed_since_last_period
            );
           #else
           status->since_last_period = since_last_period;
           status->executed_since_last_period = executed;
           #endif
           }
          
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/ratemonident.c

       1  /*
           * Rate Monotonic Manager -- Name to Id Lookup
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemonident.c,  v 1.11 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * rtems_rate_monotonic_ident
           *
           * This directive returns the system ID associated with
           * the rate monotonic period name.
           *
           * Input parameters:
           * name - user defined period name
           * id - pointer to period id
           *
           * Output parameters:
           * *id - region id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      43  rtems_status_code rtems_rate_monotonic_ident(  
           rtems_name name,  
           rtems_id *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
          
           status = _Objects_Name_to_id_u32(  
           &_Rate_monotonic_Information,  
           name,  
           OBJECTS_SEARCH_LOCAL_NODE,  
           id
            );
          
           return _Status_Object_name_errors_to_status[ status ];
          }

rtems/src/ratemonperiod.c

       1  /*
           * Rate Monotonic Manager - Period Blocking and Status
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemonperiod.c,  v 1.29 2010/07/26 20:27:04 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/score/thread.h>
          
      26  bool _Rate_monotonic_Get_status(  
           Rate_monotonic_Control *the_period,  
           Rate_monotonic_Period_time_t *wall_since_last_period,  
           Thread_CPU_usage_t *cpu_since_last_period
           )
          {
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           Timestamp_Control uptime;
           #endif
           Thread_Control *owning_thread = the_period->owner;
           Thread_CPU_usage_t used;
          
           /*
           * Determine elapsed wall time since period initiated.
           */
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           _TOD_Get_uptime(   &uptime  );
           _Timestamp_Subtract(  
           &the_period->time_period_initiated,   &uptime,   wall_since_last_period
            );
           #else
           *wall_since_last_period =
           _Watchdog_Ticks_since_boot - the_period->time_period_initiated;
           #endif
          
           /*
           * Determine cpu usage since period initiated.
           */
           used = owning_thread->cpu_time_used;
          
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           if (  owning_thread == _Thread_Executing ) {
          
           Thread_CPU_usage_t ran;
          
           /* How much time time since last context switch */
           _Timestamp_Subtract(  
           &_Thread_Time_of_last_context_switch,   &uptime,   &ran
            );
          
           /* cpu usage += ran */
           _Timestamp_Add_to(   &used,   &ran  );
          
           /*
           * The cpu usage info was reset while executing. Can't
           * determine a status.
           */
           if (  _Timestamp_Less_than(  &used,   &the_period->cpu_usage_period_initiated ) )
           return false;
          
           /* used = current cpu usage - cpu usage at start of period */
           _Timestamp_Subtract(  
           &the_period->cpu_usage_period_initiated,  
           &used,  
           cpu_since_last_period
            );
           }
           #else
           /*
           * The cpu usage info was reset while executing. Can't
           * determine a status.
           */
           if (  used < the_period->cpu_usage_period_initiated )
           return false;
          
           *cpu_since_last_period = used - the_period->cpu_usage_period_initiated;
           #endif
           return true;
          }
          
      96  void _Rate_monotonic_Initiate_statistics(  
           Rate_monotonic_Control *the_period
           )
          {
           Thread_Control *owning_thread = the_period->owner;
          
           /*
           * If using nanosecond statistics,   we need to obtain the uptime.
           */
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           Timestamp_Control uptime;
          
           _TOD_Get_uptime(   &uptime  );
           #endif
          
           /*
           * Set the starting point and the CPU time used for the statistics.
           */
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           the_period->time_period_initiated = uptime;
           #else
           the_period->time_period_initiated = _Watchdog_Ticks_since_boot;
           #endif
          
           the_period->cpu_usage_period_initiated = owning_thread->cpu_time_used;
          
           /*
           * If using nanosecond statistics and the period's thread is currently
           * executing,   then we need to take into account how much time the
           * executing thread has run since the last context switch. When this
           * routine is invoked from rtems_rate_monotonic_period,   the owner will
           * be the executing thread. When this routine is invoked from
           * _Rate_monotonic_Timeout,   it will not.
           */
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           if (  owning_thread == _Thread_Executing ) {
          
           rtems_thread_cpu_usage_t ran;
          
           /*
           * Adjust the CPU time used to account for the time since last
           * context switch.
           */
           _Timespec_Subtract(  
           &_Thread_Time_of_last_context_switch,   &uptime,   &ran
            );
          
           _Timespec_Add_to(   &the_period->cpu_usage_period_initiated,   &ran  );
           }
           #endif
          }
          
     148  void _Rate_monotonic_Update_statistics(  
           Rate_monotonic_Control *the_period
           )
          {
           Thread_CPU_usage_t executed;
           Rate_monotonic_Period_time_t since_last_period;
           Rate_monotonic_Statistics *stats;
           bool valid_status;
          
           /*
           * Assume we are only called in states where it is appropriate
           * to update the statistics. This should only be RATE_MONOTONIC_ACTIVE
           * and RATE_MONOTONIC_EXPIRED.
           */
          
           /*
           * Update the counts.
           */
           stats = &the_period->Statistics;
           stats->count++;
          
           if (   the_period->state == RATE_MONOTONIC_EXPIRED  )
           stats->missed_count++;
          
           /*
           * Grab status for time statistics.
           */
           valid_status =
           _Rate_monotonic_Get_status(   the_period,   &since_last_period,   &executed  );
           if (  !valid_status )
           return;
          
           /*
           * Update CPU time
           */
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           _Timestamp_Add_to(   &stats->total_cpu_time,   &executed  );
          
           if (   _Timestamp_Less_than(   &executed,   &stats->min_cpu_time  )  )
           stats->min_cpu_time = executed;
          
           if (   _Timestamp_Greater_than(   &executed,   &stats->max_cpu_time  )  )
           stats->max_cpu_time = executed;
           #else
           stats->total_cpu_time += executed;
          
           if (   executed < stats->min_cpu_time  )
           stats->min_cpu_time = executed;
          
           if (   executed > stats->max_cpu_time  )
           stats->max_cpu_time = executed;
           #endif
          
           /*
           * Update Wall time
           */
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           _Timestamp_Add_to(   &stats->total_wall_time,   &since_last_period  );
          
           if (   _Timestamp_Less_than(   &since_last_period,   &stats->min_wall_time  )  )
           stats->min_wall_time = since_last_period;
          
           if (   _Timestamp_Greater_than(   &since_last_period,   &stats->max_wall_time  )  )
           stats->max_wall_time = since_last_period;
           #else
          
           /* Sanity check wall time */
           if (   since_last_period < executed  )
           since_last_period = executed;
          
           stats->total_wall_time += since_last_period;
          
           if (   since_last_period < stats->min_wall_time  )
           stats->min_wall_time = since_last_period;
          
           if (   since_last_period > stats->max_wall_time  )
           stats->max_wall_time = since_last_period;
           #endif
          }
          
          
          /*PAGE
           *
           * rtems_rate_monotonic_period
           *
           * This directive allows a thread to manipulate a rate monotonic timer.
           *
           * Input parameters:
           * id - rate monotonic id
           * length - length of period (  in ticks )
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
     244  rtems_status_code rtems_rate_monotonic_period(  
           rtems_id id,  
           rtems_interval length
           )
          {
           Rate_monotonic_Control *the_period;
           Objects_Locations location;
           rtems_status_code return_value;
           rtems_rate_monotonic_period_states local_state;
           ISR_Level level;
          
           the_period = _Rate_monotonic_Get(   id,   &location  );
          
           switch (   location  ) {
           case OBJECTS_LOCAL:
           if (   !_Thread_Is_executing(   the_period->owner  )  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_NOT_OWNER_OF_RESOURCE;
           }
          
           if (   length == RTEMS_PERIOD_STATUS  ) {
           switch (   the_period->state  ) {
           case RATE_MONOTONIC_INACTIVE:
           return_value = RTEMS_NOT_DEFINED;
           break;
           case RATE_MONOTONIC_EXPIRED:
           case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
           return_value = RTEMS_TIMEOUT;
           break;
           case RATE_MONOTONIC_ACTIVE:
           default: /* unreached -- only to remove warnings */
           return_value = RTEMS_SUCCESSFUL;
           break;
           }
           _Thread_Enable_dispatch(   );
           return(   return_value  );
           }
          
           _ISR_Disable(   level  );
           if (   the_period->state == RATE_MONOTONIC_INACTIVE  ) {
           _ISR_Enable(   level  );
          
           /*
           * Baseline statistics information for the beginning of a period.
           */
           _Rate_monotonic_Initiate_statistics(   the_period  );
          
           the_period->state = RATE_MONOTONIC_ACTIVE;
           _Watchdog_Initialize(  
           &the_period->Timer,  
           _Rate_monotonic_Timeout,  
           id,  
           NULL
            );
          
           the_period->next_length = length;
          
           _Watchdog_Insert_ticks(   &the_period->Timer,   length  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
          
           if (   the_period->state == RATE_MONOTONIC_ACTIVE  ) {
           /*
           * Update statistics from the concluding period.
           */
           _Rate_monotonic_Update_statistics(   the_period  );
          
           /*
           * This tells the _Rate_monotonic_Timeout that this task is
           * in the process of blocking on the period and that we
           * may be changing the length of the next period.
           */
           the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING;
           the_period->next_length = length;
          
           _ISR_Enable(   level  );
          
           _Thread_Executing->Wait.id = the_period->Object.id;
           _Thread_Set_state(   _Thread_Executing,   STATES_WAITING_FOR_PERIOD  );
          
           /*
           * Did the watchdog timer expire while we were actually blocking
           * on it?
           */
           _ISR_Disable(   level  );
           local_state = the_period->state;
           the_period->state = RATE_MONOTONIC_ACTIVE;
           _ISR_Enable(   level  );
          
           /*
           * If it did,   then we want to unblock ourself and continue as
           * if nothing happen. The period was reset in the timeout routine.
           */
           if (   local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING  )
           _Thread_Clear_state(   _Thread_Executing,   STATES_WAITING_FOR_PERIOD  );
          
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
          
           if (   the_period->state == RATE_MONOTONIC_EXPIRED  ) {
           /*
           * Update statistics from the concluding period
           */
           _Rate_monotonic_Update_statistics(   the_period  );
          
           _ISR_Enable(   level  );
          
           the_period->state = RATE_MONOTONIC_ACTIVE;
           the_period->next_length = length;
          
           _Watchdog_Insert_ticks(   &the_period->Timer,   length  );
           _Thread_Enable_dispatch(   );
           return RTEMS_TIMEOUT;
           }
          
           /*
           * These should never happen so just return invalid Id.
           * - RATE_MONOTONIC_OWNER_IS_BLOCKING:
           * - RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
           */
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/ratemonreportstatistics.c

       1  /*
           * Rate Monotonic Manager -- Report Statistics for All Periods
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemonreportstatistics.c,  v 1.12 2009/12/02 18:22:18 humph Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <stdlib.h>
          #include <ctype.h>
          #include <inttypes.h>
          
          #include <rtems/bspIo.h>
          #include <rtems/score/timespec.h>
          
          #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           /* We print to 1/10's of milliseconds */
           #define NANOSECONDS_DIVIDER 1000
           #define PERCENT_FMT "%04" PRId32
           #define NANOSECONDS_FMT "%06" PRId32
          #endif
          
          /*
           * This directive allows a thread to print the statistics information
           * on ALL period instances which have non-zero counts using printk.
           *
           * The implementation of this directive straddles the fence between
           * inside and outside of RTEMS. It is presented as part of the Manager
           * but actually uses other services of the Manager.
           */
      41  void rtems_rate_monotonic_report_statistics_with_plugin(  
           void *context,  
           rtems_printk_plugin_t print
           )
          {
           rtems_status_code status;
           rtems_id id;
           rtems_rate_monotonic_period_statistics the_stats;
           rtems_rate_monotonic_period_status the_status;
           char name[5];
          
           if (   !print  )
           return;
          
           (  *print )(   context,   "Period information by period\n"  );
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           (  *print )(   context,   "--- CPU times are in seconds ---\n"  );
           (  *print )(   context,   "--- Wall times are in seconds ---\n"  );
           #endif
          /*
          Layout by columns -- in memory of Hollerith : )
          
          1234567890123456789012345678901234567890123456789012345678901234567890123456789\
           ID OWNER COUNT MISSED X
          ididididid NNNN ccccc mmmmmm X
          
           Uncomment the following if you are tinkering with the formatting.
           Be sure to test the various cases.
           (  *print )(   context,  "\
          1234567890123456789012345678901234567890123456789012345678901234567890123456789\
          \n" );
          */
           (  *print )(   context,   " ID OWNER COUNT MISSED "
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           " "
           #endif
           "CPU TIME "
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           " "
           #endif
           " WALL TIME\n"
            );
           (  *print )(   context,   " "
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           " "
           #endif
           "MIN/MAX/AVG "
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           " "
           #endif
           " MIN/MAX/AVG\n"
            );
          
           /*
           * Cycle through all possible ids and try to report on each one. If it
           * is a period that is inactive,   we just get an error back. No big deal.
           */
           for (   id=_Rate_monotonic_Information.minimum_id ;
           id <= _Rate_monotonic_Information.maximum_id ;
           id++  ) {
           status = rtems_rate_monotonic_get_statistics(   id,   &the_stats  );
           if (   status != RTEMS_SUCCESSFUL  )
           continue;
          
           /* If the above passed,   so should this but check it anyway */
           status = rtems_rate_monotonic_get_status(   id,   &the_status  );
           #if defined(  RTEMS_DEBUG )
           if (   status != RTEMS_SUCCESSFUL  )
           continue;
           #endif
          
           rtems_object_get_name(   the_status.owner,   sizeof(  name ),   name  );
          
           /*
           * Print part of report line that is not dependent on granularity
           */
           (  *print )(   context,  
           "0x%08" PRIx32 " %4s %5" PRId32 " %6" PRId32 " ",  
           id,   name,  
           the_stats.count,   the_stats.missed_count
            );
          
           /*
           * If the count is zero,   don't print statistics
           */
           if (  the_stats.count == 0 ) {
           (  *print )(   context,   "\n"  );
           continue;
           }
          
           /*
           * print CPU Usage part of statistics
           */
           {
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           struct timespec cpu_average;
           struct timespec *min_cpu = &the_stats.min_cpu_time;
           struct timespec *max_cpu = &the_stats.max_cpu_time;
           struct timespec *total_cpu = &the_stats.total_cpu_time;
          
           _Timespec_Divide_by_integer(   total_cpu,   the_stats.count,   &cpu_average  );
           (  *print )(   context,  
           "%" PRId32 "." NANOSECONDS_FMT "/" /* min cpu time */
           "%" PRId32 "." NANOSECONDS_FMT "/" /* max cpu time */
           "%" PRId32 "." NANOSECONDS_FMT " ",   /* avg cpu time */
           _Timespec_Get_seconds(   min_cpu  ),  
           _Timespec_Get_nanoseconds(   min_cpu  ) / NANOSECONDS_DIVIDER,  
           _Timespec_Get_seconds(   max_cpu  ),  
           _Timespec_Get_nanoseconds(   max_cpu  ) / NANOSECONDS_DIVIDER,  
           _Timespec_Get_seconds(   &cpu_average  ),  
           _Timespec_Get_nanoseconds(   &cpu_average  ) / NANOSECONDS_DIVIDER
            );
           #else
           uint32_t ival_cpu,   fval_cpu;
          
           ival_cpu = the_stats.total_cpu_time * 100 / the_stats.count;
           fval_cpu = ival_cpu % 100;
           ival_cpu /= 100;
          
           (  *print )(   context,  
           "%3" PRId32 "/%4" PRId32 "/%3" PRId32 ".%02" PRId32 " ",  
           the_stats.min_cpu_time,   the_stats.max_cpu_time,   ival_cpu,   fval_cpu
            );
           #endif
           }
          
           /*
           * print wall time part of statistics
           */
           {
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           struct timespec wall_average;
           struct timespec *min_wall = &the_stats.min_wall_time;
           struct timespec *max_wall = &the_stats.max_wall_time;
           struct timespec *total_wall = &the_stats.total_wall_time;
          
           _Timespec_Divide_by_integer(  total_wall,   the_stats.count,   &wall_average );
           (  *print )(   context,  
           "%" PRId32 "." NANOSECONDS_FMT "/" /* min wall time */
           "%" PRId32 "." NANOSECONDS_FMT "/" /* max wall time */
           "%" PRId32 "." NANOSECONDS_FMT "\n",   /* avg wall time */
           _Timespec_Get_seconds(   min_wall  ),  
           _Timespec_Get_nanoseconds(   min_wall  ) / NANOSECONDS_DIVIDER,  
           _Timespec_Get_seconds(   max_wall  ),  
           _Timespec_Get_nanoseconds(   max_wall  ) / NANOSECONDS_DIVIDER,  
           _Timespec_Get_seconds(   &wall_average  ),  
           _Timespec_Get_nanoseconds(   &wall_average  ) / NANOSECONDS_DIVIDER
            );
           #else
           uint32_t ival_wall,   fval_wall;
          
           ival_wall = the_stats.total_wall_time * 100 / the_stats.count;
           fval_wall = ival_wall % 100;
           ival_wall /= 100;
           (  *print )(   context,  
           "%3" PRId32 "/%4" PRId32 "/%3" PRId32 ".%02" PRId32 "\n",  
           the_stats.min_wall_time,   the_stats.max_wall_time,   ival_wall,   fval_wall
            );
           #endif
           }
           }
          }
          
     204  void rtems_rate_monotonic_report_statistics(   void  )
          {
           rtems_rate_monotonic_report_statistics_with_plugin(   NULL,   printk_plugin  );
          }

rtems/src/ratemonresetall.c

       1  /*
           * Rate Monotonic Manager -- Reset Statistics for All Periods
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemonresetall.c,  v 1.2 2007/05/17 22:46:45 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/score/thread.h>
          
          /*
           * rtems_rate_monotonic_reset_all_statistics
           */
      28  void rtems_rate_monotonic_reset_all_statistics(   void  )
          {
           Objects_Id id;
           rtems_status_code status;
          
           /*
           * Prevent allocation or deallocation of any of the periods while
           * we are cycling. Also this is an optimization which ensures that
           * we only disable/enable once. The call to
           * rtems_rate_monotonic_reset_statistics will be in a nested dispatch
           * disabled critical section.
           */
           _Thread_Disable_dispatch(   );
          
           /*
           * Cycle through all possible ids and try to reset each one. If it
           * is a period that is inactive,   we just get an error back. No big deal.
           */
           for (   id=_Rate_monotonic_Information.minimum_id ;
           id <= _Rate_monotonic_Information.maximum_id ;
           id++  ) {
           status = rtems_rate_monotonic_reset_statistics(   id  );
           }
          
           /*
           * Done so exit thread dispatching disabled critical section.
           */
           _Thread_Enable_dispatch(   );
          }

rtems/src/ratemonresetstatistics.c

       1  /*
           * Rate Monotonic Manager -- Reset Statistics
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemonresetstatistics.c,  v 1.4 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * rtems_rate_monotonic_reset_statistics
           *
           * This directive allows a thread to reset the statistics information
           * on a specific period instance.
           *
           * Input parameters:
           * id - rate monotonic id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           *
           */
          
      42  rtems_status_code rtems_rate_monotonic_reset_statistics(  
           rtems_id id
           )
          {
           Objects_Locations location;
           Rate_monotonic_Control *the_period;
          
           the_period = _Rate_monotonic_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _Rate_monotonic_Reset_statistics(   the_period  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/ratemontimeout.c

       1  /*
           * Rate Monotonic Manager -- Period End Timeout Handler
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ratemontimeout.c,  v 1.10 2009/10/30 17:54:29 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * _Rate_monotonic_Timeout
           *
           * This routine processes a period ending. If the owning thread
           * is waiting for the period,   that thread is unblocked and the
           * period reinitiated. Otherwise,   the period is expired.
           * This routine is called by the watchdog handler.
           *
           * Input parameters:
           * id - period id
           *
           * Output parameters: NONE
           */
          
      41  void _Rate_monotonic_Timeout(  
           Objects_Id id,  
           void *ignored
           )
          {
           Rate_monotonic_Control *the_period;
           Objects_Locations location;
           Thread_Control *the_thread;
          
           /*
           * When we get here,   the Timer is already off the chain so we do not
           * have to worry about that -- hence no _Watchdog_Remove(   ).
           */
           the_period = _Rate_monotonic_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           the_thread = the_period->owner;
           if (   _States_Is_waiting_for_period(   the_thread->current_state  ) &&
           the_thread->Wait.id == the_period->Object.id  ) {
           _Thread_Unblock(   the_thread  );
          
           _Rate_monotonic_Initiate_statistics(   the_period  );
          
           _Watchdog_Insert_ticks(   &the_period->Timer,   the_period->next_length  );
           } else if (   the_period->state == RATE_MONOTONIC_OWNER_IS_BLOCKING  ) {
           the_period->state = RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING;
          
           _Rate_monotonic_Initiate_statistics(   the_period  );
          
           _Watchdog_Insert_ticks(   &the_period->Timer,   the_period->next_length  );
           } else
           the_period->state = RATE_MONOTONIC_EXPIRED;
           _Thread_Unnest_dispatch(   );
           break;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* impossible */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          }

rtems/src/region.c

       1  /*
           * Region Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: region.c,  v 1.27 2009/01/06 05:02:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * _Region_Manager_initialization
           *
           * This routine initializes all region manager related data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      41  void _Region_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_Region_Information,   /* object information table */
           OBJECTS_CLASSIC_API,   /* object API */
           OBJECTS_RTEMS_REGIONS,   /* object class */
           Configuration_RTEMS_API.maximum_regions,  
           /* maximum objects of this class */
           sizeof(   Region_Control  ),   /* size of this object's control block */
           false,   /* true if the name is a string */
           RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          
           /*
           * Register the MP Process Packet routine.
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
           _MPCI_Register_packet_processor(  
           MP_PACKET_REGION,  
           0 /* XXX _Region_MP_Process_packet */
            );
          #endif
          
          }

rtems/src/regioncreate.c

       1  /*
           * Region Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regioncreate.c,  v 1.14 2010/08/09 08:24:41 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * rtems_region_create
           *
           * This directive creates a region of physical contiguous memory area
           * from which variable sized segments can be allocated.
           *
           * Input parameters:
           * name - user defined region name
           * starting_address - physical start address of region
           * length - physical length in bytes
           * page_size - page size in bytes
           * attribute_set - region attributes
           * id - address of region id to set
           *
           * Output parameters:
           * id - region id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      50  rtems_status_code rtems_region_create(  
           rtems_name name,  
           void *starting_address,  
           uintptr_t length,  
           uintptr_t page_size,  
           rtems_attribute attribute_set,  
           rtems_id *id
           )
          {
           rtems_status_code return_status;
           Region_Control *the_region;
          
           if (   !rtems_is_name_valid(   name  )  )
           return RTEMS_INVALID_NAME;
          
           if (   !starting_address  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !id  )
           return RTEMS_INVALID_ADDRESS;
          
           _RTEMS_Lock_allocator(   ); /* to prevent deletion */
          
           the_region = _Region_Allocate(   );
          
           if (   !the_region  )
           return_status = RTEMS_TOO_MANY;
          
           else {
          
           the_region->maximum_segment_size = _Heap_Initialize(  
           &the_region->Memory,   starting_address,   length,   page_size
            );
          
           if (   !the_region->maximum_segment_size  ) {
           _Region_Free(   the_region  );
           return_status = RTEMS_INVALID_SIZE;
           }
          
           else {
          
           the_region->starting_address = starting_address;
           the_region->length = length;
           the_region->page_size = page_size;
           the_region->attribute_set = attribute_set;
           the_region->number_of_used_blocks = 0;
          
           _Thread_queue_Initialize(  
           &the_region->Wait_queue,  
           _Attributes_Is_priority(   attribute_set  ) ?
           THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,  
           STATES_WAITING_FOR_SEGMENT,  
           RTEMS_TIMEOUT
            );
          
           _Objects_Open(  
           &_Region_Information,  
           &the_region->Object,  
           (  Objects_Name ) name
            );
          
           *id = the_region->Object.id;
           return_status = RTEMS_SUCCESSFUL;
           }
           }
          
           _RTEMS_Unlock_allocator(   );
           return return_status;
          }

rtems/src/regiondata.c

       1  /*
           * Region Manager -- Instantiate Data
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regiondata.c,  v 1.1 2007/05/21 23:19:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate RTEMS Region data */
          #define RTEMS_REGION_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/rtems/region.h>

rtems/src/regiondelete.c

       1  /*
           * Region Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regiondelete.c,  v 1.12 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * rtems_region_delete
           *
           * This directive allows a thread to delete a region specified by
           * the region identifier,   provided that none of its segments are
           * still allocated.
           *
           * Input parameters:
           * id - region id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      45  rtems_status_code rtems_region_delete(  
           rtems_id id
           )
          {
           Objects_Locations location;
           rtems_status_code return_status;
           Region_Control *the_region;
          
           _RTEMS_Lock_allocator(   );
          
           the_region = _Region_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _Region_Debug_Walk(   the_region,   5  );
           if (   the_region->number_of_used_blocks != 0  )
           return_status = RTEMS_RESOURCE_IN_USE;
           else {
           _Objects_Close(   &_Region_Information,   &the_region->Object  );
           _Region_Free(   the_region  );
           return_status = RTEMS_SUCCESSFUL;
           }
           break;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* this error cannot be returned */
           break;
          #endif
          
           case OBJECTS_ERROR:
           default:
           return_status = RTEMS_INVALID_ID;
           break;
           }
          
           _RTEMS_Unlock_allocator(   );
           return return_status;
          }

rtems/src/regionextend.c

       1  /*
           * Region Manager - Extend (  add memory to ) a Region
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regionextend.c,  v 1.17 2010/06/07 09:35:01 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * rtems_region_extend
           *
           * This directive attempts to grow a region of physical contiguous memory area
           * from which variable sized segments can be allocated.
           *
           * Input parameters:
           * id - id of region to grow
           * start - starting address of memory area for extension
           * length - physical length in bytes to grow the region
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      45  rtems_status_code rtems_region_extend(  
           rtems_id id,  
           void *starting_address,  
           uintptr_t length
           )
          {
           uintptr_t amount_extended;
           bool extend_ok;
           Objects_Locations location;
           rtems_status_code return_status;
           Region_Control *the_region;
          
           if (   !starting_address  )
           return RTEMS_INVALID_ADDRESS;
          
           _RTEMS_Lock_allocator(   ); /* to prevent deletion */
          
           the_region = _Region_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           extend_ok = _Heap_Extend(  
           &the_region->Memory,  
           starting_address,  
           length,  
           &amount_extended
            );
          
           if (   extend_ok  ) {
           the_region->length += amount_extended;
           the_region->maximum_segment_size += amount_extended;
           return_status = RTEMS_SUCCESSFUL;
           } else {
           return_status = RTEMS_INVALID_ADDRESS;
           }
           break;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* this error cannot be returned */
           break;
          #endif
          
           case OBJECTS_ERROR:
           default:
           return_status = RTEMS_INVALID_ID;
           break;
           }
          
           _RTEMS_Unlock_allocator(   );
           return return_status;
          }

rtems/src/regiongetfreeinfo.c

       1  /*
           * Region Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regiongetfreeinfo.c,  v 1.9 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/apimutex.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * rtems_region_get_free_information
           *
           * This directive will return information about the free blocks
           * in the region specified. Information about the used blocks
           * will be returned as zero.
           *
           * Input parameters:
           * id - region id
           * the_info - pointer to region information block
           *
           * Output parameters:
           * *the_info - region information block filled in
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      47  rtems_status_code rtems_region_get_free_information(  
           rtems_id id,  
           Heap_Information_block *the_info
           )
          {
           Objects_Locations location;
           rtems_status_code return_status;
           register Region_Control *the_region;
          
           if (   !the_info  )
           return RTEMS_INVALID_ADDRESS;
          
           _RTEMS_Lock_allocator(   );
          
           the_region = _Region_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           the_info->Used.number = 0;
           the_info->Used.total = 0;
           the_info->Used.largest = 0;
          
           _Heap_Get_free_information(   &the_region->Memory,   &the_info->Free  );
          
           return_status = RTEMS_SUCCESSFUL;
           break;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* this error cannot be returned */
           break;
          #endif
          
           case OBJECTS_ERROR:
           default:
           return_status = RTEMS_INVALID_ID;
           break;
           }
          
           _RTEMS_Unlock_allocator(   );
           return return_status;
          }

rtems/src/regiongetinfo.c

       1  /*
           * Region Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regiongetinfo.c,  v 1.13 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/apimutex.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * rtems_region_get_information
           *
           * This directive will return information about the region specified.
           *
           * Input parameters:
           * id - region id
           * the_info - pointer to region information block
           *
           * Output parameters:
           * *the_info - region information block filled in
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      45  rtems_status_code rtems_region_get_information(  
           rtems_id id,  
           Heap_Information_block *the_info
           )
          {
           Objects_Locations location;
           rtems_status_code return_status;
           register Region_Control *the_region;
          
           if (   !the_info  )
           return RTEMS_INVALID_ADDRESS;
          
           _RTEMS_Lock_allocator(   );
          
           the_region = _Region_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _Heap_Get_information(   &the_region->Memory,   the_info  );
           return_status = RTEMS_SUCCESSFUL;
           break;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* this error cannot be returned */
           break;
          #endif
          
           case OBJECTS_ERROR:
           default:
           return_status = RTEMS_INVALID_ID;
           break;
           }
          
           _RTEMS_Unlock_allocator(   );
           return return_status;
          }

rtems/src/regiongetsegment.c

       1  /*
           * Region Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regiongetsegment.c,  v 1.17 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * rtems_region_get_segment
           *
           * This directive will obtain a segment from the given region.
           *
           * Input parameters:
           * id - region id
           * size - segment size in bytes
           * option_set - wait option
           * timeout - number of ticks to wait (  0 means wait forever )
           * segment - pointer to segment address
           *
           * Output parameters:
           * segment - pointer to segment address filled in
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      48  rtems_status_code rtems_region_get_segment(  
           rtems_id id,  
           uintptr_t size,  
           rtems_option option_set,  
           rtems_interval timeout,  
           void **segment
           )
          {
           Thread_Control *executing;
           Objects_Locations location;
           rtems_status_code return_status;
           Region_Control *the_region;
           void *the_segment;
          
           if (   !segment  )
           return RTEMS_INVALID_ADDRESS;
          
           *segment = NULL;
          
           if (   size == 0  )
           return RTEMS_INVALID_SIZE;
          
           _RTEMS_Lock_allocator(   );
          
           executing = _Thread_Executing;
           the_region = _Region_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   size > the_region->maximum_segment_size  )
           return_status = RTEMS_INVALID_SIZE;
          
           else {
           _Region_Debug_Walk(   the_region,   1  );
          
           the_segment = _Region_Allocate_segment(   the_region,   size  );
          
           _Region_Debug_Walk(   the_region,   2  );
          
           if (   the_segment  ) {
           the_region->number_of_used_blocks += 1;
           *segment = the_segment;
           return_status = RTEMS_SUCCESSFUL;
           } else if (   _Options_Is_no_wait(   option_set  )  ) {
           return_status = RTEMS_UNSATISFIED;
           } else {
           /*
           * Switch from using the memory allocation mutex to using a
           * dispatching disabled critical section. We have to do this
           * because this thread is going to block.
           */
           _Thread_Disable_dispatch(   );
           _RTEMS_Unlock_allocator(   );
          
           executing->Wait.queue = &the_region->Wait_queue;
           executing->Wait.id = id;
           executing->Wait.count = size;
           executing->Wait.return_argument = segment;
          
           _Thread_queue_Enter_critical_section(   &the_region->Wait_queue  );
          
           _Thread_queue_Enqueue(   &the_region->Wait_queue,   timeout  );
          
           _Thread_Enable_dispatch(   );
          
           return (  rtems_status_code ) executing->Wait.return_code;
           }
           }
           break;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* this error cannot be returned */
           break;
          #endif
          
           case OBJECTS_ERROR:
           default:
           return_status = RTEMS_INVALID_ID;
           break;
           }
          
           _RTEMS_Unlock_allocator(   );
           return return_status;
          }

rtems/src/regiongetsegmentsize.c

       1  /*
           * Region Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regiongetsegmentsize.c,  v 1.18 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * rtems_region_get_segment_size
           *
           * This directive will return the size of the segment indicated
           *
           * Input parameters:
           * id - region id
           * segment - segment address
           * size - pointer to segment size in bytes
           *
           * Output parameters:
           * size - segment size in bytes filled in
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      45  rtems_status_code rtems_region_get_segment_size(  
           rtems_id id,  
           void *segment,  
           uintptr_t *size
           )
          {
           Objects_Locations location;
           rtems_status_code return_status = RTEMS_SUCCESSFUL;
           register Region_Control *the_region;
          
           if (   !segment  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !size  )
           return RTEMS_INVALID_ADDRESS;
          
           _RTEMS_Lock_allocator(   );
          
           the_region = _Region_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   !_Heap_Size_of_alloc_area(   &the_region->Memory,   segment,   size  )  )
           return_status = RTEMS_INVALID_ADDRESS;
           break;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* this error cannot be returned */
           break;
          #endif
          
           case OBJECTS_ERROR:
           return_status = RTEMS_INVALID_ID;
           break;
           }
          
           _RTEMS_Unlock_allocator(   );
           return return_status;
          }

rtems/src/regionident.c

       1  /*
           * Region Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regionident.c,  v 1.10 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * rtems_region_ident
           *
           * This directive returns the system ID associated with
           * the region name.
           *
           * Input parameters:
           * name - user defined region name
           * id - pointer to region id
           *
           * Output parameters:
           * *id - region id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      46  rtems_status_code rtems_region_ident(  
           rtems_name name,  
           rtems_id *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
          
           status = _Objects_Name_to_id_u32(  
           &_Region_Information,  
           name,  
           OBJECTS_SEARCH_LOCAL_NODE,  
           id
            );
          
           return _Status_Object_name_errors_to_status[ status ];
          }

rtems/src/regionmp.c

       1  /*
           * Multiprocessing Support for the Region Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regionmp.c,  v 1.21 2009/01/06 05:02:25 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/score/mpci.h>
          #include <rtems/score/mppkt.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * _Region_MP_Send_process_packet
           *
           */
          
      35  void _Region_MP_Send_process_packet (  
           Region_MP_Remote_operations operation,  
           Objects_Id region_id,  
           rtems_name name,  
           Objects_Id proxy_id
           )
          {
           Region_MP_Packet *the_packet;
           uint32_t node;
          
           switch (   operation  ) {
          
           case REGION_MP_ANNOUNCE_CREATE:
           case REGION_MP_ANNOUNCE_DELETE:
           case REGION_MP_EXTRACT_PROXY:
          
           the_packet = _Region_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_REGION;
           the_packet->Prefix.length = sizeof (   Region_MP_Packet  );
           the_packet->Prefix.to_convert = sizeof (   Region_MP_Packet  );
           the_packet->operation = operation;
           the_packet->Prefix.id = region_id;
           the_packet->name = name;
           the_packet->proxy_id = proxy_id;
          
           if (   operation == REGION_MP_EXTRACT_PROXY  )
           node = _Objects_Get_node(   region_id  );
           else
           node = MPCI_ALL_NODES;
          
           _MPCI_Send_process_packet(   node,   &the_packet->Prefix  );
           break;
          
           case REGION_MP_GET_SEGMENT_REQUEST:
           case REGION_MP_GET_SEGMENT_RESPONSE:
           case REGION_MP_RETURN_SEGMENT_REQUEST:
           case REGION_MP_RETURN_SEGMENT_RESPONSE:
           break;
           }
          }
          
          /*PAGE
           *
           * _Region_MP_Send_request_packet
           *
           */
          
      82  rtems_status_code _Region_MP_Send_request_packet (  
           Region_MP_Remote_operations operation,  
           Objects_Id region_id,  
           void *segment,  
           intptr_t size,  
           rtems_option option_set,  
           rtems_interval timeout
           )
          {
           Region_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case REGION_MP_GET_SEGMENT_REQUEST:
           case REGION_MP_RETURN_SEGMENT_REQUEST:
          
           the_packet = _Region_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_REGION;
           the_packet->Prefix.length = sizeof (   Region_MP_Packet  );
           the_packet->Prefix.to_convert = sizeof (   Region_MP_Packet  );
           if (   ! _Options_Is_no_wait(  option_set ) )
           the_packet->Prefix.timeout = timeout;
          
           the_packet->operation = operation;
           the_packet->Prefix.id = region_id;
           the_packet->segment = segment;
           the_packet->size = size;
           the_packet->option_set = option_set;
          
           return (  rtems_status_code ) _MPCI_Send_request_packet(  
           _Objects_Get_node(   region_id  ),  
           &the_packet->Prefix,  
           STATES_READY /* Not used */
            );
           break;
          
           case REGION_MP_ANNOUNCE_CREATE:
           case REGION_MP_ANNOUNCE_DELETE:
           case REGION_MP_EXTRACT_PROXY:
           case REGION_MP_GET_SEGMENT_RESPONSE:
           case REGION_MP_RETURN_SEGMENT_RESPONSE:
           break;
          
           }
           /*
           * The following line is included to satisfy compilers which
           * produce warnings when a function does not end with a return.
           */
           return RTEMS_INTERNAL_ERROR;
          }
          
          /*PAGE
           *
           * _Region_MP_Send_response_packet
           *
           */
          
     139  void _Region_MP_Send_response_packet (  
           Region_MP_Remote_operations operation,  
           Objects_Id region_id,  
           Thread_Control *the_thread
           )
          {
           Region_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case REGION_MP_GET_SEGMENT_RESPONSE:
           case REGION_MP_RETURN_SEGMENT_RESPONSE:
          
           the_packet = (   Region_MP_Packet * ) the_thread->receive_packet;
          
          /*
           * The packet being returned already contains the class,   length,   and
           * to_convert fields,   therefore they are not set in this routine.
           */
           the_packet->operation = operation;
           the_packet->Prefix.id = the_packet->Prefix.source_tid;
          
           _MPCI_Send_response_packet(  
           _Objects_Get_node(   the_packet->Prefix.source_tid  ),  
           &the_packet->Prefix
            );
           break;
          
           case REGION_MP_ANNOUNCE_CREATE:
           case REGION_MP_ANNOUNCE_DELETE:
           case REGION_MP_EXTRACT_PROXY:
           case REGION_MP_GET_SEGMENT_REQUEST:
           case REGION_MP_RETURN_SEGMENT_REQUEST:
           break;
          
           }
          }
          
          /*PAGE
           *
           *
           * _Region_MP_Process_packet
           *
           */
          
     184  void _Region_MP_Process_packet (  
           rtems_packet_prefix *the_packet_prefix
           )
          {
           Region_MP_Packet *the_packet;
           Thread_Control *the_thread;
           bool ignored;
          
           the_packet = (  Region_MP_Packet * ) the_packet_prefix;
          
           switch (   the_packet->operation  ) {
          
           case REGION_MP_ANNOUNCE_CREATE:
          
           ignored = _Objects_MP_Allocate_and_open(  
           &_Region_Information,  
           the_packet->name,  
           the_packet->Prefix.id,  
           true
            );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case REGION_MP_ANNOUNCE_DELETE:
          
           _Objects_MP_Close(   &_Region_Information,   the_packet->Prefix.id  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case REGION_MP_EXTRACT_PROXY:
          
           the_thread = _Thread_MP_Find_proxy(   the_packet->proxy_id  );
          
           if (   ! _Thread_Is_null(   the_thread  )  )
           _Thread_queue_Extract(   the_thread->Wait.queue,   the_thread  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case REGION_MP_GET_SEGMENT_REQUEST:
          
           the_packet->Prefix.return_code = rtems_region_get_segment(  
           the_packet->Prefix.id,  
           the_packet->size,  
           the_packet->option_set,  
           the_packet->Prefix.timeout,  
           &the_packet->segment
            );
          
           _Region_MP_Send_response_packet(  
           REGION_MP_GET_SEGMENT_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
          
           case REGION_MP_GET_SEGMENT_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           *(  void ** )the_thread->Wait.return_argument = the_packet->segment;
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case REGION_MP_RETURN_SEGMENT_REQUEST:
          
           the_packet->Prefix.return_code = rtems_region_return_segment(  
           the_packet->Prefix.id,  
           the_packet->segment
            );
          
           _Region_MP_Send_response_packet(  
           REGION_MP_RETURN_SEGMENT_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
          
           case REGION_MP_RETURN_SEGMENT_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           }
          }
          
          /*PAGE
           *
           * _Region_MP_Send_object_was_deleted
           *
           * This routine is not needed by the Region since a region
           * cannot be deleted when segments are in use.
           *
           */
          
          /*PAGE
           *
           * _Region_MP_Send_extract_proxy
           *
           */
          
     290  void _Region_MP_Send_extract_proxy (  
           void *argument
           )
          {
           Thread_Control *the_thread = (  Thread_Control * )argument;
          
           _Region_MP_Send_process_packet(  
           REGION_MP_EXTRACT_PROXY,  
           the_thread->Wait.id,  
           (  rtems_name ) 0,  
           the_thread->Object.id
            );
          }
          
          /*PAGE
           *
           * _Region_MP_Get_packet
           *
           */
          
     310  Region_MP_Packet *_Region_MP_Get_packet (   void  )
          {
           return (   (  Region_MP_Packet * ) _MPCI_Get_packet(   )  );
          }
          
          /* end of file */

rtems/src/regionprocessqueue.c

       1  /*
           * Region Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regionprocessqueue.c,  v 1.3 2009/11/30 15:59:55 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * _Region_Process_queue
           *
           * If enough memory is available to satisfy the rtems_region_get_segment of
           * the first blocked task,   then that task and as many subsequent tasks as
           * possible will be unblocked with their requests satisfied.
           *
           * Input parameters:
           * the_region - the region
           *
           * Output parameters:
           * none
           */
          
      44  void _Region_Process_queue(  
           Region_Control *the_region
           )
          {
           Thread_Control *the_thread;
           void *the_segment;
           /*
           * Switch from using the memory allocation mutex to using a
           * dispatching disabled critical section. We have to do this
           * because this thread may unblock one or more threads that were
           * waiting on memory.
           *
           * NOTE: Be sure to disable dispatching before unlocking the mutex
           * since we do not want to open a window where a context
           * switch could occur.
           */
           _Thread_Disable_dispatch(   );
           _RTEMS_Unlock_allocator(   );
          
           /*
           * NOTE: The following loop is O(  n ) where n is the number of
           * threads whose memory request is satisfied.
           */
           for (   ; ;  ) {
           the_thread = _Thread_queue_First(   &the_region->Wait_queue  );
          
           if (   the_thread == NULL  )
           break;
          
           the_segment = (  void ** ) _Region_Allocate_segment(  
           the_region,  
           the_thread->Wait.count
            );
          
           if (   the_segment == NULL  )
           break;
          
           *(  void ** )the_thread->Wait.return_argument = the_segment;
           the_region->number_of_used_blocks += 1;
           _Thread_queue_Extract(   &the_region->Wait_queue,   the_thread  );
           the_thread->Wait.return_code = RTEMS_SUCCESSFUL;
           }
           _Thread_Enable_dispatch(   );
          }

rtems/src/regionresizesegment.c

       1  /*
           * Region Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regionresizesegment.c,  v 1.12 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * rtems_region_resize_segment
           *
           * This directive will try to resize segment to the new size 'size'
           * "in place".
           *
           * Input parameters:
           * id - region id
           * segment - pointer to segment address
           * size - new required size
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      46  rtems_status_code rtems_region_resize_segment(  
           rtems_id id,  
           void *segment,  
           uintptr_t size,  
           uintptr_t *old_size
           )
          {
           uintptr_t avail_size;
           Objects_Locations location;
           uintptr_t osize;
           rtems_status_code return_status;
           Heap_Resize_status status;
           register Region_Control *the_region;
          
           if (   !old_size  )
           return RTEMS_INVALID_ADDRESS;
          
           _RTEMS_Lock_allocator(   );
          
           the_region = _Region_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           _Region_Debug_Walk(   the_region,   7  );
          
           status = _Heap_Resize_block(  
           &the_region->Memory,  
           segment,  
           (  uint32_t ) size,  
           &osize,  
           &avail_size
            );
           *old_size = (  uint32_t ) osize;
          
           _Region_Debug_Walk(   the_region,   8  );
          
           if (   status == HEAP_RESIZE_SUCCESSFUL  )
           _Region_Process_queue(   the_region  ); /* unlocks allocator */
           else
           _RTEMS_Unlock_allocator(   );
          
          
           if (  status == HEAP_RESIZE_SUCCESSFUL )
           return RTEMS_SUCCESSFUL;
           if (  status == HEAP_RESIZE_UNSATISFIED )
           return RTEMS_UNSATISFIED;
           return RTEMS_INVALID_ADDRESS;
           break;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* this error cannot be returned */
           break;
          #endif
          
           case OBJECTS_ERROR:
           default:
           return_status = RTEMS_INVALID_ID;
           break;
           }
          
           _RTEMS_Unlock_allocator(   );
           return return_status;
          }

rtems/src/regionreturnsegment.c

       1  /*
           * Region Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: regionreturnsegment.c,  v 1.19 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef RTEMS_REGION_SHRED_ON_FREE
          #include <string.h>
          
          #ifndef RTEMS_REGION_FREE_SHRED_PATTERN
          #define RTEMS_REGION_FREE_SHRED_PATTERN 0x00
          #endif
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/region.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * rtems_region_return_segment
           *
           * This directive will return a segment to its region.
           *
           * Input parameters:
           * id - region id
           * segment - pointer to segment address
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      52  rtems_status_code rtems_region_return_segment(  
           rtems_id id,  
           void *segment
           )
          {
           Objects_Locations location;
           rtems_status_code return_status;
          #ifdef RTEMS_REGION_FREE_SHRED_PATTERN
           uint32_t size;
          #endif
           int status;
           register Region_Control *the_region;
          
           _RTEMS_Lock_allocator(   );
          
           the_region = _Region_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
          
           _Region_Debug_Walk(   the_region,   3  );
          
          #ifdef RTEMS_REGION_FREE_SHRED_PATTERN
           if (   !_Heap_Size_of_alloc_area(   &the_region->Memory,   segment,   &size  )  )
           return_status = RTEMS_INVALID_ADDRESS;
           else {
           memset(   segment,   (  RTEMS_REGION_FREE_SHRED_PATTERN & 0xFF ),   size  );
          #endif
           status = _Region_Free_segment(   the_region,   segment  );
          
           _Region_Debug_Walk(   the_region,   4  );
          
           if (   !status  )
           return_status = RTEMS_INVALID_ADDRESS;
           else {
           the_region->number_of_used_blocks -= 1;
          
           _Region_Process_queue(  the_region ); /* unlocks allocator */
          
           return RTEMS_SUCCESSFUL;
           }
          #ifdef RTEMS_REGION_FREE_SHRED_PATTERN
           }
          #endif
           break;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* this error cannot be returned */
           break;
          #endif
          
           case OBJECTS_ERROR:
           default:
           return_status = RTEMS_INVALID_ID;
           break;
           }
          
           _RTEMS_Unlock_allocator(   );
           return return_status;
          }

rtems/src/rtclock.c

       1  /*
           * Clock Manager
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtclock.c,  v 1.14 2005/01/18 09:03:44 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /* No initialization routine */

rtems/src/rtemsbuildid.c

       1  /*
           * RTEMS Object Helper -- Build an Object Id
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsbuildid.c,  v 1.2 2009/11/30 15:59:55 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/types.h>
          
          #undef rtems_build_id
      23  rtems_id rtems_build_id(  
           uint32_t api,  
           uint32_t class,  
           uint32_t node,  
           uint32_t index
           )
          {
           return _Objects_Build_id(   api,   class,   node,   index  );
          }

rtems/src/rtemsbuildname.c

       1  /*
           * RTEMS Object Helper -- Build an Object Name
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsbuildname.c,  v 1.2 2009/11/30 15:59:55 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/types.h>
          
          #undef rtems_build_name
      23  rtems_name rtems_build_name(  
           char C1,  
           char C2,  
           char C3,  
           char C4
           )
          {
           return _Objects_Build_name(   C1,   C2,   C3,   C4  );
          }

rtems/src/rtemsobjectapimaximumclass.c

       1  /*
           * RTEMS Object Helper -- Get Greatest Valid Class for an API
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectapimaximumclass.c,  v 1.3 2009/11/23 14:53:04 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/types.h>
          
      22  int rtems_object_api_maximum_class(  
           int api
           )
          {
           return _Objects_API_maximum_class(  api );
          }

rtems/src/rtemsobjectapiminimumclass.c

       1  /*
           * RTEMS Object Helper -- Get Least Valid Class for an API
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectapiminimumclass.c,  v 1.1 2008/01/29 21:52:20 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/types.h>
          
      22  uint32_t rtems_object_api_minimum_class(  
           uint32_t api
           )
          {
           if (   _Objects_Is_api_valid(   api  )  )
           return 1;
           return -1;
          }

rtems/src/rtemsobjectgetapiclassname.c

       1  /*
           * RTEMS Object Helper -- Obtain Name of API
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectgetapiclassname.c,  v 1.8 2010/06/18 03:03:22 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/object.h>
          
          #include <rtems/assoc.h>
          
          rtems_assoc_t rtems_object_api_internal_assoc[] = {
           { "Thread",   OBJECTS_INTERNAL_THREADS,   0},  
           { "Mutex",   OBJECTS_INTERNAL_MUTEXES,   0},  
          };
          
          rtems_assoc_t rtems_object_api_classic_assoc[] = {
           { "Task",   OBJECTS_RTEMS_TASKS,   0},  
           { "Timer",   OBJECTS_RTEMS_TIMERS,   0},  
           { "Semaphore",   OBJECTS_RTEMS_SEMAPHORES,   0},  
           { "Message Queue",   OBJECTS_RTEMS_MESSAGE_QUEUES,   0},  
           { "Partition",   OBJECTS_RTEMS_PARTITIONS,   0},  
           { "Region",   OBJECTS_RTEMS_REGIONS,   0},  
           { "Port",   OBJECTS_RTEMS_PORTS,   0},  
           { "Period",   OBJECTS_RTEMS_PERIODS,   0},  
           { "Extension",   OBJECTS_RTEMS_EXTENSIONS,   0},  
           { "Barrier",   OBJECTS_RTEMS_BARRIERS,   0},  
          };
          
          #ifdef RTEMS_POSIX_API
          rtems_assoc_t rtems_object_api_posix_assoc[] = {
           { "Thread",   OBJECTS_POSIX_THREADS,   0},  
           { "Key",   OBJECTS_POSIX_KEYS,   0},  
           { "Interrupt",   OBJECTS_POSIX_INTERRUPTS,   0},  
           { "Queued fd",   OBJECTS_POSIX_MESSAGE_QUEUE_FDS,   0},  
           { "Message Queue",   OBJECTS_POSIX_MESSAGE_QUEUES,   0},  
           { "Mutex",   OBJECTS_POSIX_MUTEXES,   0},  
           { "Semaphore",   OBJECTS_POSIX_SEMAPHORES,   0},  
           { "Condition Variable",   OBJECTS_POSIX_CONDITION_VARIABLES,   0},  
           { "Timer",   OBJECTS_POSIX_TIMERS,   0},  
           { "Barrier",   OBJECTS_POSIX_BARRIERS,   0},  
           { "Spinlock",   OBJECTS_POSIX_SPINLOCKS,   0},  
           { "RWLock",   OBJECTS_POSIX_RWLOCKS,   0},  
          };
          #endif
          
      59  const char *rtems_object_get_api_class_name(  
           int the_api,  
           int the_class
           )
          {
           const rtems_assoc_t *api_assoc;
           const rtems_assoc_t *class_assoc;
          
           if (   the_api == OBJECTS_INTERNAL_API  )
           api_assoc = rtems_object_api_internal_assoc;
           else if (   the_api == OBJECTS_CLASSIC_API  )
           api_assoc = rtems_object_api_classic_assoc;
          #ifdef RTEMS_POSIX_API
           else if (   the_api == OBJECTS_POSIX_API  )
           api_assoc = rtems_object_api_posix_assoc;
          #endif
           else
           return "BAD API";
           class_assoc = rtems_assoc_ptr_by_local(   api_assoc,   the_class  );
           if (   class_assoc  )
           return class_assoc->name;
           return "BAD CLASS";
          }

rtems/src/rtemsobjectgetapiname.c

       1  /*
           * RTEMS Object Helper -- Obtain Name of API
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectgetapiname.c,  v 1.5 2010/06/18 04:05:05 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/object.h>
          
          #include <rtems/assoc.h>
          
          rtems_assoc_t rtems_objects_api_assoc[] = {
           { "Internal",   OBJECTS_INTERNAL_API,   0},  
           { "Classic",   OBJECTS_CLASSIC_API,   0},  
           { "POSIX",   OBJECTS_POSIX_API,   0},  
           { 0,   0,   0 }
          };
          
      31  const char *rtems_object_get_api_name(  
           int api
           )
          {
           const rtems_assoc_t *api_assoc;
          
           api_assoc = rtems_assoc_ptr_by_local(   rtems_objects_api_assoc,   api  );
           if (   api_assoc  )
           return api_assoc->name;
           return "BAD CLASS";
          }
          

rtems/src/rtemsobjectgetclassicname.c

       1  /*
           * RTEMS ID To Name Lookup
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectgetclassicname.c,  v 1.1 2008/01/29 21:52:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/types.h>
          
          /*PAGE
           *
           * rtems_object_get_classic_name
           *
           * This directive returns the name associated with the specified
           * object ID.
           *
           * Input parameters:
           * id - message queue id
           *
           * Output parameters:
           * *name - user defined object name
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      40  rtems_status_code rtems_object_get_classic_name(  
           rtems_id id,  
           rtems_name *name
           )
          {
           Objects_Name_or_id_lookup_errors status;
           Objects_Name name_u;
          
           if (   !name  )
           return RTEMS_INVALID_ADDRESS;
          
           status = _Objects_Id_to_name(   id,   &name_u  );
          
           *name = name_u.name_u32;
           return _Status_Object_name_errors_to_status[ status ];
          }

rtems/src/rtemsobjectgetclassinfo.c

       1  /*
           * RTEMS Object Helper -- Get Information on Class
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectgetclassinfo.c,  v 1.4 2009/11/23 14:53:04 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/object.h>
          
      23  rtems_status_code rtems_object_get_class_information(  
           int the_api,  
           int the_class,  
           rtems_object_api_class_information *info
           )
          {
           Objects_Information *obj_info;
           int unallocated;
           int i;
          
           /*
           * Validate parameters and look up information structure.
           */
           if (   !info  )
           return RTEMS_INVALID_ADDRESS;
          
           obj_info = _Objects_Get_information(   the_api,   the_class  );
           if (   !obj_info  )
           return RTEMS_INVALID_NUMBER;
          
           /*
           * Return information about this object class to the user.
           */
           info->minimum_id = obj_info->minimum_id;
           info->maximum_id = obj_info->maximum_id;
           info->auto_extend = obj_info->auto_extend;
           info->maximum = obj_info->maximum;
          
           for (   unallocated=0,   i=1 ; i <= info->maximum ; i++  )
           if (   !obj_info->local_table[i]  )
           unallocated++;
          
           info->unallocated = unallocated;
          
           return RTEMS_SUCCESSFUL;
          }
          

rtems/src/rtemsobjectgetname.c

       1  /*
           * RTEMS Object Helper -- Obtain Name of Object as String
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectgetname.c,  v 1.3 2009/11/30 15:59:55 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          
          /*
           * This method obtain the name of an object and returns its name
           * in the form of a C string. It attempts to be careful about
           * overflowing the user's string and about returning unprintable characters.
           */
      26  char *rtems_object_get_name(  
           Objects_Id id,  
           size_t length,  
           char *name
           )
          {
           return _Objects_Get_name_as_string(   id,   length,   name  );
          }

rtems/src/rtemsobjectidapimaximum.c

       1  /*
           * RTEMS Object Helper -- Get Greatest Valid API Number
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectidapimaximum.c,  v 1.3 2010/06/18 04:22:24 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/types.h>
          
          #undef rtems_object_id_api_maximum
      23  int rtems_object_id_api_maximum(  void )
          {
           return OBJECTS_APIS_LAST;
          }

rtems/src/rtemsobjectidapiminimum.c

       1  /*
           * RTEMS Object Helper -- Get Least Valid API Number
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectidapiminimum.c,  v 1.2 2009/11/23 14:53:04 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/types.h>
          
          #undef rtems_object_id_api_minimum
      23  int rtems_object_id_api_minimum(  void )
          {
           return OBJECTS_INTERNAL_API;
          }

rtems/src/rtemsobjectidgetapi.c

       1  /*
           * RTEMS Object Helper -- Extract API From Id
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectidgetapi.c,  v 1.3 2009/11/30 15:59:56 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/types.h>
          
          #undef rtems_object_id_get_api
      23  int rtems_object_id_get_api(  
           rtems_id id
           )
          {
           return _Objects_Get_API(   id  );
          }

rtems/src/rtemsobjectidgetclass.c

       1  /*
           * RTEMS Object Helper -- Extract Class From Id
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectidgetclass.c,  v 1.3 2009/11/30 15:59:56 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/types.h>
          
          #undef rtems_object_id_get_class
      23  int rtems_object_id_get_class(  
           rtems_id id
           )
          {
           return _Objects_Get_class(   id  );
          }

rtems/src/rtemsobjectidgetindex.c

       1  /*
           * RTEMS Object Helper -- Extract Index From Id
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectidgetindex.c,  v 1.3 2009/11/30 15:59:56 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/types.h>
          
          #undef rtems_object_id_get_index
      23  int rtems_object_id_get_index(  
           rtems_id id
           )
          {
           return _Objects_Get_index(   id  );
          }

rtems/src/rtemsobjectidgetnode.c

       1  /*
           * RTEMS Object Helper -- Extract Node From Id
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectidgetnode.c,  v 1.3 2009/11/30 15:59:56 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/types.h>
          
          #undef rtems_object_id_get_node
      23  int rtems_object_id_get_node(  
           rtems_id id
           )
          {
           return _Objects_Get_node(   id  );
          }

rtems/src/rtemsobjectsetname.c

       1  /*
           * RTEMS Object Helper -- Set Name of Object as String
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsobjectsetname.c,  v 1.3 2009/11/30 15:59:56 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/types.h>
          
          /*
           * This method will set the object name based upon the user string.
           * If the object class uses 32-bit names,   then only the first 4 bytes
           * of the string will be used.
           */
      29  rtems_status_code rtems_object_set_name(  
           rtems_id id,  
           const char *name
           )
          {
           Objects_Information *information;
           Objects_Locations location;
           Objects_Control *the_object;
           Objects_Id tmpId;
          
           if (   !name  )
           return RTEMS_INVALID_ADDRESS;
          
           tmpId = (  id == OBJECTS_ID_OF_SELF ) ? _Thread_Executing->Object.id : id;
          
           information = _Objects_Get_information_id(   tmpId  );
           if (   !information  )
           return RTEMS_INVALID_ID;
          
           the_object = _Objects_Get(   information,   tmpId,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _Objects_Set_name(   information,   the_object,   name  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/rtemstimer.c

       1  /*
           * Timer Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemstimer.c,  v 1.26 2009/11/30 09:08:35 thomas Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _Timer_Manager_initialization
           *
           * This routine initializes all timer manager related data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      40  void _Timer_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_Timer_Information,   /* object information table */
           OBJECTS_CLASSIC_API,   /* object API */
           OBJECTS_RTEMS_TIMERS,   /* object class */
           Configuration_RTEMS_API.maximum_timers ,  
           /* maximum objects of this class */
           sizeof(   Timer_Control  ),   /* size of this object's control block */
           false,   /* true if the name is a string */
           RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          
           /*
           * Initialize the pointer to the default timer server control block to NULL
           * indicating that task-based timer support is not initialized.
           */
          
           _Timer_server = NULL;
          }

rtems/src/rtemstimerdata.c

       1  /*
           * Timer Manager -- Instantiate Data
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemstimerdata.c,  v 1.1 2007/05/21 23:19:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate RTEMS timer data */
          #define RTEMS_TIMER_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/rtems/timer.h>

rtems/src/sem.c

       1  /*
           * Semaphore Manager
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Semaphore Manager.
           * This manager utilizes standard Dijkstra counting semaphores to provide
           * synchronization and mutual exclusion capabilities.
           *
           * Directives provided are:
           *
           * + create a semaphore
           * + get an ID of a semaphore
           * + delete a semaphore
           * + acquire a semaphore
           * + release a semaphore
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: sem.c,  v 1.28 2009/01/06 05:00:45 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/sem.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/score/sysstate.h>
          
          #include <rtems/score/interr.h>
          
          /*PAGE
           *
           * _Semaphore_Manager_initialization
           *
           * This routine initializes all semaphore manager related data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      64  void _Semaphore_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_Semaphore_Information,   /* object information table */
           OBJECTS_CLASSIC_API,   /* object API */
           OBJECTS_RTEMS_SEMAPHORES,   /* object class */
           Configuration_RTEMS_API.maximum_semaphores,  
           /* maximum objects of this class */
           sizeof(   Semaphore_Control  ),   /* size of this object's control block */
           false,   /* true if the name is a string */
           RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           true,   /* true if this is a global object class */
           _Semaphore_MP_Send_extract_proxy /* Proxy extraction support callout */
          #endif
            );
          
           /*
           * Register the MP Process Packet routine.
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
           _MPCI_Register_packet_processor(  
           MP_PACKET_SEMAPHORE,  
           _Semaphore_MP_Process_packet
            );
          #endif
          
          }

rtems/src/semcreate.c

       1  /*
           * Semaphore Manager
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Semaphore Manager.
           * This manager utilizes standard Dijkstra counting semaphores to provide
           * synchronization and mutual exclusion capabilities.
           *
           * Directives provided are:
           *
           * + create a semaphore
           * + get an ID of a semaphore
           * + delete a semaphore
           * + acquire a semaphore
           * + release a semaphore
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semcreate.c,  v 1.23 2009/11/30 15:59:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/sem.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/score/sysstate.h>
          
          #include <rtems/score/interr.h>
          
          /*PAGE
           *
           * rtems_semaphore_create
           *
           * This directive creates a semaphore and sets the initial value based
           * on the given count. A semaphore id is returned.
           *
           * Input parameters:
           * name - user defined semaphore name
           * count - initial count of semaphore
           * attribute_set - semaphore attributes
           * priority_ceiling - semaphore's ceiling priority
           * id - pointer to semaphore id
           *
           * Output parameters:
           * id - semaphore id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      72  rtems_status_code rtems_semaphore_create(  
           rtems_name name,  
           uint32_t count,  
           rtems_attribute attribute_set,  
           rtems_task_priority priority_ceiling,  
           rtems_id *id
           )
          {
           register Semaphore_Control *the_semaphore;
           CORE_mutex_Attributes the_mutex_attr;
           CORE_semaphore_Attributes the_semaphore_attr;
           CORE_mutex_Status mutex_status;
          
           if (   !rtems_is_name_valid(   name  )  )
           return RTEMS_INVALID_NAME;
          
           if (   !id  )
           return RTEMS_INVALID_ADDRESS;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Attributes_Is_global(   attribute_set  )  ) {
          
           if (   !_System_state_Is_multiprocessing  )
           return RTEMS_MP_NOT_CONFIGURED;
          
           if (   _Attributes_Is_inherit_priority(   attribute_set  ) ||
           _Attributes_Is_priority_ceiling(   attribute_set  )  )
           return RTEMS_NOT_DEFINED;
          
           } else
          #endif
          
           if (   _Attributes_Is_inherit_priority(   attribute_set  ) ||
           _Attributes_Is_priority_ceiling(   attribute_set  )  ) {
          
           if (   ! (  _Attributes_Is_binary_semaphore(   attribute_set  ) &&
           _Attributes_Is_priority(   attribute_set  )  )  )
           return RTEMS_NOT_DEFINED;
          
           }
          
           if (   _Attributes_Is_inherit_priority(   attribute_set  ) &&
           _Attributes_Is_priority_ceiling(   attribute_set  )  )
           return RTEMS_NOT_DEFINED;
          
           if (   !_Attributes_Is_counting_semaphore(   attribute_set  ) && (   count > 1  )  )
           return RTEMS_INVALID_NUMBER;
          
           _Thread_Disable_dispatch(   ); /* prevents deletion */
          
           the_semaphore = _Semaphore_Allocate(   );
          
           if (   !the_semaphore  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_TOO_MANY;
           }
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Attributes_Is_global(   attribute_set  ) &&
           ! (   _Objects_MP_Allocate_and_open(   &_Semaphore_Information,   name,  
           the_semaphore->Object.id,   false  )  )  ) {
           _Semaphore_Free(   the_semaphore  );
           _Thread_Enable_dispatch(   );
           return RTEMS_TOO_MANY;
           }
          #endif
          
           the_semaphore->attribute_set = attribute_set;
          
           /*
           * Initialize it as a counting semaphore.
           */
           if (   _Attributes_Is_counting_semaphore(   attribute_set  )  ) {
           /*
           * This effectively disables limit checking.
           */
           the_semaphore_attr.maximum_count = 0xFFFFFFFF;
          
           if (   _Attributes_Is_priority(   attribute_set  )  )
           the_semaphore_attr.discipline = CORE_SEMAPHORE_DISCIPLINES_PRIORITY;
           else
           the_semaphore_attr.discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
          
           /*
           * The following are just to make Purify happy.
           */
           the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
           the_mutex_attr.priority_ceiling = PRIORITY_MINIMUM;
          
           _CORE_semaphore_Initialize(  
           &the_semaphore->Core_control.semaphore,  
           &the_semaphore_attr,  
           count
            );
           } else {
           /*
           * It is either simple binary semaphore or a more powerful mutex
           * style binary semaphore. This is the mutex style.
           */
           if (   _Attributes_Is_priority(   attribute_set  )  )
           the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY;
           else
           the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_FIFO;
          
           if (   _Attributes_Is_binary_semaphore(   attribute_set  )  ) {
           the_mutex_attr.priority_ceiling = priority_ceiling;
           the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
           the_mutex_attr.only_owner_release = false;
          
           if (   the_mutex_attr.discipline == CORE_MUTEX_DISCIPLINES_PRIORITY  ) {
           if (   _Attributes_Is_inherit_priority(   attribute_set  )  ) {
           the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
           the_mutex_attr.only_owner_release = true;
           } else if (   _Attributes_Is_priority_ceiling(   attribute_set  )  ) {
           the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
           the_mutex_attr.only_owner_release = true;
           }
           }
           } else /* must be simple binary semaphore */ {
           the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_BLOCKS;
           the_mutex_attr.only_owner_release = false;
           }
          
           mutex_status = _CORE_mutex_Initialize(  
           &the_semaphore->Core_control.mutex,  
           &the_mutex_attr,  
           (  count == 1 ) ? CORE_MUTEX_UNLOCKED : CORE_MUTEX_LOCKED
            );
          
           if (   mutex_status == CORE_MUTEX_STATUS_CEILING_VIOLATED  ) {
           _Semaphore_Free(   the_semaphore  );
           _Thread_Enable_dispatch(   );
           return RTEMS_INVALID_PRIORITY;
           }
           }
          
           /*
           * Whether we initialized it as a mutex or counting semaphore,   it is
           * now ready to be "offered" for use as a Classic API Semaphore.
           */
           _Objects_Open(  
           &_Semaphore_Information,  
           &the_semaphore->Object,  
           (  Objects_Name ) name
            );
          
           *id = the_semaphore->Object.id;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Attributes_Is_global(   attribute_set  )  )
           _Semaphore_MP_Send_process_packet(  
           SEMAPHORE_MP_ANNOUNCE_CREATE,  
           the_semaphore->Object.id,  
           name,  
           0 /* Not used */
            );
          #endif
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/semdata.c

       1  /*
           * Semaphore Manager -- Data Instantiation
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semdata.c,  v 1.1 2007/05/21 23:19:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate semaphore data */
          #define RTEMS_SEM_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/rtems/sem.h>

rtems/src/semdelete.c

       1  /*
           * Semaphore Manager
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Semaphore Manager.
           * This manager utilizes standard Dijkstra counting semaphores to provide
           * synchronization and mutual exclusion capabilities.
           *
           * Directives provided are:
           *
           * + create a semaphore
           * + get an ID of a semaphore
           * + delete a semaphore
           * + acquire a semaphore
           * + release a semaphore
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semdelete.c,  v 1.11 2007/11/30 21:49:41 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/sem.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/score/sysstate.h>
          
          #include <rtems/score/interr.h>
          
          /*PAGE
           *
           * rtems_semaphore_delete
           *
           * This directive allows a thread to delete a semaphore specified by
           * the semaphore id. The semaphore is freed back to the inactive
           * semaphore chain.
           *
           * Input parameters:
           * id - semaphore id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
          #define SEMAPHORE_MP_OBJECT_WAS_DELETED _Semaphore_MP_Send_object_was_deleted
          #else
          #define SEMAPHORE_MP_OBJECT_WAS_DELETED NULL
          #endif
          
      74  rtems_status_code rtems_semaphore_delete(  
           rtems_id id
           )
          {
           register Semaphore_Control *the_semaphore;
           Objects_Locations location;
          
           the_semaphore = _Semaphore_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   !_Attributes_Is_counting_semaphore(  the_semaphore->attribute_set )  ) {
           if (   _CORE_mutex_Is_locked(   &the_semaphore->Core_control.mutex  ) &&
           !_Attributes_Is_simple_binary_semaphore(  
           the_semaphore->attribute_set  )  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_RESOURCE_IN_USE;
           }
           _CORE_mutex_Flush(  
           &the_semaphore->Core_control.mutex,  
           SEMAPHORE_MP_OBJECT_WAS_DELETED,  
           CORE_MUTEX_WAS_DELETED
            );
           } else {
           _CORE_semaphore_Flush(  
           &the_semaphore->Core_control.semaphore,  
           SEMAPHORE_MP_OBJECT_WAS_DELETED,  
           CORE_SEMAPHORE_WAS_DELETED
            );
           }
          
           _Objects_Close(   &_Semaphore_Information,   &the_semaphore->Object  );
          
           _Semaphore_Free(   the_semaphore  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Attributes_Is_global(   the_semaphore->attribute_set  )  ) {
          
           _Objects_MP_Close(   &_Semaphore_Information,   the_semaphore->Object.id  );
          
           _Semaphore_MP_Send_process_packet(  
           SEMAPHORE_MP_ANNOUNCE_DELETE,  
           the_semaphore->Object.id,  
           0,   /* Not used */
           0 /* Not used */
            );
           }
          #endif
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Dispatch(   );
           return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/semflush.c

       1  /*
           * rtems_semaphore_flush
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the flush directive
           * of the Semaphore Manager.
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semflush.c,  v 1.12 2007/11/30 21:49:41 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/sem.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/score/sysstate.h>
          
          #include <rtems/score/interr.h>
          
          /*PAGE
           *
           * rtems_semaphore_flush
           *
           * This directive allows a thread to flush the threads
           * pending on the semaphore.
           *
           * Input parameters:
           * id - semaphore id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
          #define SEND_OBJECT_WAS_DELETED _Semaphore_MP_Send_object_was_deleted
          #else
          #define SEND_OBJECT_WAS_DELETED NULL
          #endif
          
      64  rtems_status_code rtems_semaphore_flush(  
           rtems_id id
           )
          {
           register Semaphore_Control *the_semaphore;
           Objects_Locations location;
          
           the_semaphore = _Semaphore_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   !_Attributes_Is_counting_semaphore(  the_semaphore->attribute_set )  ) {
           _CORE_mutex_Flush(  
           &the_semaphore->Core_control.mutex,  
           SEND_OBJECT_WAS_DELETED,  
           CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT
            );
           } else {
           _CORE_semaphore_Flush(  
           &the_semaphore->Core_control.semaphore,  
           SEND_OBJECT_WAS_DELETED,  
           CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT
            );
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Dispatch(   );
           return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/semident.c

       1  /*
           * Semaphore Manager
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Semaphore Manager.
           * This manager utilizes standard Dijkstra counting semaphores to provide
           * synchronization and mutual exclusion capabilities.
           *
           * Directives provided are:
           *
           * + create a semaphore
           * + get an ID of a semaphore
           * + delete a semaphore
           * + acquire a semaphore
           * + release a semaphore
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semident.c,  v 1.12 2008/01/23 22:57:43 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/sem.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/score/sysstate.h>
          
          #include <rtems/score/interr.h>
          
          /*PAGE
           *
           * rtems_semaphore_ident
           *
           * This directive returns the system ID associated with
           * the semaphore name.
           *
           * Input parameters:
           * name - user defined semaphore name
           * node - node(  s ) to be searched
           * id - pointer to semaphore id
           *
           * Output parameters:
           * *id - semaphore id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      70  rtems_status_code rtems_semaphore_ident(  
           rtems_name name,  
           uint32_t node,  
           rtems_id *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
          
           status = _Objects_Name_to_id_u32(   &_Semaphore_Information,   name,   node,   id  );
          
           return _Status_Object_name_errors_to_status[ status ];
          }

rtems/src/semmp.c

       1  /*
           * Multiprocessing Support for the Semaphore Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semmp.c,  v 1.21 2009/01/06 05:00:45 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/score/mpci.h>
          #include <rtems/score/mppkt.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/sem.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * _Semaphore_MP_Send_process_packet
           *
           */
          
      36  void _Semaphore_MP_Send_process_packet (  
           Semaphore_MP_Remote_operations operation,  
           Objects_Id semaphore_id,  
           rtems_name name,  
           Objects_Id proxy_id
           )
          {
           Semaphore_MP_Packet *the_packet;
           uint32_t node;
          
           switch (   operation  ) {
          
           case SEMAPHORE_MP_ANNOUNCE_CREATE:
           case SEMAPHORE_MP_ANNOUNCE_DELETE:
           case SEMAPHORE_MP_EXTRACT_PROXY:
          
           the_packet = _Semaphore_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_SEMAPHORE;
           the_packet->Prefix.length = sizeof (   Semaphore_MP_Packet  );
           the_packet->Prefix.to_convert = sizeof (   Semaphore_MP_Packet  );
           the_packet->operation = operation;
           the_packet->Prefix.id = semaphore_id;
           the_packet->name = name;
           the_packet->proxy_id = proxy_id;
          
           if (   operation == SEMAPHORE_MP_EXTRACT_PROXY  )
           node = _Objects_Get_node(   semaphore_id  );
           else
           node = MPCI_ALL_NODES;
          
           _MPCI_Send_process_packet(   node,   &the_packet->Prefix  );
           break;
          
           case SEMAPHORE_MP_OBTAIN_REQUEST:
           case SEMAPHORE_MP_OBTAIN_RESPONSE:
           case SEMAPHORE_MP_RELEASE_REQUEST:
           case SEMAPHORE_MP_RELEASE_RESPONSE:
           break;
           }
          }
          
          /*PAGE
           *
           * _Semaphore_MP_Send_request_packet
           *
           */
          
      83  rtems_status_code _Semaphore_MP_Send_request_packet (  
           Semaphore_MP_Remote_operations operation,  
           Objects_Id semaphore_id,  
           rtems_option option_set,  
           rtems_interval timeout
           )
          {
           Semaphore_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case SEMAPHORE_MP_OBTAIN_REQUEST:
           case SEMAPHORE_MP_RELEASE_REQUEST:
          
           the_packet = _Semaphore_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_SEMAPHORE;
           the_packet->Prefix.length = sizeof (   Semaphore_MP_Packet  );
           the_packet->Prefix.to_convert = sizeof (   Semaphore_MP_Packet  );
           if (   ! _Options_Is_no_wait(  option_set ) )
           the_packet->Prefix.timeout = timeout;
          
           the_packet->operation = operation;
           the_packet->Prefix.id = semaphore_id;
           the_packet->option_set = option_set;
          
           return _MPCI_Send_request_packet(  
           _Objects_Get_node(   semaphore_id  ),  
           &the_packet->Prefix,  
           STATES_WAITING_FOR_SEMAPHORE
            );
           break;
          
           case SEMAPHORE_MP_ANNOUNCE_CREATE:
           case SEMAPHORE_MP_ANNOUNCE_DELETE:
           case SEMAPHORE_MP_EXTRACT_PROXY:
           case SEMAPHORE_MP_OBTAIN_RESPONSE:
           case SEMAPHORE_MP_RELEASE_RESPONSE:
           break;
          
           }
           /*
           * The following line is included to satisfy compilers which
           * produce warnings when a function does not end with a return.
           */
           return RTEMS_SUCCESSFUL;
          }
          
          /*PAGE
           *
           * _Semaphore_MP_Send_response_packet
           *
           */
          
     136  void _Semaphore_MP_Send_response_packet (  
           Semaphore_MP_Remote_operations operation,  
           Objects_Id semaphore_id,  
           Thread_Control *the_thread
           )
          {
           Semaphore_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case SEMAPHORE_MP_OBTAIN_RESPONSE:
           case SEMAPHORE_MP_RELEASE_RESPONSE:
          
           the_packet = (   Semaphore_MP_Packet * ) the_thread->receive_packet;
          
          /*
           * The packet being returned already contains the class,   length,   and
           * to_convert fields,   therefore they are not set in this routine.
           */
           the_packet->operation = operation;
           the_packet->Prefix.id = the_packet->Prefix.source_tid;
          
           _MPCI_Send_response_packet(  
           _Objects_Get_node(   the_packet->Prefix.source_tid  ),  
           &the_packet->Prefix
            );
           break;
          
           case SEMAPHORE_MP_ANNOUNCE_CREATE:
           case SEMAPHORE_MP_ANNOUNCE_DELETE:
           case SEMAPHORE_MP_EXTRACT_PROXY:
           case SEMAPHORE_MP_OBTAIN_REQUEST:
           case SEMAPHORE_MP_RELEASE_REQUEST:
           break;
          
           }
          }
          
          /*PAGE
           *
           *
           * _Semaphore_MP_Process_packet
           *
           */
          
     181  void _Semaphore_MP_Process_packet (  
           rtems_packet_prefix *the_packet_prefix
           )
          {
           Semaphore_MP_Packet *the_packet;
           Thread_Control *the_thread;
           bool ignored;
          
           the_packet = (  Semaphore_MP_Packet * ) the_packet_prefix;
          
           switch (   the_packet->operation  ) {
          
           case SEMAPHORE_MP_ANNOUNCE_CREATE:
          
           ignored = _Objects_MP_Allocate_and_open(  
           &_Semaphore_Information,  
           the_packet->name,  
           the_packet->Prefix.id,  
           true
            );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case SEMAPHORE_MP_ANNOUNCE_DELETE:
          
           _Objects_MP_Close(   &_Semaphore_Information,   the_packet->Prefix.id  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case SEMAPHORE_MP_EXTRACT_PROXY:
          
           the_thread = _Thread_MP_Find_proxy(   the_packet->proxy_id  );
          
           if (   ! _Thread_Is_null(   the_thread  )  )
           _Thread_queue_Extract(   the_thread->Wait.queue,   the_thread  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case SEMAPHORE_MP_OBTAIN_REQUEST:
          
           the_packet->Prefix.return_code = rtems_semaphore_obtain(  
           the_packet->Prefix.id,  
           the_packet->option_set,  
           the_packet->Prefix.timeout
            );
          
           if (   the_packet->Prefix.return_code != RTEMS_PROXY_BLOCKING  )
           _Semaphore_MP_Send_response_packet(  
           SEMAPHORE_MP_OBTAIN_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
          
           case SEMAPHORE_MP_OBTAIN_RESPONSE:
           case SEMAPHORE_MP_RELEASE_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case SEMAPHORE_MP_RELEASE_REQUEST:
          
           the_packet->Prefix.return_code = rtems_semaphore_release(  
           the_packet->Prefix.id
            );
          
           _Semaphore_MP_Send_response_packet(  
           SEMAPHORE_MP_RELEASE_RESPONSE,  
           the_packet->Prefix.id,  
           _Thread_Executing
            );
           break;
           }
          }
          
          /*PAGE
           *
           * _Semaphore_MP_Send_object_was_deleted
           *
           */
          
     267  void _Semaphore_MP_Send_object_was_deleted (  
           Thread_Control *the_proxy
           )
          {
           the_proxy->receive_packet->return_code = RTEMS_OBJECT_WAS_DELETED;
          
           _Semaphore_MP_Send_response_packet(  
           SEMAPHORE_MP_OBTAIN_RESPONSE,  
           the_proxy->Wait.id,  
           the_proxy
            );
          
          }
          
          /*PAGE
           *
           * _Semaphore_MP_Send_extract_proxy
           *
           */
          
     287  void _Semaphore_MP_Send_extract_proxy (  
           void *argument
           )
          {
           Thread_Control *the_thread = (  Thread_Control * )argument;
          
           _Semaphore_MP_Send_process_packet(  
           SEMAPHORE_MP_EXTRACT_PROXY,  
           the_thread->Wait.id,  
           (  rtems_name ) 0,  
           the_thread->Object.id
            );
          
          }
          
          /*PAGE
           *
           * _Semaphore_MP_Get_packet
           *
           */
          
     308  Semaphore_MP_Packet *_Semaphore_MP_Get_packet (   void  )
          {
           return (   (  Semaphore_MP_Packet * ) _MPCI_Get_packet(   )  );
          }
          
          /*PAGE
           *
           * _Semaphore_Core_mutex_mp_support
           *
           * Input parameters:
           * the_thread - the remote thread the semaphore was surrendered to
           * id - id of the surrendered semaphore
           *
           * Output parameters: NONE
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
     325  void _Semaphore_Core_mutex_mp_support (  
           Thread_Control *the_thread,  
           Objects_Id id
           )
          {
           the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL;
          
           _Semaphore_MP_Send_response_packet(  
           SEMAPHORE_MP_OBTAIN_RESPONSE,  
           id,  
           the_thread
            );
          }
          #endif
          
          
          /*PAGE
           *
           * _Semaphore_Core_semaphore_mp_support
           *
           * Input parameters:
           * the_thread - the remote thread the semaphore was surrendered to
           * id - id of the surrendered semaphore
           *
           * Output parameters: NONE
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
     353  void _Semaphore_Core_semaphore_mp_support (  
           Thread_Control *the_thread,  
           Objects_Id id
           )
          {
           the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL;
          
           _Semaphore_MP_Send_response_packet(  
           SEMAPHORE_MP_OBTAIN_RESPONSE,  
           id,  
           the_thread
            );
          }
          #endif
          /* end of file */

rtems/src/semobtain.c

       1  /*
           * Semaphore Manager
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Semaphore Manager.
           * This manager utilizes standard Dijkstra counting semaphores to provide
           * synchronization and mutual exclusion capabilities.
           *
           * Directives provided are:
           *
           * + create a semaphore
           * + get an ID of a semaphore
           * + delete a semaphore
           * + acquire a semaphore
           * + release a semaphore
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semobtain.c,  v 1.16 2009/01/06 05:00:45 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/sem.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/score/sysstate.h>
          
          #include <rtems/score/interr.h>
          
          /*PAGE
           *
           * rtems_semaphore_obtain
           *
           * This directive allows a thread to acquire a semaphore.
           *
           * Input parameters:
           * id - semaphore id
           * option_set - wait option
           * timeout - number of ticks to wait (  0 means wait forever )
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      68  rtems_status_code rtems_semaphore_obtain(  
           rtems_id id,  
           rtems_option option_set,  
           rtems_interval timeout
           )
          {
           register Semaphore_Control *the_semaphore;
           Objects_Locations location;
           ISR_Level level;
          
           the_semaphore = _Semaphore_Get_interrupt_disable(   id,   &location,   &level  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   !_Attributes_Is_counting_semaphore(  the_semaphore->attribute_set )  ) {
           _CORE_mutex_Seize(  
           &the_semaphore->Core_control.mutex,  
           id,  
           (  (  _Options_Is_no_wait(   option_set  ) ) ? false : true ),  
           timeout,  
           level
            );
           return _Semaphore_Translate_core_mutex_return_code(  
           _Thread_Executing->Wait.return_code  );
           }
          
           /* must be a counting semaphore */
           _CORE_semaphore_Seize_isr_disable(  
           &the_semaphore->Core_control.semaphore,  
           id,  
           (  (  _Options_Is_no_wait(   option_set  ) ) ? false : true ),  
           timeout,  
           &level
            );
           return _Semaphore_Translate_core_semaphore_return_code(  
           _Thread_Executing->Wait.return_code  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           return _Semaphore_MP_Send_request_packet(  
           SEMAPHORE_MP_OBTAIN_REQUEST,  
           id,  
           option_set,  
           timeout
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
          
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/semrelease.c

       1  /*
           * Semaphore Manager
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Semaphore Manager.
           * This manager utilizes standard Dijkstra counting semaphores to provide
           * synchronization and mutual exclusion capabilities.
           *
           * Directives provided are:
           *
           * + create a semaphore
           * + get an ID of a semaphore
           * + delete a semaphore
           * + acquire a semaphore
           * + release a semaphore
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semrelease.c,  v 1.9 2007/11/30 21:49:41 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/sem.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/score/sysstate.h>
          
          #include <rtems/score/interr.h>
          
          /*PAGE
           *
           * rtems_semaphore_release
           *
           * This directive allows a thread to release a semaphore.
           *
           * Input parameters:
           * id - semaphore id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
          #define MUTEX_MP_SUPPORT _Semaphore_Core_mutex_mp_support
          #else
          #define MUTEX_MP_SUPPORT NULL
          #endif
          
      72  rtems_status_code rtems_semaphore_release(  
           rtems_id id
           )
          {
           register Semaphore_Control *the_semaphore;
           Objects_Locations location;
           CORE_mutex_Status mutex_status;
           CORE_semaphore_Status semaphore_status;
          
           the_semaphore = _Semaphore_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   !_Attributes_Is_counting_semaphore(  the_semaphore->attribute_set )  ) {
           mutex_status = _CORE_mutex_Surrender(  
           &the_semaphore->Core_control.mutex,  
           id,  
           MUTEX_MP_SUPPORT
            );
           _Thread_Enable_dispatch(   );
           return _Semaphore_Translate_core_mutex_return_code(   mutex_status  );
           } else {
           semaphore_status = _CORE_semaphore_Surrender(  
           &the_semaphore->Core_control.semaphore,  
           id,  
           MUTEX_MP_SUPPORT
            );
           _Thread_Enable_dispatch(   );
           return
           _Semaphore_Translate_core_semaphore_return_code(   semaphore_status  );
           }
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           return _Semaphore_MP_Send_request_packet(  
           SEMAPHORE_MP_RELEASE_REQUEST,  
           id,  
           0,   /* Not used */
           MPCI_DEFAULT_TIMEOUT
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/semtranslatereturncode.c

       1  /*
           * Semaphore Manager
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Semaphore Manager.
           * This manager utilizes standard Dijkstra counting semaphores to provide
           * synchronization and mutual exclusion capabilities.
           *
           * Directives provided are:
           *
           * + create a semaphore
           * + get an ID of a semaphore
           * + delete a semaphore
           * + acquire a semaphore
           * + release a semaphore
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: semtranslatereturncode.c,  v 1.20 2009/05/28 20:38:12 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/attr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/sem.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/score/sysstate.h>
          
          #include <rtems/score/interr.h>
          
          /*PAGE
           *
           * _Semaphore_Translate_core_mutex_return_code
           *
           * Input parameters:
           * status - mutex status code to translate
           *
           * Output parameters:
           * rtems status code - translated RTEMS status code
           *
           */
          
          const rtems_status_code _Semaphore_Translate_core_mutex_return_code_[] = {
           RTEMS_SUCCESSFUL,   /* CORE_MUTEX_STATUS_SUCCESSFUL */
           RTEMS_UNSATISFIED,   /* CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT */
           RTEMS_UNSATISFIED,   /* CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED */
           RTEMS_NOT_OWNER_OF_RESOURCE,   /* CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE */
           RTEMS_OBJECT_WAS_DELETED,   /* CORE_MUTEX_WAS_DELETED */
           RTEMS_TIMEOUT,   /* CORE_MUTEX_TIMEOUT */
          #ifdef __RTEMS_STRICT_ORDER_MUTEX__
           CORE_MUTEX_RELEASE_NOT_ORDER,  
          #endif
           RTEMS_INVALID_PRIORITY /* CORE_MUTEX_STATUS_CEILING_VIOLATED */
          };
          
      77  rtems_status_code _Semaphore_Translate_core_mutex_return_code (  
           uint32_t status
           )
          {
           /*
           * If this thread is blocking waiting for a result on a remote operation.
           */
           #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Thread_Is_proxy_blocking(  status )  )
           return RTEMS_PROXY_BLOCKING;
           #endif
          
           /*
           * Internal consistency check for bad status from SuperCore
           */
           #if defined(  RTEMS_DEBUG )
           if (   status > CORE_MUTEX_STATUS_LAST  )
           return RTEMS_INTERNAL_ERROR;
           #endif
           return _Semaphore_Translate_core_mutex_return_code_[status];
          }
          
          /*PAGE
           *
           * _Semaphore_Translate_core_semaphore_return_code
           *
           * Input parameters:
           * status - semaphore status code to translate
           *
           * Output parameters:
           * rtems status code - translated RTEMS status code
           *
           */
          
          const rtems_status_code _Semaphore_Translate_core_semaphore_return_code_[] = {
           RTEMS_SUCCESSFUL,   /* CORE_SEMAPHORE_STATUS_SUCCESSFUL */
           RTEMS_UNSATISFIED,   /* CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT */
           RTEMS_OBJECT_WAS_DELETED,   /* CORE_SEMAPHORE_WAS_DELETED */
           RTEMS_TIMEOUT,   /* CORE_SEMAPHORE_TIMEOUT */
           RTEMS_INTERNAL_ERROR,   /* CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED */
          };
          
     119  rtems_status_code _Semaphore_Translate_core_semaphore_return_code (  
           uint32_t status
           )
          {
           #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Thread_Is_proxy_blocking(  status )  )
           return RTEMS_PROXY_BLOCKING;
           #endif
           /*
           * Internal consistency check for bad status from SuperCore
           */
           #if defined(  RTEMS_DEBUG )
           if (   status > CORE_SEMAPHORE_STATUS_LAST  )
           return RTEMS_INTERNAL_ERROR;
           #endif
           return _Semaphore_Translate_core_semaphore_return_code_[status];
          }

rtems/src/signal.c

       1  /*
           * Signal Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: signal.c,  v 1.16 2005/01/18 09:03:44 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/asr.h>
          #include <rtems/score/isr.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/rtems/signal.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/tasks.h>
          
          /*PAGE
           *
           * _Signal_Manager_initialization
           *
           * This routine initializes all signal manager related data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      39  void _Signal_Manager_initialization(   void  )
          {
           /*
           * Register the MP Process Packet routine.
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
           _MPCI_Register_packet_processor(  
           MP_PACKET_SIGNAL,  
           _Signal_MP_Process_packet
            );
          #endif
          }

rtems/src/signalcatch.c

       1  /*
           * Signal Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: signalcatch.c,  v 1.5 2005/01/18 09:03:44 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/asr.h>
          #include <rtems/score/isr.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/rtems/signal.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/tasks.h>
          
          /*PAGE
           *
           * rtems_signal_catch
           *
           * This directive allows a thread to specify what action to take when
           * catching signals.
           *
           * Input parameters:
           * handler - address of asynchronous signal routine (  asr )
           * (   NULL indicates asr is invalid  )
           * mode_set - mode value for asr
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - always succeeds
           */
          
      44  rtems_status_code rtems_signal_catch(  
           rtems_asr_entry asr_handler,  
           rtems_mode mode_set
           )
          {
           Thread_Control *executing;
           RTEMS_API_Control *api;
           ASR_Information *asr;
          
          /* XXX normalize mode */
           executing = _Thread_Executing;
           api = (  RTEMS_API_Control* )executing->API_Extensions[ THREAD_API_RTEMS ];
           asr = &api->Signal;
          
           _Thread_Disable_dispatch(   ); /* cannot reschedule while */
           /* the thread is inconsistent */
          
           if (   !_ASR_Is_null_handler(   asr_handler  )  ) {
           asr->mode_set = mode_set;
           asr->handler = asr_handler;
           }
           else
           _ASR_Initialize(   asr  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/signalmp.c

       1  /*
           * Multiprocessing Support for the Signal Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: signalmp.c,  v 1.13 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/score/mpci.h>
          #include <rtems/score/mppkt.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/signal.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * _Signal_MP_Send_process_packet
           *
           * This subprogram is not needed since there are no process
           * packets to be sent by this manager.
           *
           */
          
          /*PAGE
           *
           * _Signal_MP_Send_request_packet
           *
           */
          
      46  rtems_status_code _Signal_MP_Send_request_packet (  
           Signal_MP_Remote_operations operation,  
           Objects_Id task_id,  
           rtems_signal_set signal_in
           )
          {
           Signal_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case SIGNAL_MP_SEND_REQUEST:
          
           the_packet = _Signal_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_SIGNAL;
           the_packet->Prefix.length = sizeof (   Signal_MP_Packet  );
           the_packet->Prefix.to_convert = sizeof (   Signal_MP_Packet  );
           the_packet->operation = operation;
           the_packet->Prefix.id = task_id;
           the_packet->signal_in = signal_in;
          
           return _MPCI_Send_request_packet(  
           _Objects_Get_node(   task_id  ),  
           &the_packet->Prefix,  
           STATES_READY /* Not used */
            );
           break;
          
           case SIGNAL_MP_SEND_RESPONSE:
           break;
          
           }
           /*
           * The following line is included to satisfy compilers which
           * produce warnings when a function does not end with a return.
           */
           return RTEMS_INTERNAL_ERROR;
          }
          
          /*PAGE
           *
           * _Signal_MP_Send_response_packet
           *
           */
          
      90  void _Signal_MP_Send_response_packet (  
           Signal_MP_Remote_operations operation,  
           Thread_Control *the_thread
           )
          {
           Signal_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case SIGNAL_MP_SEND_RESPONSE:
          
           the_packet = (   Signal_MP_Packet * ) the_thread->receive_packet;
          
          /*
           * The packet being returned already contains the class,   length,   and
           * to_convert fields,   therefore they are not set in this routine.
           */
           the_packet->operation = operation;
           the_packet->Prefix.id = the_packet->Prefix.source_tid;
          
           _MPCI_Send_response_packet(  
           _Objects_Get_node(   the_packet->Prefix.source_tid  ),  
           &the_packet->Prefix
            );
           break;
          
           case SIGNAL_MP_SEND_REQUEST:
           break;
          
           }
          }
          
          /*PAGE
           *
           *
           * _Signal_MP_Process_packet
           *
           */
          
     129  void _Signal_MP_Process_packet (  
           rtems_packet_prefix *the_packet_prefix
           )
          {
           Signal_MP_Packet *the_packet;
           Thread_Control *the_thread;
          
           the_packet = (  Signal_MP_Packet * ) the_packet_prefix;
          
           switch (   the_packet->operation  ) {
          
           case SIGNAL_MP_SEND_REQUEST:
          
           the_packet->Prefix.return_code = rtems_signal_send(  
           the_packet->Prefix.id,  
           the_packet->signal_in
            );
          
           _Signal_MP_Send_response_packet(  
           SIGNAL_MP_SEND_RESPONSE,  
           _Thread_Executing
            );
           break;
          
           case SIGNAL_MP_SEND_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           }
          }
          
          /*PAGE
           *
           * _Signal_MP_Send_object_was_deleted
           *
           * This subprogram is not needed since there are no objects
           * deleted by this manager.
           *
           */
          
          /*PAGE
           *
           * _Signal_MP_Send_extract_proxy
           *
           * This subprogram is not needed since there are no objects
           * deleted by this manager.
           *
           */
          
          /*PAGE
           *
           * _Signal_MP_Get_packet
           *
           */
          
     187  Signal_MP_Packet *_Signal_MP_Get_packet (   void  )
          {
           return (   (  Signal_MP_Packet * ) _MPCI_Get_packet(   )  );
          }
          
          /* end of file */

rtems/src/signalsend.c

       1  /*
           * Signal Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: signalsend.c,  v 1.12 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/asr.h>
          #include <rtems/score/isr.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/rtems/signal.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/tasks.h>
          
          /*PAGE
           *
           * rtems_signal_send
           *
           * This directive allows a thread to send signals to a thread.
           *
           * Input parameters:
           * id - thread id
           * signal_set - signal set
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      43  rtems_status_code rtems_signal_send(  
           rtems_id id,  
           rtems_signal_set signal_set
           )
          {
           register Thread_Control *the_thread;
           Objects_Locations location;
           RTEMS_API_Control *api;
           ASR_Information *asr;
          
           if (   !signal_set  )
           return RTEMS_INVALID_NUMBER;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
           asr = &api->Signal;
          
           if (   ! _ASR_Is_null_handler(   asr->handler  )  ) {
           if (   asr->is_enabled  ) {
           _ASR_Post_signals(   signal_set,   &asr->signals_posted  );
          
           if (   _ISR_Is_in_progress(   ) && _Thread_Is_executing(   the_thread  )  )
           _Thread_Dispatch_necessary = true;
           } else {
           _ASR_Post_signals(   signal_set,   &asr->signals_pending  );
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_NOT_DEFINED;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           return _Signal_MP_Send_request_packet(  
           SIGNAL_MP_SEND_REQUEST,  
           id,  
           signal_set
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/taskcreate.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskcreate.c,  v 1.17 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * rtems_task_create
           *
           * This directive creates a thread by allocating and initializing a
           * thread control block and a stack. The newly created thread is
           * placed in the dormant state.
           *
           * Input parameters:
           * name - user defined thread name
           * initial_priority - thread priority
           * stack_size - stack size in bytes
           * initial_modes - initial thread mode
           * attribute_set - thread attributes
           * id - pointer to thread id
           *
           * Output parameters:
           * id - thread id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      58  rtems_status_code rtems_task_create(  
           rtems_name name,  
           rtems_task_priority initial_priority,  
           size_t stack_size,  
           rtems_mode initial_modes,  
           rtems_attribute attribute_set,  
           rtems_id *id
           )
          {
           register Thread_Control *the_thread;
           bool is_fp;
          #if defined(  RTEMS_MULTIPROCESSING )
           Objects_MP_Control *the_global_object = NULL;
           bool is_global;
          #endif
           bool status;
           rtems_attribute the_attribute_set;
           Priority_Control core_priority;
           RTEMS_API_Control *api;
           ASR_Information *asr;
          
          
           if (   !id  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !rtems_is_name_valid(   name  )  )
           return RTEMS_INVALID_NAME;
          
           /*
           * Core Thread Initialize insures we get the minimum amount of
           * stack space.
           */
          
           /*
           * Fix the attribute set to match the attributes which
           * this processor (  1 ) requires and (  2 ) is able to support.
           * First add in the required flags for attribute_set
           * Typically this might include FP if the platform
           * or application required all tasks to be fp aware.
           * Then turn off the requested bits which are not supported.
           */
          
           the_attribute_set = _Attributes_Set(   attribute_set,   ATTRIBUTES_REQUIRED  );
           the_attribute_set =
           _Attributes_Clear(   the_attribute_set,   ATTRIBUTES_NOT_SUPPORTED  );
          
           if (   _Attributes_Is_floating_point(   the_attribute_set  )  )
           is_fp = true;
           else
           is_fp = false;
          
           /*
           * Validate the RTEMS API priority and convert it to the core priority range.
           */
          
           if (   !_Attributes_Is_system_task(   the_attribute_set  )  ) {
           if (   !_RTEMS_tasks_Priority_is_valid(   initial_priority  )  )
           return RTEMS_INVALID_PRIORITY;
           }
          
           core_priority = _RTEMS_tasks_Priority_to_Core(   initial_priority  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Attributes_Is_global(   the_attribute_set  )  ) {
          
           is_global = true;
          
           if (   !_System_state_Is_multiprocessing  )
           return RTEMS_MP_NOT_CONFIGURED;
          
           } else
           is_global = false;
          #endif
          
           /*
           * Make sure system is MP if this task is global
           */
          
           /*
           * Lock the allocator mutex for protection
           */
           _RTEMS_Lock_allocator(   );
          
           /*
           * Allocate the thread control block and -- if the task is global --
           * allocate a global object control block.
           *
           * NOTE: This routine does not use the combined allocate and open
           * global object routine because this results in a lack of
           * control over when memory is allocated and can be freed in
           * the event of an error.
           */
          
           the_thread = _RTEMS_tasks_Allocate(   );
          
           if (   !the_thread  ) {
           _RTEMS_Unlock_allocator(   );
           return RTEMS_TOO_MANY;
           }
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   is_global  ) {
           the_global_object = _Objects_MP_Allocate_global_object(   );
          
           if (   _Objects_MP_Is_null_global_object(   the_global_object  )  ) {
           _RTEMS_tasks_Free(   the_thread  );
           _RTEMS_Unlock_allocator(   );
           return RTEMS_TOO_MANY;
           }
           }
          #endif
          
           /*
           * Initialize the core thread for this task.
           */
          
           status = _Thread_Initialize(  
           &_RTEMS_tasks_Information,  
           the_thread,  
           NULL,  
           stack_size,  
           is_fp,  
           core_priority,  
           _Modes_Is_preempt(  initial_modes ) ? true : false,  
           _Modes_Is_timeslice(  initial_modes ) ?
           THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE :
           THREAD_CPU_BUDGET_ALGORITHM_NONE,  
           NULL,   /* no budget algorithm callout */
           _Modes_Get_interrupt_level(  initial_modes ),  
           (  Objects_Name ) name
            );
          
           if (   !status  ) {
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   is_global  )
           _Objects_MP_Free_global_object(   the_global_object  );
          #endif
           _RTEMS_tasks_Free(   the_thread  );
           _RTEMS_Unlock_allocator(   );
           return RTEMS_UNSATISFIED;
           }
          
           api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
           asr = &api->Signal;
          
           asr->is_enabled = _Modes_Is_asr_disabled(  initial_modes ) ? false : true;
          
           *id = the_thread->Object.id;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           the_thread->is_global = is_global;
           if (   is_global  ) {
          
           _Objects_MP_Open(  
           &_RTEMS_tasks_Information,  
           the_global_object,  
           name,  
           the_thread->Object.id
            );
          
           _RTEMS_tasks_MP_Send_process_packet(  
           RTEMS_TASKS_MP_ANNOUNCE_CREATE,  
           the_thread->Object.id,  
           name
            );
          
           }
          #endif
          
           _RTEMS_Unlock_allocator(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/taskdata.c

       1  /*
           * RTEMS Task Manager -- Instantiate Data
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskdata.c,  v 1.1 2007/05/21 23:19:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate RTEMS Classic API tasks data */
          #define RTEMS_TASKS_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/rtems/tasks.h>

rtems/src/taskdelete.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskdelete.c,  v 1.11 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/apimutex.h>
          
          /*PAGE
           *
           * rtems_task_delete
           *
           * This directive allows a thread to delete itself or the thread
           * identified in the id field. The executive halts execution
           * of the thread and frees the thread control block.
           *
           * Input parameters:
           * id - thread id
           *
           * Output parameters:
           * nothing - if id is the requesting thread (  always succeeds )
           * RTEMS_SUCCESSFUL - if successful and id is
           * not the requesting thread
           * error code - if unsuccessful
           */
          
      54  rtems_status_code rtems_task_delete(  
           rtems_id id
           )
          {
           register Thread_Control *the_thread;
           Objects_Locations location;
           Objects_Information *the_information;
          
           _RTEMS_Lock_allocator(   );
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           the_information = _Objects_Get_information_id(   the_thread->Object.id  );
          
           #if defined(  RTEMS_DEBUG )
           if (   !the_information  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_INVALID_ID;
           /* This should never happen if _Thread_Get(   ) works right */
           }
           #endif
          
           #if defined(  RTEMS_MULTIPROCESSING )
           if (   the_thread->is_global  ) {
           _Objects_MP_Close(   &_RTEMS_tasks_Information,   the_thread->Object.id  );
           _RTEMS_tasks_MP_Send_process_packet(  
           RTEMS_TASKS_MP_ANNOUNCE_DELETE,  
           the_thread->Object.id,  
           0 /* Not used */
            );
           }
           #endif
          
           _Thread_Close(   the_information,   the_thread  );
          
           _RTEMS_tasks_Free(   the_thread  );
          
           _RTEMS_Unlock_allocator(   );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _RTEMS_Unlock_allocator(   );
           _Thread_Dispatch(   );
           return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           _RTEMS_Unlock_allocator(   );
           return RTEMS_INVALID_ID;
          }

rtems/src/taskgetnote.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskgetnote.c,  v 1.11 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_task_get_note
           *
           * This directive obtains the note from the specified notepad
           * of the specified thread.
           *
           * Input parameters:
           * id - thread id
           * notepad - notepad number
           * note - pointer to note
           *
           * Output parameters:
           * note - filled in if successful
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      54  rtems_status_code rtems_task_get_note(  
           rtems_id id,  
           uint32_t notepad,  
           uint32_t *note
           )
          {
           register Thread_Control *the_thread;
           Objects_Locations location;
           RTEMS_API_Control *api;
          
           if (   !rtems_configuration_get_notepads_enabled(   )  )
           return RTEMS_NOT_CONFIGURED;
          
           if (   !note  )
           return RTEMS_INVALID_ADDRESS;
          
           /*
           * NOTE: There is no check for < RTEMS_NOTEPAD_FIRST because that would
           * be checking an unsigned number for being negative.
           */
          
           if (   notepad > RTEMS_NOTEPAD_LAST  )
           return RTEMS_INVALID_NUMBER;
          
           /*
           * Optimize the most likely case to avoid the Thread_Dispatch.
           */
          
           if (   _Objects_Are_ids_equal(   id,   OBJECTS_ID_OF_SELF  ) ||
           _Objects_Are_ids_equal(   id,   _Thread_Executing->Object.id  )  ) {
           api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
           *note = api->Notepads[ notepad ];
           return RTEMS_SUCCESSFUL;
           }
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
           *note = api->Notepads[ notepad ];
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Executing->Wait.return_argument = note;
          
           return _RTEMS_tasks_MP_Send_request_packet(  
           RTEMS_TASKS_MP_GET_NOTE_REQUEST,  
           id,  
           0,   /* Not used */
           notepad,  
           0 /* Not used */
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/taskident.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskident.c,  v 1.11 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_task_ident
           *
           * This directive returns the system ID associated with
           * the thread name.
           *
           * Input parameters:
           * name - user defined thread name
           * node - node(  s ) to be searched
           * id - pointer to thread id
           *
           * Output parameters:
           * *id - thread id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      53  rtems_status_code rtems_task_ident(  
           rtems_name name,  
           uint32_t node,  
           rtems_id *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
          
           if (   !id  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   name == OBJECTS_ID_OF_SELF  ) {
           *id = _Thread_Executing->Object.id;
           return RTEMS_SUCCESSFUL;
           }
          
           status = _Objects_Name_to_id_u32(   &_RTEMS_tasks_Information,   name,   node,   id  );
          
           return _Status_Object_name_errors_to_status[ status ];
          }

rtems/src/taskinitusers.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskinitusers.c,  v 1.10 2009/07/04 19:45:18 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/rtemsapi.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * _RTEMS_tasks_Initialize_user_tasks_body
           *
           * This routine creates and starts all configured user
           * initialzation threads.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      49  void _RTEMS_tasks_Initialize_user_tasks_body(   void  )
          {
           uint32_t index;
           uint32_t maximum;
           rtems_id id;
           rtems_status_code return_value;
           rtems_initialization_tasks_table *user_tasks;
          
           /*
           * Move information into local variables
           */
           user_tasks = Configuration_RTEMS_API.User_initialization_tasks_table;
           maximum = Configuration_RTEMS_API.number_of_initialization_tasks;
          
           /*
           * Verify that we have a set of user tasks to iterate
           */
           if (   !user_tasks  )
           return;
          
           /*
           * Now iterate over the initialization tasks and create/start them.
           */
           for (   index=0 ; index < maximum ; index++  ) {
           return_value = rtems_task_create(  
           user_tasks[ index ].name,  
           user_tasks[ index ].initial_priority,  
           user_tasks[ index ].stack_size,  
           user_tasks[ index ].mode_set,  
           user_tasks[ index ].attribute_set,  
           &id
            );
           if (   !rtems_is_status_successful(   return_value  )  )
           _Internal_error_Occurred(   INTERNAL_ERROR_RTEMS_API,   true,   return_value  );
          
           return_value = rtems_task_start(  
           id,  
           user_tasks[ index ].entry_point,  
           user_tasks[ index ].argument
            );
           if (   !rtems_is_status_successful(   return_value  )  )
           _Internal_error_Occurred(   INTERNAL_ERROR_RTEMS_API,   true,   return_value  );
           }
          }

rtems/src/taskissuspended.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskissuspended.c,  v 1.8 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_task_is_suspended
           *
           * This directive returns a status indicating whether or not
           * the specified task is suspended.
           *
           * Input parameters:
           * id - thread id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful and not suspended
           * RTEMS_ALREADY_SUSPENDED - if successful and suspended
           * error code - if unsuccessful
           */
          
      51  rtems_status_code rtems_task_is_suspended(  
           rtems_id id
           )
          {
           register Thread_Control *the_thread;
           Objects_Locations location;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   !_States_Is_suspended(   the_thread->current_state  )  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_ALREADY_SUSPENDED;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Dispatch(   );
           return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/taskmode.c

       1  /*
           * RTEMS Task Manager - Change Task Mode
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskmode.c,  v 1.13 2010/07/27 01:48:46 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*
           * rtems_task_mode
           *
           * This directive enables and disables several modes of
           * execution for the requesting thread.
           *
           * Input parameters:
           * mode_set - new mode
           * mask - mask
           * previous_mode_set - address of previous mode set
           *
           * Output:
           * *previous_mode_set - previous mode set
           * always return RTEMS_SUCCESSFUL;
           */
          
      50  rtems_status_code rtems_task_mode(  
           rtems_mode mode_set,  
           rtems_mode mask,  
           rtems_mode *previous_mode_set
           )
          {
           Thread_Control *executing;
           RTEMS_API_Control *api;
           ASR_Information *asr;
           bool is_asr_enabled = false;
           bool needs_asr_dispatching = false;
           rtems_mode old_mode;
          
           if (   !previous_mode_set  )
           return RTEMS_INVALID_ADDRESS;
          
           executing = _Thread_Executing;
           api = executing->API_Extensions[ THREAD_API_RTEMS ];
           asr = &api->Signal;
          
           old_mode = (  executing->is_preemptible ) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT;
          
           if (   executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE  )
           old_mode |= RTEMS_NO_TIMESLICE;
           else
           old_mode |= RTEMS_TIMESLICE;
          
           old_mode |= (  asr->is_enabled ) ? RTEMS_ASR : RTEMS_NO_ASR;
           old_mode |= _ISR_Get_level(   );
          
           *previous_mode_set = old_mode;
          
           /*
           * These are generic thread scheduling characteristics.
           */
           if (   mask & RTEMS_PREEMPT_MASK  )
           executing->is_preemptible = _Modes_Is_preempt(  mode_set ) ? true : false;
          
           if (   mask & RTEMS_TIMESLICE_MASK  ) {
           if (   _Modes_Is_timeslice(  mode_set )  ) {
           executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
           executing->cpu_time_budget = _Thread_Ticks_per_timeslice;
           } else
           executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
           }
          
           /*
           * Set the new interrupt level
           */
           if (   mask & RTEMS_INTERRUPT_MASK  )
           _Modes_Set_interrupt_level(   mode_set  );
          
           /*
           * This is specific to the RTEMS API
           */
           is_asr_enabled = false;
           needs_asr_dispatching = false;
          
           if (   mask & RTEMS_ASR_MASK  ) {
           is_asr_enabled = _Modes_Is_asr_disabled(   mode_set  ) ? false : true;
           if (   is_asr_enabled != asr->is_enabled  ) {
           asr->is_enabled = is_asr_enabled;
           _ASR_Swap_signals(   asr  );
           if (   _ASR_Are_signals_pending(   asr  )  ) {
           needs_asr_dispatching = true;
           }
           }
           }
          
           if (   _System_state_Is_up(   _System_state_Get(   )  )  ) {
           if (  _Thread_Evaluate_is_dispatch_needed(   needs_asr_dispatching  )  )
           _Thread_Dispatch(   );
           }
          
           return RTEMS_SUCCESSFUL;
          }

rtems/src/taskmp.c

       1  /*
           * Multiprocessing Support for the RTEMS Task Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskmp.c,  v 1.18 2009/01/06 04:58:46 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/score/mpci.h>
          #include <rtems/score/mppkt.h>
          #include <rtems/score/object.h>
          #include <rtems/rtems/options.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/rtems/support.h>
          
          /*PAGE
           *
           * _RTEMS_tasks_MP_Send_process_packet
           *
           */
          
      36  void _RTEMS_tasks_MP_Send_process_packet (  
           RTEMS_tasks_MP_Remote_operations operation,  
           Objects_Id task_id,  
           rtems_name name
           )
          {
           RTEMS_tasks_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
           case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
          
           the_packet = _RTEMS_tasks_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_TASKS;
           the_packet->Prefix.length = sizeof (   RTEMS_tasks_MP_Packet  );
           the_packet->Prefix.to_convert = sizeof (   RTEMS_tasks_MP_Packet  );
           the_packet->operation = operation;
           the_packet->Prefix.id = task_id;
           the_packet->name = name;
          
           _MPCI_Send_process_packet(   MPCI_ALL_NODES,   &the_packet->Prefix  );
           break;
          
           case RTEMS_TASKS_MP_SUSPEND_REQUEST:
           case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
           case RTEMS_TASKS_MP_RESUME_REQUEST:
           case RTEMS_TASKS_MP_RESUME_RESPONSE:
           case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
           case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
           case RTEMS_TASKS_MP_GET_NOTE_REQUEST:
           case RTEMS_TASKS_MP_GET_NOTE_RESPONSE:
           case RTEMS_TASKS_MP_SET_NOTE_REQUEST:
           case RTEMS_TASKS_MP_SET_NOTE_RESPONSE:
           break;
           }
          }
          
          /*PAGE
           *
           * _RTEMS_tasks_MP_Send_request_packet
           *
           */
          
      80  rtems_status_code _RTEMS_tasks_MP_Send_request_packet (  
           RTEMS_tasks_MP_Remote_operations operation,  
           Objects_Id task_id,  
           rtems_task_priority new_priority,  
           uint32_t notepad,  
           uint32_t note
           )
          {
           RTEMS_tasks_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case RTEMS_TASKS_MP_SUSPEND_REQUEST:
           case RTEMS_TASKS_MP_RESUME_REQUEST:
           case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
           case RTEMS_TASKS_MP_GET_NOTE_REQUEST:
           case RTEMS_TASKS_MP_SET_NOTE_REQUEST:
          
           the_packet = _RTEMS_tasks_MP_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_TASKS;
           the_packet->Prefix.length = sizeof (   RTEMS_tasks_MP_Packet  );
           the_packet->Prefix.to_convert = sizeof (   RTEMS_tasks_MP_Packet  );
           the_packet->operation = operation;
           the_packet->Prefix.id = task_id;
           the_packet->the_priority = new_priority;
           the_packet->notepad = notepad;
           the_packet->note = note;
          
           return _MPCI_Send_request_packet(  
           _Objects_Get_node(   task_id  ),  
           &the_packet->Prefix,  
           STATES_READY /* Not used */
            );
           break;
          
           case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
           case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
           case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
           case RTEMS_TASKS_MP_RESUME_RESPONSE:
           case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
           case RTEMS_TASKS_MP_GET_NOTE_RESPONSE:
           case RTEMS_TASKS_MP_SET_NOTE_RESPONSE:
           break;
          
           }
           /*
           * The following line is included to satisfy compilers which
           * produce warnings when a function does not end with a return.
           */
           return RTEMS_SUCCESSFUL;
          }
          
          /*PAGE
           *
           * _RTEMS_tasks_MP_Send_response_packet
           *
           */
          
     138  void _RTEMS_tasks_MP_Send_response_packet (  
           RTEMS_tasks_MP_Remote_operations operation,  
           Thread_Control *the_thread
           )
          {
           RTEMS_tasks_MP_Packet *the_packet;
          
           switch (   operation  ) {
          
           case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
           case RTEMS_TASKS_MP_RESUME_RESPONSE:
           case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
           case RTEMS_TASKS_MP_GET_NOTE_RESPONSE:
           case RTEMS_TASKS_MP_SET_NOTE_RESPONSE:
          
           the_packet = (  RTEMS_tasks_MP_Packet * ) the_thread->receive_packet;
          
          /*
           * The packet being returned already contains the class,   length,   and
           * to_convert fields,   therefore they are not set in this routine.
           */
           the_packet->operation = operation;
           the_packet->Prefix.id = the_packet->Prefix.source_tid;
          
           _MPCI_Send_response_packet(  
           _Objects_Get_node(   the_packet->Prefix.source_tid  ),  
           &the_packet->Prefix
            );
           break;
          
           case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
           case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
           case RTEMS_TASKS_MP_SUSPEND_REQUEST:
           case RTEMS_TASKS_MP_RESUME_REQUEST:
           case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
           case RTEMS_TASKS_MP_GET_NOTE_REQUEST:
           case RTEMS_TASKS_MP_SET_NOTE_REQUEST:
           break;
          
           }
          }
          
          /*PAGE
           *
           *
           * _RTEMS_tasks_MP_Process_packet
           *
           */
          
     187  void _RTEMS_tasks_MP_Process_packet (  
           rtems_packet_prefix *the_packet_prefix
           )
          {
           RTEMS_tasks_MP_Packet *the_packet;
           Thread_Control *the_thread;
           bool ignored;
          
           the_packet = (  RTEMS_tasks_MP_Packet * ) the_packet_prefix;
          
           switch (   the_packet->operation  ) {
          
           case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
          
           ignored = _Objects_MP_Allocate_and_open(  
           &_RTEMS_tasks_Information,  
           the_packet->name,  
           the_packet->Prefix.id,  
           true
            );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
          
           _Objects_MP_Close(   &_RTEMS_tasks_Information,   the_packet->Prefix.id  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case RTEMS_TASKS_MP_SUSPEND_REQUEST:
          
           the_packet->Prefix.return_code = rtems_task_suspend(  
           the_packet->Prefix.id
            );
          
           _RTEMS_tasks_MP_Send_response_packet(  
           RTEMS_TASKS_MP_SUSPEND_RESPONSE,  
           _Thread_Executing
            );
           break;
          
           case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
           case RTEMS_TASKS_MP_RESUME_RESPONSE:
           case RTEMS_TASKS_MP_SET_NOTE_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case RTEMS_TASKS_MP_RESUME_REQUEST:
          
           the_packet->Prefix.return_code = rtems_task_resume(  
           the_packet->Prefix.id
            );
          
           _RTEMS_tasks_MP_Send_response_packet(  
           RTEMS_TASKS_MP_RESUME_RESPONSE,  
           _Thread_Executing
            );
           break;
          
           case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
          
           the_packet->Prefix.return_code = rtems_task_set_priority(  
           the_packet->Prefix.id,  
           the_packet->the_priority,  
           &the_packet->the_priority
            );
          
           _RTEMS_tasks_MP_Send_response_packet(  
           RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE,  
           _Thread_Executing
            );
           break;
          
           case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           *(  rtems_task_priority * )the_thread->Wait.return_argument =
           the_packet->the_priority;
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case RTEMS_TASKS_MP_GET_NOTE_REQUEST:
          
           the_packet->Prefix.return_code = rtems_task_get_note(  
           the_packet->Prefix.id,  
           the_packet->notepad,  
           &the_packet->note
            );
          
           _RTEMS_tasks_MP_Send_response_packet(  
           RTEMS_TASKS_MP_GET_NOTE_RESPONSE,  
           _Thread_Executing
            );
           break;
          
           case RTEMS_TASKS_MP_GET_NOTE_RESPONSE:
          
           the_thread = _MPCI_Process_response(   the_packet_prefix  );
          
           *(  uint32_t * )the_thread->Wait.return_argument = the_packet->note;
          
           _MPCI_Return_packet(   the_packet_prefix  );
           break;
          
           case RTEMS_TASKS_MP_SET_NOTE_REQUEST:
          
           the_packet->Prefix.return_code = rtems_task_set_note(  
           the_packet->Prefix.id,  
           the_packet->notepad,  
           the_packet->note
            );
          
           _RTEMS_tasks_MP_Send_response_packet(  
           RTEMS_TASKS_MP_SET_NOTE_RESPONSE,  
           _Thread_Executing
            );
           break;
           }
          }
          
          /*PAGE
           *
           * _RTEMS_tasks_MP_Send_object_was_deleted
           *
           * This routine is not neededby the Tasks since a task
           * cannot be globally deleted.
           *
           */
          
          /*PAGE
           *
           * _RTEMS_tasks_MP_Send_extract_proxy
           *
           * This routine is not neededby the Tasks since a task
           * cannot be globally deleted.
           *
           */
          
          /*PAGE
           *
           * _RTEMS_tasks_MP_Get_packet
           *
           */
          
     338  RTEMS_tasks_MP_Packet *_RTEMS_tasks_MP_Get_packet (   void  )
          {
           return (  RTEMS_tasks_MP_Packet * ) _MPCI_Get_packet(   );
          }
          
          /* end of file */

rtems/src/taskrestart.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskrestart.c,  v 1.9 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_task_restart
           *
           * This directive readies the specified thread. It restores
           * the thread environment to the original values established
           * at thread creation and start time. A thread can be restarted
           * from any state except the dormant state.
           *
           * Input parameters:
           * id - thread id
           * argument - thread argument
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      53  rtems_status_code rtems_task_restart(  
           rtems_id id,  
           uint32_t argument
           )
          {
           register Thread_Control *the_thread;
           Objects_Locations location;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   _Thread_Restart(   the_thread,   NULL,   argument  )  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_INCORRECT_STATE;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Dispatch(   );
           return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/taskresume.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskresume.c,  v 1.10 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_task_resume
           *
           * This directive will remove the specified thread
           * from the suspended state.
           *
           * Input parameters:
           * id - thread id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      50  rtems_status_code rtems_task_resume(  
           rtems_id id
           )
          {
           register Thread_Control *the_thread;
           Objects_Locations location;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   _States_Is_suspended(   the_thread->current_state  )  ) {
           _Thread_Resume(   the_thread,   true  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_INCORRECT_STATE;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           return _RTEMS_tasks_MP_Send_request_packet(  
           RTEMS_TASKS_MP_RESUME_REQUEST,  
           id,  
           0,   /* Not used */
           0,   /* Not used */
           0 /* Not used */
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/tasks.c

       1  /*
           * RTEMS Task Manager -- Initialize Manager
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tasks.c,  v 1.62 2009/09/26 16:17:00 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * _RTEMS_tasks_Create_extension
           *
           * This routine is an extension routine that is invoked as part
           * of creating any type of task or thread in the system. If the
           * task is created via another API,   then this routine is invoked
           * and this API given the opportunity to initialize its extension
           * area.
           */
          
      46  bool _RTEMS_tasks_Create_extension(  
           Thread_Control *executing,  
           Thread_Control *created
           )
          {
           RTEMS_API_Control *api;
           int i;
           size_t to_allocate;
          
           /*
           * Notepads must be the last entry in the structure and they
           * can be left off if disabled in the configuration.
           */
           to_allocate = sizeof(   RTEMS_API_Control  );
           if (   !rtems_configuration_get_notepads_enabled(   )  )
           to_allocate -= (  RTEMS_NUMBER_NOTEPADS * sizeof(  uint32_t ) );
          
           api = _Workspace_Allocate(   to_allocate  );
          
           if (   !api  )
           return false;
          
           created->API_Extensions[ THREAD_API_RTEMS ] = api;
          
           api->pending_events = EVENT_SETS_NONE_PENDING;
           api->event_condition = 0;
           _ASR_Initialize(   &api->Signal  );
           created->task_variables = NULL;
          
           if (   rtems_configuration_get_notepads_enabled(   )  ) {
           for (  i=0; i < RTEMS_NUMBER_NOTEPADS; i++ )
           api->Notepads[i] = 0;
           }
          
           return true;
          }
          
          /*PAGE
           *
           * _RTEMS_tasks_Start_extension
           *
           * This extension routine is invoked when a task is started for the
           * first time.
           */
          
      91  void _RTEMS_tasks_Start_extension(  
           Thread_Control *executing,  
           Thread_Control *started
           )
          {
           RTEMS_API_Control *api;
          
           api = started->API_Extensions[ THREAD_API_RTEMS ];
          
           api->pending_events = EVENT_SETS_NONE_PENDING;
          }
          
          /*PAGE
           *
           * _RTEMS_tasks_Delete_extension
           *
           * This extension routine is invoked when a task is deleted.
           */
          
     110  void _RTEMS_tasks_Delete_extension(  
           Thread_Control *executing,  
           Thread_Control *deleted
           )
          {
           rtems_task_variable_t *tvp,   *next;
          
           /*
           * Free per task variable memory
           */
          
           tvp = deleted->task_variables;
           deleted->task_variables = NULL;
           while (  tvp ) {
           next = (  rtems_task_variable_t * )tvp->next;
           _RTEMS_Tasks_Invoke_task_variable_dtor(   deleted,   tvp  );
           tvp = next;
           }
          
           /*
           * Free API specific memory
           */
          
           (  void ) _Workspace_Free(   deleted->API_Extensions[ THREAD_API_RTEMS ]  );
           deleted->API_Extensions[ THREAD_API_RTEMS ] = NULL;
          }
          
          /*PAGE
           *
           * _RTEMS_tasks_Switch_extension
           *
           * This extension routine is invoked at each context switch.
           */
          
     144  void _RTEMS_tasks_Switch_extension(  
           Thread_Control *executing,  
           Thread_Control *heir
           )
          {
           rtems_task_variable_t *tvp;
          
           /*
           * Per Task Variables
           */
          
           tvp = executing->task_variables;
           while (  tvp ) {
           tvp->tval = *tvp->ptr;
           *tvp->ptr = tvp->gval;
           tvp = (  rtems_task_variable_t * )tvp->next;
           }
          
           tvp = heir->task_variables;
           while (  tvp ) {
           tvp->gval = *tvp->ptr;
           *tvp->ptr = tvp->tval;
           tvp = (  rtems_task_variable_t * )tvp->next;
           }
          }
          
          /*PAGE
           *
           * _RTEMS_tasks_Post_switch_extension
           *
           * This extension routine is invoked at each context switch.
           */
          
     177  void _RTEMS_tasks_Post_switch_extension(  
           Thread_Control *executing
           )
          {
           ISR_Level level;
           RTEMS_API_Control *api;
           ASR_Information *asr;
           rtems_signal_set signal_set;
           Modes_Control prev_mode;
          
           api = executing->API_Extensions[ THREAD_API_RTEMS ];
           if (   !api  )
           return;
          
           /*
           * Signal Processing
           */
          
           asr = &api->Signal;
          
           _ISR_Disable(   level  );
           signal_set = asr->signals_posted;
           asr->signals_posted = 0;
           _ISR_Enable(   level  );
          
          
           if (   !signal_set  ) /* similar to _ASR_Are_signals_pending(   asr  ) */
           return;
          
           asr->nest_level += 1;
           rtems_task_mode(   asr->mode_set,   RTEMS_ALL_MODE_MASKS,   &prev_mode  );
          
           (  *asr->handler )(   signal_set  );
          
           asr->nest_level -= 1;
           rtems_task_mode(   prev_mode,   RTEMS_ALL_MODE_MASKS,   &prev_mode  );
          
          }
          
          API_extensions_Control _RTEMS_tasks_API_extensions = {
           { NULL,   NULL },  
           #if defined(  FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API )
           NULL,   /* predriver */
           #endif
           _RTEMS_tasks_Initialize_user_tasks,   /* postdriver */
           _RTEMS_tasks_Post_switch_extension /* post switch */
          };
          
          User_extensions_Control _RTEMS_tasks_User_extensions = {
           { NULL,   NULL },  
           { { NULL,   NULL },   _RTEMS_tasks_Switch_extension },  
           { _RTEMS_tasks_Create_extension,   /* create */
           _RTEMS_tasks_Start_extension,   /* start */
           _RTEMS_tasks_Start_extension,   /* restart */
           _RTEMS_tasks_Delete_extension,   /* delete */
           _RTEMS_tasks_Switch_extension,   /* switch */
           NULL,   /* begin */
           NULL,   /* exitted */
           NULL /* fatal */
           }
          };
          
          /*PAGE
           *
           * _RTEMS_tasks_Manager_initialization
           *
           * This routine initializes all Task Manager related data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
     250  void _RTEMS_tasks_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_RTEMS_tasks_Information,   /* object information table */
           OBJECTS_CLASSIC_API,   /* object API */
           OBJECTS_RTEMS_TASKS,   /* object class */
           Configuration_RTEMS_API.maximum_tasks,  
           /* maximum objects of this class */
           sizeof(   Thread_Control  ),   /* size of this object's control block */
           false,   /* true if the name is a string */
           RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           true,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          
           /*
           * Add all the extensions for this API
           */
          
           _User_extensions_Add_API_set(   &_RTEMS_tasks_User_extensions  );
          
           _API_extensions_Add(   &_RTEMS_tasks_API_extensions  );
          
           /*
           * Register the MP Process Packet routine.
           */
          
          #if defined(  RTEMS_MULTIPROCESSING )
           _MPCI_Register_packet_processor(  
           MP_PACKET_TASKS,  
           _RTEMS_tasks_MP_Process_packet
            );
          #endif
          
          }
          
          /*PAGE
           *
           * _RTEMS_tasks_Initialize_user_tasks
           *
           * This routine creates and starts all configured user
           * initialzation threads.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
     301  void _RTEMS_tasks_Initialize_user_tasks(   void  )
          {
           if (   _RTEMS_tasks_Initialize_user_tasks_p  )
           (  *_RTEMS_tasks_Initialize_user_tasks_p )(   );
          }

rtems/src/taskself.c

       1  /*
           * RTEMS Task Manager - Get ID of Self
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskself.c,  v 1.1 2007/12/20 21:51:23 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/tasks.h>
          
      21  rtems_id rtems_task_self(  void )
          {
           return _Thread_Executing->Object.id;
          }

rtems/src/tasksetnote.c

       1  /*
           * RTEMS Task Manager
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tasksetnote.c,  v 1.12 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_task_set_note
           *
           * This directive sets the specified notepad contents to the given
           * note.
           *
           * Input parameters:
           * id - thread id
           * notepad - notepad number
           * note - note value
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      52  rtems_status_code rtems_task_set_note(  
           rtems_id id,  
           uint32_t notepad,  
           uint32_t note
           )
          {
           register Thread_Control *the_thread;
           Objects_Locations location;
           RTEMS_API_Control *api;
          
           if (   !rtems_configuration_get_notepads_enabled(   )  )
           return RTEMS_NOT_CONFIGURED;
          
           /*
           * NOTE: There is no check for < RTEMS_NOTEPAD_FIRST because that would
           * be checking an unsigned number for being negative.
           */
          
           if (   notepad > RTEMS_NOTEPAD_LAST  )
           return RTEMS_INVALID_NUMBER;
          
           /*
           * Optimize the most likely case to avoid the Thread_Dispatch.
           */
          
           if (   _Objects_Are_ids_equal(   id,   OBJECTS_ID_OF_SELF  ) ||
           _Objects_Are_ids_equal(   id,   _Thread_Executing->Object.id  )  ) {
           api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
           api->Notepads[ notepad ] = note;
           return RTEMS_SUCCESSFUL;
           }
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
           api->Notepads[ notepad ] = note;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           return _RTEMS_tasks_MP_Send_request_packet(  
           RTEMS_TASKS_MP_SET_NOTE_REQUEST,  
           id,  
           0,   /* Not used */
           notepad,  
           note
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/tasksetpriority.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tasksetpriority.c,  v 1.12 2010/06/12 17:55:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_task_set_priority
           *
           * This directive changes the priority of the specified thread.
           * The specified thread can be any thread in the system including
           * the requesting thread.
           *
           * Input parameters:
           * id - thread id (  0 indicates requesting thread )
           * new_priority - thread priority (  0 indicates current priority )
           * old_priority - pointer to previous priority
           *
           * Output parameters:
           * old_priority - previous priority
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      54  rtems_status_code rtems_task_set_priority(  
           rtems_id id,  
           rtems_task_priority new_priority,  
           rtems_task_priority *old_priority
           )
          {
           register Thread_Control *the_thread;
           Objects_Locations location;
          
           if (   new_priority != RTEMS_CURRENT_PRIORITY &&
           !_RTEMS_tasks_Priority_is_valid(   new_priority  )  )
           return RTEMS_INVALID_PRIORITY;
          
           if (   !old_priority  )
           return RTEMS_INVALID_ADDRESS;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           /* XXX need helper to "convert" from core priority */
           *old_priority = the_thread->current_priority;
           if (   new_priority != RTEMS_CURRENT_PRIORITY  ) {
           the_thread->real_priority = new_priority;
           if (   the_thread->resource_count == 0 ||
           the_thread->current_priority > new_priority  )
           _Thread_Change_priority(   the_thread,   new_priority,   false  );
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Executing->Wait.return_argument = old_priority;
           return _RTEMS_tasks_MP_Send_request_packet(  
           RTEMS_TASKS_MP_SET_PRIORITY_REQUEST,  
           id,  
           new_priority,  
           0,   /* Not used */
           0 /* Not used */
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/taskstart.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskstart.c,  v 1.10 2007/11/30 21:49:41 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_task_start
           *
           * This directive readies the thread identified by the "id"
           * based on its current priorty,   to await execution. A thread
           * can be started only from the dormant state.
           *
           * Input parameters:
           * id - thread id
           * entry_point - start execution address of thread
           * argument - thread argument
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      53  rtems_status_code rtems_task_start(  
           rtems_id id,  
           rtems_task_entry entry_point,  
           rtems_task_argument argument
           )
          {
           register Thread_Control *the_thread;
           Objects_Locations location;
          
           if (   entry_point == NULL  )
           return RTEMS_INVALID_ADDRESS;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   _Thread_Start(  
           the_thread,   THREAD_START_NUMERIC,   entry_point,   NULL,   argument  )  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_INCORRECT_STATE;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Dispatch(   );
           return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/tasksuspend.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: tasksuspend.c,  v 1.9 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_task_suspend
           *
           * This directive will place the specified thread in the "suspended"
           * state. Note that the suspended state can be in addition to
           * other waiting states.
           *
           * Input parameters:
           * id - thread id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      51  rtems_status_code rtems_task_suspend(  
           rtems_id id
           )
          {
           register Thread_Control *the_thread;
           Objects_Locations location;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   !_States_Is_suspended(   the_thread->current_state  )  ) {
           _Thread_Suspend(   the_thread  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_ALREADY_SUSPENDED;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           return _RTEMS_tasks_MP_Send_request_packet(  
           RTEMS_TASKS_MP_SUSPEND_REQUEST,  
           id,  
           0,   /* Not used */
           0,   /* Not used */
           0 /* Not used */
            );
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/taskvariable_invoke_dtor.c

       1  /*
           * Invoke the destructor on a per-task variable
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskvariable_invoke_dtor.c,  v 1.1 2007/12/12 23:19:57 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/wkspace.h>
          
      23  void _RTEMS_Tasks_Invoke_task_variable_dtor(  
           Thread_Control *the_thread,  
           rtems_task_variable_t *tvp
           )
          {
           void (  *dtor )(  void * );
           void *value;
          
           dtor = tvp->dtor;
           if (  _Thread_Is_executing(  the_thread ) ) {
           value = *tvp->ptr;
           *tvp->ptr = tvp->gval;
           } else {
           value = tvp->tval;
           }
          
           if (   dtor  )
           (  *dtor )(  value );
          
           _Workspace_Free(  tvp );
          }

rtems/src/taskvariableadd.c

       1  /*
           * rtems_task_variable_add - Add a per-task variable
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskvariableadd.c,  v 1.16 2007/12/12 23:19:57 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/wkspace.h>
          
          /*
           * rtems_task_variable_add
           *
           * This directive registers a task variable.
           */
          
      29  rtems_status_code rtems_task_variable_add(  
           rtems_id tid,  
           void **ptr,  
           void (  *dtor )(  void * )
           )
          {
           Thread_Control *the_thread;
           Objects_Locations location;
           rtems_task_variable_t *tvp,   *new;
          
           if (   !ptr  )
           return RTEMS_INVALID_ADDRESS;
          
           the_thread = _Thread_Get (  tid,   &location );
           switch (  location ) {
          
           case OBJECTS_LOCAL:
           /*
           * Figure out if the variable is already in this task's list.
           */
           tvp = the_thread->task_variables;
           while (  tvp ) {
           if (  tvp->ptr == ptr ) {
           tvp->dtor = dtor;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           tvp = (  rtems_task_variable_t * )tvp->next;
           }
          
           /*
           * Now allocate memory for this task variable.
           */
           new = (  rtems_task_variable_t * )
           _Workspace_Allocate(  sizeof(  rtems_task_variable_t ) );
           if (  new == NULL ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_NO_MEMORY;
           }
           new->gval = *ptr;
           new->ptr = ptr;
           new->dtor = dtor;
          
           new->next = (  struct rtems_task_variable_tt * )the_thread->task_variables;
           the_thread->task_variables = new;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Dispatch(   );
           return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
           return RTEMS_INVALID_ID;
          }

rtems/src/taskvariabledelete.c

       1  /*
           * rtems_task_variable_delete - Delete a per-task variable
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskvariabledelete.c,  v 1.17 2009/11/30 15:59:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/wkspace.h>
          
          /*
           * rtems_task_variable_delete
           *
           * This directive removes a task variable.
           */
          
      29  rtems_status_code rtems_task_variable_delete(  
           rtems_id tid,  
           void **ptr
           )
          {
           Thread_Control *the_thread;
           Objects_Locations location;
           rtems_task_variable_t *tvp,   *prev;
          
           if (   !ptr  )
           return RTEMS_INVALID_ADDRESS;
          
           prev = NULL;
          
           the_thread = _Thread_Get (  tid,   &location );
           switch (  location ) {
          
           case OBJECTS_LOCAL:
           tvp = the_thread->task_variables;
           while (  tvp ) {
           if (  tvp->ptr == ptr ) {
           if (  prev )
           prev->next = tvp->next;
           else
           the_thread->task_variables = (  rtems_task_variable_t * )tvp->next;
          
           _RTEMS_Tasks_Invoke_task_variable_dtor(   the_thread,   tvp  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           prev = tvp;
           tvp = (  rtems_task_variable_t * )tvp->next;
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_INVALID_ADDRESS;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Dispatch(   );
           return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/taskvariableget.c

       1  /*
           * rtems_task_variable_get - Get a per-task variable
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskvariableget.c,  v 1.9 2007/11/30 21:49:41 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/wkspace.h>
          
          /*
           * rtems_task_variable_get
           *
           * This directive gets the value of a task variable.
           */
          
      29  rtems_status_code rtems_task_variable_get(  
           rtems_id tid,  
           void **ptr,  
           void **result
           )
          {
           Thread_Control *the_thread;
           Objects_Locations location;
           rtems_task_variable_t *tvp;
          
           if (   !ptr  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !result  )
           return RTEMS_INVALID_ADDRESS;
          
           the_thread = _Thread_Get (  tid,   &location );
           switch (  location ) {
          
           case OBJECTS_LOCAL:
           /*
           * Figure out if the variable is in this task's list.
           */
           tvp = the_thread->task_variables;
           while (  tvp ) {
           if (  tvp->ptr == ptr ) {
           /*
           * Should this return the current (  i.e not the
           * saved ) value if `tid' is the current task?
           */
           *result = tvp->tval;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
           tvp = (  rtems_task_variable_t * )tvp->next;
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_INVALID_ADDRESS;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           _Thread_Dispatch(   );
           return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
          #endif
          
           case OBJECTS_ERROR:
           break;
           }
           return RTEMS_INVALID_ID;
          }

rtems/src/taskwakeafter.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskwakeafter.c,  v 1.4 2005/01/18 09:03:45 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_task_wake_after
           *
           * This directive suspends the requesting thread for the given amount
           * of ticks.
           *
           * Input parameters:
           * ticks - number of ticks to wait
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - always successful
           */
          
      49  rtems_status_code rtems_task_wake_after(  
           rtems_interval ticks
           )
          {
           _Thread_Disable_dispatch(   );
           if (   ticks == 0  ) {
           _Thread_Yield_processor(   );
           } else {
           _Thread_Set_state(   _Thread_Executing,   STATES_DELAYING  );
           _Watchdog_Initialize(  
           &_Thread_Executing->Timer,  
           _Thread_Delay_ended,  
           _Thread_Executing->Object.id,  
           NULL
            );
           _Watchdog_Insert_ticks(   &_Thread_Executing->Timer,   ticks  );
           }
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/taskwakewhen.c

       1  /*
           * RTEMS Task Manager
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: taskwakewhen.c,  v 1.7 2008/12/08 19:41:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/rtems/modes.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/score/object.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/states.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/sysstate.h>
          
          /*PAGE
           *
           * rtems_task_wake_when
           *
           * This directive blocks the requesting thread until the given date and
           * time is reached.
           *
           * Input parameters:
           * time_buffer - pointer to the time and date structure
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      51  rtems_status_code rtems_task_wake_when(  
           rtems_time_of_day *time_buffer
           )
          {
           Watchdog_Interval seconds;
          
           if (   !_TOD_Is_set  )
           return RTEMS_NOT_DEFINED;
          
           if (   !time_buffer  )
           return RTEMS_INVALID_ADDRESS;
          
           time_buffer->ticks = 0;
          
           if (   !_TOD_Validate(   time_buffer  )  )
           return RTEMS_INVALID_CLOCK;
          
           seconds = _TOD_To_seconds(   time_buffer  );
          
           if (   seconds <= _TOD_Seconds_since_epoch(   )  )
           return RTEMS_INVALID_CLOCK;
          
           _Thread_Disable_dispatch(   );
           _Thread_Set_state(   _Thread_Executing,   STATES_WAITING_FOR_TIME  );
           _Watchdog_Initialize(  
           &_Thread_Executing->Timer,  
           _Thread_Delay_ended,  
           _Thread_Executing->Object.id,  
           NULL
            );
           _Watchdog_Insert_seconds(  
           &_Thread_Executing->Timer,  
           seconds - _TOD_Seconds_since_epoch(   )
            );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/timercancel.c

       1  /*
           * Timer Manager - rtems_timer_cancel directive
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timercancel.c,  v 1.9 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_timer_cancel
           *
           * This directive allows a thread to cancel a timer.
           *
           * Input parameters:
           * id - timer id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      42  rtems_status_code rtems_timer_cancel(  
           rtems_id id
           )
          {
           Timer_Control *the_timer;
           Objects_Locations location;
          
           the_timer = _Timer_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   !_Timer_Is_dormant_class(   the_timer->the_class  )  )
           (  void ) _Watchdog_Remove(   &the_timer->Ticker  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/timercreate.c

       1  /*
           * Timer Manager - rtems_timer_create directive
           *
           *
           * COPYRIGHT (  c ) 1989-2002.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timercreate.c,  v 1.10 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_timer_create
           *
           * This directive creates a timer and performs some initialization.
           *
           * Input parameters:
           * name - timer name
           * id - pointer to timer id
           *
           * Output parameters:
           * id - timer id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      44  rtems_status_code rtems_timer_create(  
           rtems_name name,  
           rtems_id *id
           )
          {
           Timer_Control *the_timer;
          
           if (   !rtems_is_name_valid(   name  )  )
           return RTEMS_INVALID_NAME;
          
           if (   !id  )
           return RTEMS_INVALID_ADDRESS;
          
           _Thread_Disable_dispatch(   ); /* to prevent deletion */
          
           the_timer = _Timer_Allocate(   );
          
           if (   !the_timer  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_TOO_MANY;
           }
          
           the_timer->the_class = TIMER_DORMANT;
           _Watchdog_Initialize(   &the_timer->Ticker,   NULL,   0,   NULL  );
          
           _Objects_Open(  
           &_Timer_Information,  
           &the_timer->Object,  
           (  Objects_Name ) name
            );
          
           *id = the_timer->Object.id;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          }

rtems/src/timerdelete.c

       1  /*
           * Timer Manager - rtems_timer_delete directive
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timerdelete.c,  v 1.9 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_timer_delete
           *
           * This directive allows a thread to delete a timer.
           *
           * Input parameters:
           * id - timer id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      42  rtems_status_code rtems_timer_delete(  
           rtems_id id
           )
          {
           Timer_Control *the_timer;
           Objects_Locations location;
          
           the_timer = _Timer_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           _Objects_Close(   &_Timer_Information,   &the_timer->Object  );
           (  void ) _Watchdog_Remove(   &the_timer->Ticker  );
           _Timer_Free(   the_timer  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/timerfireafter.c

       1  /*
           * Timer Manager - rtems_timer_fire_after directive
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timerfireafter.c,  v 1.11 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_timer_fire_after
           *
           * This directive allows a thread to start a timer.
           *
           * Input parameters:
           * id - timer id
           * ticks - interval until routine is fired
           * routine - routine to schedule
           * user_data - passed as argument to routine when it is fired
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      45  rtems_status_code rtems_timer_fire_after(  
           rtems_id id,  
           rtems_interval ticks,  
           rtems_timer_service_routine_entry routine,  
           void *user_data
           )
          {
           Timer_Control *the_timer;
           Objects_Locations location;
           ISR_Level level;
          
           if (   ticks == 0  )
           return RTEMS_INVALID_NUMBER;
          
           if (   !routine  )
           return RTEMS_INVALID_ADDRESS;
          
           the_timer = _Timer_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           (  void ) _Watchdog_Remove(   &the_timer->Ticker  );
          
           _ISR_Disable(   level  );
          
           /*
           * Check to see if the watchdog has just been inserted by a
           * higher priority interrupt. If so,   abandon this insert.
           */
          
           if (   the_timer->Ticker.state != WATCHDOG_INACTIVE  ) {
           _ISR_Enable(   level  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
          
           /*
           * OK. Now we now the timer was not rescheduled by an interrupt
           * so we can atomically initialize it as in use.
           */
          
           the_timer->the_class = TIMER_INTERVAL;
           _Watchdog_Initialize(   &the_timer->Ticker,   routine,   id,   user_data  );
           _ISR_Enable(   level  );
          
          
           _Watchdog_Insert_ticks(   &the_timer->Ticker,   ticks  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/timerfirewhen.c

       1  /*
           * Timer Manager - rtems_timer_fire_when directive
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timerfirewhen.c,  v 1.10 2009/12/15 18:26:41 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_timer_fire_when
           *
           * This directive allows a thread to start a timer.
           *
           * Input parameters:
           * id - timer id
           * wall_time - time of day to fire timer
           * routine - routine to schedule
           * user_data - passed as argument to routine when it is fired
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      45  rtems_status_code rtems_timer_fire_when(  
           rtems_id id,  
           rtems_time_of_day *wall_time,  
           rtems_timer_service_routine_entry routine,  
           void *user_data
           )
          {
           Timer_Control *the_timer;
           Objects_Locations location;
           rtems_interval seconds;
          
           if (   !_TOD_Is_set  )
           return RTEMS_NOT_DEFINED;
          
           if (   !_TOD_Validate(   wall_time  )  )
           return RTEMS_INVALID_CLOCK;
          
           if (   !routine  )
           return RTEMS_INVALID_ADDRESS;
          
           seconds = _TOD_To_seconds(   wall_time  );
           if (   seconds <= _TOD_Seconds_since_epoch(   )  )
           return RTEMS_INVALID_CLOCK;
          
           the_timer = _Timer_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           (  void ) _Watchdog_Remove(   &the_timer->Ticker  );
           the_timer->the_class = TIMER_TIME_OF_DAY;
           _Watchdog_Initialize(   &the_timer->Ticker,   routine,   id,   user_data  );
           _Watchdog_Insert_seconds(  
           &the_timer->Ticker,  
           seconds - _TOD_Seconds_since_epoch(   )
            );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/timergetinfo.c

       1  /*
           * Timer Manager - rtems_timer_get_information directive
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timergetinfo.c,  v 1.8 2009/12/15 18:26:42 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_timer_get_information
           *
           * This directive allows a thread to obtain information about a timer.
           *
           * Input parameters:
           * id - timer id
           * the_info - pointer to timer information block
           *
           * Output parameters:
           * *the_info - region information block filled in
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           *
           */
          
      45  rtems_status_code rtems_timer_get_information(  
           rtems_id id,  
           rtems_timer_information *the_info
           )
          {
           Timer_Control *the_timer;
           Objects_Locations location;
          
           if (   !the_info  )
           return RTEMS_INVALID_ADDRESS;
          
           the_timer = _Timer_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           the_info->the_class = the_timer->the_class;
           the_info->initial = the_timer->Ticker.initial;
           the_info->start_time = the_timer->Ticker.start_time;
           the_info->stop_time = the_timer->Ticker.stop_time;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/timerident.c

       1  /*
           * Timer Manager - rtems_timer_ident directive
           *
           *
           * COPYRIGHT (  c ) 1989-2002.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timerident.c,  v 1.10 2009/12/15 18:26:42 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_timer_ident
           *
           * This directive returns the system ID associated with
           * the timer name.
           *
           * Input parameters:
           * name - user defined message queue name
           * id - pointer to timer id
           *
           * Output parameters:
           * *id - message queue id
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      45  rtems_status_code rtems_timer_ident(  
           rtems_name name,  
           rtems_id *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
          
           status = _Objects_Name_to_id_u32(  
           &_Timer_Information,  
           name,  
           OBJECTS_SEARCH_LOCAL_NODE,  
           id
            );
          
           return _Status_Object_name_errors_to_status[ status ];
          }

rtems/src/timerreset.c

       1  /*
           * Timer Manager - rtems_timer_reset directive
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timerreset.c,  v 1.13 2009/12/15 18:26:42 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_timer_reset
           *
           * This directive allows a thread to reset a timer.
           *
           * Input parameters:
           * id - timer id
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      42  rtems_status_code rtems_timer_reset(  
           rtems_id id
           )
          {
           Timer_Control *the_timer;
           Objects_Locations location;
           rtems_status_code status = RTEMS_SUCCESSFUL;
          
           the_timer = _Timer_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           if (   the_timer->the_class == TIMER_INTERVAL  ) {
           _Watchdog_Remove(   &the_timer->Ticker  );
           _Watchdog_Insert(   &_Watchdog_Ticks_chain,   &the_timer->Ticker  );
           } else if (   the_timer->the_class == TIMER_INTERVAL_ON_TASK  ) {
           Timer_server_Control *timer_server = _Timer_server;
          
           /*
           * There is no way for a timer to have this class unless
           * it was scheduled as a server fire. That requires that
           * the Timer Server be initiated. So this error cannot
           * occur unless something is internally wrong.
           */
           #if defined(  RTEMS_DEBUG )
           if (   !timer_server  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_INCORRECT_STATE;
           }
           #endif
           _Watchdog_Remove(   &the_timer->Ticker  );
           (  *timer_server->schedule_operation )(   timer_server,   the_timer  );
           } else {
           /*
           * Must be dormant or time of day timer (  e.g. TIMER_DORMANT,  
           * TIMER_TIME_OF_DAY,   or TIMER_TIME_OF_DAY_ON_TASK ). We
           * can only reset active interval timers.
           */
           status = RTEMS_NOT_DEFINED;
           }
           _Thread_Enable_dispatch(   );
           return status;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/timerserver.c

       1  /**
           * @file timerserver.c
           *
           * Timer Manager - rtems_timer_initiate_server directive along with
           * the Timer Server Body and support routines
           *
           * @note Data specific to the Timer Server is declared in this
           * file as the Timer Server so it does not have to be in the
           * minimum footprint. It is only really required when
           * task-based timers are used. Since task-based timers can
           * not be started until the server is initiated,   this structure
           * does not have to be initialized until then.
           */
          
          /* COPYRIGHT (  c ) 1989-2008.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * Copyright (  c ) 2009 embedded brains GmbH.
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: timerserver.c,  v 1.24 2009/11/30 09:08:35 thomas Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          #include <rtems/rtems/tasks.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/thread.h>
          
          static Timer_server_Control _Timer_server_Default;
          
      46  static void _Timer_server_Stop_interval_system_watchdog(  
           Timer_server_Control *ts
           )
          {
           _Watchdog_Remove(   &ts->Interval_watchdogs.System_watchdog  );
          }
          
      53  static void _Timer_server_Reset_interval_system_watchdog(  
           Timer_server_Control *ts
           )
          {
           ISR_Level level;
          
           _Timer_server_Stop_interval_system_watchdog(   ts  );
          
           _ISR_Disable(   level  );
           if (   !_Chain_Is_empty(   &ts->Interval_watchdogs.Chain  )  ) {
           Watchdog_Interval delta_interval =
           _Watchdog_First(   &ts->Interval_watchdogs.Chain  )->delta_interval;
           _ISR_Enable(   level  );
          
           /*
           * The unit is TICKS here.
           */
           _Watchdog_Insert_ticks(  
           &ts->Interval_watchdogs.System_watchdog,  
           delta_interval
            );
           } else {
           _ISR_Enable(   level  );
           }
          }
          
      79  static void _Timer_server_Stop_tod_system_watchdog(  
           Timer_server_Control *ts
           )
          {
           _Watchdog_Remove(   &ts->TOD_watchdogs.System_watchdog  );
          }
          
      86  static void _Timer_server_Reset_tod_system_watchdog(  
           Timer_server_Control *ts
           )
          {
           ISR_Level level;
          
           _Timer_server_Stop_tod_system_watchdog(   ts  );
          
           _ISR_Disable(   level  );
           if (   !_Chain_Is_empty(   &ts->TOD_watchdogs.Chain  )  ) {
           Watchdog_Interval delta_interval =
           _Watchdog_First(   &ts->TOD_watchdogs.Chain  )->delta_interval;
           _ISR_Enable(   level  );
          
           /*
           * The unit is SECONDS here.
           */
           _Watchdog_Insert_seconds(  
           &ts->TOD_watchdogs.System_watchdog,  
           delta_interval
            );
           } else {
           _ISR_Enable(   level  );
           }
          }
          
     112  static void _Timer_server_Insert_timer(  
           Timer_server_Control *ts,  
           Timer_Control *timer
           )
          {
           if (   timer->the_class == TIMER_INTERVAL_ON_TASK  ) {
           _Watchdog_Insert(   &ts->Interval_watchdogs.Chain,   &timer->Ticker  );
           } else if (   timer->the_class == TIMER_TIME_OF_DAY_ON_TASK  ) {
           _Watchdog_Insert(   &ts->TOD_watchdogs.Chain,   &timer->Ticker  );
           }
          }
          
     124  static void _Timer_server_Insert_timer_and_make_snapshot(  
           Timer_server_Control *ts,  
           Timer_Control *timer
           )
          {
           Watchdog_Control *first_watchdog;
           Watchdog_Interval delta_interval;
           Watchdog_Interval last_snapshot;
           Watchdog_Interval snapshot;
           Watchdog_Interval delta;
           ISR_Level level;
          
           /*
           * We have to update the time snapshots here,   because otherwise we may have
           * problems with the integer range of the delta values. The time delta DT
           * from the last snapshot to now may be arbitrarily long. The last snapshot
           * is the reference point for the delta chain. Thus if we do not update the
           * reference point we have to add DT to the initial delta of the watchdog
           * being inserted. This could result in an integer overflow.
           */
          
           _Thread_Disable_dispatch(   );
          
           if (   timer->the_class == TIMER_INTERVAL_ON_TASK  ) {
           /*
           * We have to advance the last known ticks value of the server and update
           * the watchdog chain accordingly.
           */
           _ISR_Disable(   level  );
           snapshot = _Watchdog_Ticks_since_boot;
           last_snapshot = ts->Interval_watchdogs.last_snapshot;
           if (   !_Chain_Is_empty(   &ts->Interval_watchdogs.Chain  )  ) {
           first_watchdog = _Watchdog_First(   &ts->Interval_watchdogs.Chain  );
          
           /*
           * We assume adequate unsigned arithmetic here.
           */
           delta = snapshot - last_snapshot;
          
           delta_interval = first_watchdog->delta_interval;
           if (  delta_interval > delta ) {
           delta_interval -= delta;
           } else {
           delta_interval = 0;
           }
           first_watchdog->delta_interval = delta_interval;
           }
           ts->Interval_watchdogs.last_snapshot = snapshot;
           _ISR_Enable(   level  );
          
           _Watchdog_Insert(   &ts->Interval_watchdogs.Chain,   &timer->Ticker  );
          
           if (   !ts->active  ) {
           _Timer_server_Reset_interval_system_watchdog(   ts  );
           }
           } else if (   timer->the_class == TIMER_TIME_OF_DAY_ON_TASK  ) {
           /*
           * We have to advance the last known seconds value of the server and update
           * the watchdog chain accordingly.
           */
           _ISR_Disable(   level  );
           snapshot = (  Watchdog_Interval ) _TOD_Seconds_since_epoch(   );
           last_snapshot = ts->TOD_watchdogs.last_snapshot;
           if (   !_Chain_Is_empty(   &ts->TOD_watchdogs.Chain  )  ) {
           first_watchdog = _Watchdog_First(   &ts->TOD_watchdogs.Chain  );
           delta_interval = first_watchdog->delta_interval;
           if (   snapshot > last_snapshot  ) {
           /*
           * We advanced in time.
           */
           delta = snapshot - last_snapshot;
           if (  delta_interval > delta ) {
           delta_interval -= delta;
           } else {
           delta_interval = 0;
           }
           } else {
           /*
           * Someone put us in the past.
           */
           delta = last_snapshot - snapshot;
           delta_interval += delta;
           }
           first_watchdog->delta_interval = delta_interval;
           }
           ts->TOD_watchdogs.last_snapshot = snapshot;
           _ISR_Enable(   level  );
          
           _Watchdog_Insert(   &ts->TOD_watchdogs.Chain,   &timer->Ticker  );
          
           if (   !ts->active  ) {
           _Timer_server_Reset_tod_system_watchdog(   ts  );
           }
           }
          
           _Thread_Enable_dispatch(   );
          }
          
     222  static void _Timer_server_Schedule_operation_method(  
           Timer_server_Control *ts,  
           Timer_Control *timer
           )
          {
           if (   ts->insert_chain == NULL  ) {
           _Timer_server_Insert_timer_and_make_snapshot(   ts,   timer  );
           } else {
           /*
           * We interrupted a critical section of the timer server. The timer
           * server is not preemptible,   so we must be in interrupt context here. No
           * thread dispatch will happen until the timer server finishes its
           * critical section. We have to use the protected chain methods because
           * we may be interrupted by a higher priority interrupt.
           */
           _Chain_Append(   ts->insert_chain,   &timer->Object.Node  );
           }
          }
          
     241  static void _Timer_server_Process_interval_watchdogs(  
           Timer_server_Watchdogs *watchdogs,  
           Chain_Control *fire_chain
           )
          {
           Watchdog_Interval snapshot = _Watchdog_Ticks_since_boot;
          
           /*
           * We assume adequate unsigned arithmetic here.
           */
           Watchdog_Interval delta = snapshot - watchdogs->last_snapshot;
          
           watchdogs->last_snapshot = snapshot;
          
           _Watchdog_Adjust_to_chain(   &watchdogs->Chain,   delta,   fire_chain  );
          }
          
     258  static void _Timer_server_Process_tod_watchdogs(  
           Timer_server_Watchdogs *watchdogs,  
           Chain_Control *fire_chain
           )
          {
           Watchdog_Interval snapshot = (  Watchdog_Interval ) _TOD_Seconds_since_epoch(   );
           Watchdog_Interval last_snapshot = watchdogs->last_snapshot;
           Watchdog_Interval delta;
          
           /*
           * Process the seconds chain. Start by checking that the Time
           * of Day (  TOD ) has not been set backwards. If it has then
           * we want to adjust the watchdogs->Chain to indicate this.
           */
           if (   snapshot > last_snapshot  ) {
           /*
           * This path is for normal forward movement and cases where the
           * TOD has been set forward.
           */
           delta = snapshot - last_snapshot;
           _Watchdog_Adjust_to_chain(   &watchdogs->Chain,   delta,   fire_chain  );
          
           } else if (   snapshot < last_snapshot  ) {
           /*
           * The current TOD is before the last TOD which indicates that
           * TOD has been set backwards.
           */
           delta = last_snapshot - snapshot;
           _Watchdog_Adjust(   &watchdogs->Chain,   WATCHDOG_BACKWARD,   delta  );
           }
          
           watchdogs->last_snapshot = snapshot;
          }
          
     292  static void _Timer_server_Process_insertions(   Timer_server_Control *ts  )
          {
           while (   true  ) {
           Timer_Control *timer = (  Timer_Control * ) _Chain_Get(   ts->insert_chain  );
          
           if (   timer == NULL  ) {
           break;
           }
          
           _Timer_server_Insert_timer(   ts,   timer  );
           }
          }
          
     305  static void _Timer_server_Get_watchdogs_that_fire_now(  
           Timer_server_Control *ts,  
           Chain_Control *insert_chain,  
           Chain_Control *fire_chain
           )
          {
           /*
           * Afterwards all timer inserts are directed to this chain and the interval
           * and TOD chains will be no more modified by other parties.
           */
           ts->insert_chain = insert_chain;
          
           while (   true  ) {
           ISR_Level level;
          
           /*
           * Remove all the watchdogs that need to fire so we can invoke them.
           */
           _Timer_server_Process_interval_watchdogs(  
           &ts->Interval_watchdogs,  
           fire_chain
            );
           _Timer_server_Process_tod_watchdogs(   &ts->TOD_watchdogs,   fire_chain  );
          
           /*
           * The insertions have to take place here,   because they reference the
           * current time. The previous process methods take a snapshot of the
           * current time. In case someone inserts a watchdog with an initial value
           * of zero it will be processed in the next iteration of the timer server
           * body loop.
           */
           _Timer_server_Process_insertions(   ts  );
          
           _ISR_Disable(   level  );
           if (   _Chain_Is_empty(   insert_chain  )  ) {
           ts->insert_chain = NULL;
           _ISR_Enable(   level  );
          
           break;
           } else {
           _ISR_Enable(   level  );
           }
           }
          }
          
          /**
           * @brief Timer server body.
           *
           * This is the server for task based timers. This task executes whenever a
           * task-based timer should fire. It services both "after" and "when" timers.
           * It is not created automatically but must be created explicitly by the
           * application before task-based timers may be initiated. The parameter
           * @a arg points to the corresponding timer server control block.
           */
     359  static rtems_task _Timer_server_Body(  
           rtems_task_argument arg
           )
          {
           Timer_server_Control *ts = (  Timer_server_Control * ) arg;
           Chain_Control insert_chain;
           Chain_Control fire_chain;
          
           _Chain_Initialize_empty(   &insert_chain  );
           _Chain_Initialize_empty(   &fire_chain  );
          
           while (   true  ) {
           _Timer_server_Get_watchdogs_that_fire_now(   ts,   &insert_chain,   &fire_chain  );
          
           if (   !_Chain_Is_empty(   &fire_chain  )  ) {
           /*
           * Fire the watchdogs.
           */
           while (   true  ) {
           Watchdog_Control *watchdog;
           ISR_Level level;
          
           /*
           * It is essential that interrupts are disable here since an interrupt
           * service routine may remove a watchdog from the chain.
           */
           _ISR_Disable(   level  );
           watchdog = (  Watchdog_Control * ) _Chain_Get_unprotected(   &fire_chain  );
           if (   watchdog != NULL  ) {
           watchdog->state = WATCHDOG_INACTIVE;
           _ISR_Enable(   level  );
           } else {
           _ISR_Enable(   level  );
          
           break;
           }
          
           /*
           * The timer server may block here and wait for resources or time.
           * The system watchdogs are inactive and will remain inactive since
           * the active flag of the timer server is true.
           */
           (  *watchdog->routine )(   watchdog->id,   watchdog->user_data  );
           }
           } else {
           ts->active = false;
          
           /*
           * Block until there is something to do.
           */
           _Thread_Disable_dispatch(   );
           _Thread_Set_state(   ts->thread,   STATES_DELAYING  );
           _Timer_server_Reset_interval_system_watchdog(   ts  );
           _Timer_server_Reset_tod_system_watchdog(   ts  );
           _Thread_Enable_dispatch(   );
          
           ts->active = true;
          
           /*
           * Maybe an interrupt did reset the system timers,   so we have to stop
           * them here. Since we are active now,   there will be no more resets
           * until we are inactive again.
           */
           _Timer_server_Stop_interval_system_watchdog(   ts  );
           _Timer_server_Stop_tod_system_watchdog(   ts  );
           }
           }
          }
          
          /**
           * @brief rtems_timer_initiate_server
           *
           * This directive creates and starts the server for task-based timers.
           * It must be invoked before any task-based timers can be initiated.
           *
           * @param[in] priority is the timer server priority
           * @param[in] stack_size is the stack size in bytes
           * @param[in] attribute_set is the timer server attributes
           *
           * @return This method returns RTEMS_SUCCESSFUL if successful and an
           * error code otherwise.
           */
     441  rtems_status_code rtems_timer_initiate_server(  
           uint32_t priority,  
           uint32_t stack_size,  
           rtems_attribute attribute_set
           )
          {
           rtems_id id;
           rtems_status_code status;
           rtems_task_priority _priority;
           static bool initialized = false;
           bool tmpInitialized;
           Timer_server_Control *ts = &_Timer_server_Default;
          
           /*
           * Make sure the requested priority is valid. The if is
           * structured so we check it is invalid before looking for
           * a specific invalid value as the default.
           */
           _priority = priority;
           if (   !_RTEMS_tasks_Priority_is_valid(   priority  )  ) {
           if (   priority != RTEMS_TIMER_SERVER_DEFAULT_PRIORITY  )
           return RTEMS_INVALID_PRIORITY;
           _priority = 0;
           }
          
           /*
           * Just to make sure this is only called once.
           */
           _Thread_Disable_dispatch(   );
           tmpInitialized = initialized;
           initialized = true;
           _Thread_Enable_dispatch(   );
          
           if (   tmpInitialized  )
           return RTEMS_INCORRECT_STATE;
          
           /*
           * Create the Timer Server with the name the name of "TIME". The attribute
           * RTEMS_SYSTEM_TASK allows us to set a priority to 0 which will makes it
           * higher than any other task in the system. It can be viewed as a low
           * priority interrupt. It is also always NO_PREEMPT so it looks like
           * an interrupt to other tasks.
           *
           * We allow the user to override the default priority because the Timer
           * Server can invoke TSRs which must adhere to language run-time or
           * other library rules. For example,   if using a TSR written in Ada the
           * Server should run at the same priority as the priority Ada task.
           * Otherwise,   the priority ceiling for the mutex used to protect the
           * GNAT run-time is violated.
           */
           status = rtems_task_create(  
           _Objects_Build_name(  'T',  'I',  'M',  'E' ),   /* "TIME" */
           _priority,   /* create with priority 1 since 0 is illegal */
           stack_size,   /* let user specify stack size */
           RTEMS_NO_PREEMPT,   /* no preempt is like an interrupt */
           /* user may want floating point but we need */
           /* system task specified for 0 priority */
           attribute_set | RTEMS_SYSTEM_TASK,  
           &id /* get the id back */
            );
           if (  status ) {
           initialized = false;
           return status;
           }
          
           /*
           * Do all the data structure initialization before starting the
           * Timer Server so we do not have to have a critical section.
           */
          
           /*
           * We work with the TCB pointer,   not the ID,   so we need to convert
           * to a TCB pointer from here out.
           */
           ts->thread = (  Thread_Control * )_Objects_Get_local_object(  
           &_RTEMS_tasks_Information,  
           _Objects_Get_index(  id )
            );
          
           /*
           * Initialize the timer lists that the server will manage.
           */
           _Chain_Initialize_empty(   &ts->Interval_watchdogs.Chain  );
           _Chain_Initialize_empty(   &ts->TOD_watchdogs.Chain  );
          
           /*
           * Initialize the timers that will be used to control when the
           * Timer Server wakes up and services the task-based timers.
           */
           _Watchdog_Initialize(  
           &ts->Interval_watchdogs.System_watchdog,  
           _Thread_Delay_ended,  
           id,  
           NULL
            );
           _Watchdog_Initialize(  
           &ts->TOD_watchdogs.System_watchdog,  
           _Thread_Delay_ended,  
           id,  
           NULL
            );
          
           /*
           * Initialize the pointer to the timer schedule method so applications that
           * do not use the Timer Server do not have to pull it in.
           */
           ts->schedule_operation = _Timer_server_Schedule_operation_method;
          
           ts->Interval_watchdogs.last_snapshot = _Watchdog_Ticks_since_boot;
           ts->TOD_watchdogs.last_snapshot = (  Watchdog_Interval ) _TOD_Seconds_since_epoch(   );
          
           ts->insert_chain = NULL;
           ts->active = false;
          
           /*
           * The default timer server is now available.
           */
           _Timer_server = ts;
          
           /*
           * Start the timer server
           */
           status = rtems_task_start(  
           id,  
           _Timer_server_Body,  
           (  rtems_task_argument ) ts
            );
          
           #if defined(  RTEMS_DEBUG )
           /*
           * One would expect a call to rtems_task_delete(   ) here to clean up
           * but there is actually no way (  in normal circumstances ) that the
           * start can fail. The id and starting address are known to be
           * be good. If this service fails,   something is weirdly wrong on the
           * target such as a stray write in an ISR or incorrect memory layout.
           */
           if (  status ) {
           initialized = false;
           }
           #endif
          
           return status;
          }

rtems/src/timerserverfireafter.c

       1  /*
           * Timer Manager - rtems_timer_server fire_after directive
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timerserverfireafter.c,  v 1.15 2009/12/15 18:26:42 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_timer_server_fire_after
           *
           * This directive allows a thread to start a timer which will by
           * executed by the Timer Server when it fires.
           *
           * Input parameters:
           * id - timer id
           * ticks - interval until routine is fired
           * routine - routine to schedule
           * user_data - passed as argument to routine when it is fired
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      46  rtems_status_code rtems_timer_server_fire_after(  
           rtems_id id,  
           rtems_interval ticks,  
           rtems_timer_service_routine_entry routine,  
           void *user_data
           )
          {
           Timer_Control *the_timer;
           Objects_Locations location;
           ISR_Level level;
           Timer_server_Control *timer_server = _Timer_server;
          
           if (   !timer_server  )
           return RTEMS_INCORRECT_STATE;
          
           if (   !routine  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   ticks == 0  )
           return RTEMS_INVALID_NUMBER;
          
           the_timer = _Timer_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           (  void ) _Watchdog_Remove(   &the_timer->Ticker  );
          
           _ISR_Disable(   level  );
          
           /*
           * Check to see if the watchdog has just been inserted by a
           * higher priority interrupt. If so,   abandon this insert.
           */
          
           if (   the_timer->Ticker.state != WATCHDOG_INACTIVE  ) {
           _ISR_Enable(   level  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
           }
          
           /*
           * OK. Now we now the timer was not rescheduled by an interrupt
           * so we can atomically initialize it as in use.
           */
          
           the_timer->the_class = TIMER_INTERVAL_ON_TASK;
           _Watchdog_Initialize(   &the_timer->Ticker,   routine,   id,   user_data  );
           the_timer->Ticker.initial = ticks;
           _ISR_Enable(   level  );
          
           (  *timer_server->schedule_operation )(   timer_server,   the_timer  );
          
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/timerserverfirewhen.c

       1  /*
           * Timer Manager - rtems_timer_server fire_when directive
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timerserverfirewhen.c,  v 1.14 2009/12/15 18:26:42 humph Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/rtems/timer.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * rtems_timer_server_fire_when
           *
           * This directive allows a thread to start a timer which will by
           * executed by the Timer Server when it fires.
           *
           * Input parameters:
           * id - timer id
           * wall_time - time of day to fire timer
           * routine - routine to schedule
           * user_data - passed as argument to routine when it is fired
           *
           * Output parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      46  rtems_status_code rtems_timer_server_fire_when(  
           rtems_id id,  
           rtems_time_of_day *wall_time,  
           rtems_timer_service_routine_entry routine,  
           void *user_data
           )
          {
           Timer_Control *the_timer;
           Objects_Locations location;
           rtems_interval seconds;
           Timer_server_Control *timer_server = _Timer_server;
          
           if (   !timer_server  )
           return RTEMS_INCORRECT_STATE;
          
           if (   !_TOD_Is_set  )
           return RTEMS_NOT_DEFINED;
          
           if (   !routine  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !_TOD_Validate(   wall_time  )  )
           return RTEMS_INVALID_CLOCK;
          
           seconds = _TOD_To_seconds(   wall_time  );
           if (   seconds <= _TOD_Seconds_since_epoch(   )  )
           return RTEMS_INVALID_CLOCK;
          
           the_timer = _Timer_Get(   id,   &location  );
           switch (   location  ) {
          
           case OBJECTS_LOCAL:
           (  void ) _Watchdog_Remove(   &the_timer->Ticker  );
           the_timer->the_class = TIMER_TIME_OF_DAY_ON_TASK;
           _Watchdog_Initialize(   &the_timer->Ticker,   routine,   id,   user_data  );
           the_timer->Ticker.initial = seconds - _TOD_Seconds_since_epoch(   );
          
           (  *timer_server->schedule_operation )(   timer_server,   the_timer  );
          
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

rtems/src/workspace.c

       1  /*
           * Workspace Handler
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: workspace.c,  v 1.5 2009/05/13 16:48:08 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/protectedheap.h>
          #include <rtems/score/interr.h>
          #include <rtems/config.h>
          
          #include <string.h> /* for memset */
          
      26  bool rtems_workspace_get_information(  
           Heap_Information_block *the_info
           )
          {
           if (   !the_info  )
           return false;
          
           return _Protected_heap_Get_information(   &_Workspace_Area,   the_info  );
          }
          
          /*
           * _Workspace_Allocate
           */
      39  bool rtems_workspace_allocate(  
           uintptr_t bytes,  
           void **pointer
           )
          {
           void *ptr;
          
           /*
           * check the arguments
           */
           if (   !pointer  )
           return false;
          
           if (   !bytes  )
           return false;
          
           /*
           * Allocate the memory
           */
           ptr = _Protected_heap_Allocate(   &_Workspace_Area,   (  intptr_t ) bytes  );
           if (  !ptr )
           return false;
          
           *pointer = ptr;
           return true;
          }
          
          /*
           * _Workspace_Allocate
           */
      69  bool rtems_workspace_free(  
           void *pointer
           )
          {
           return _Protected_heap_Free(   &_Workspace_Area,   pointer  );
          }
          

sapi/src/chainappendnotify.c

       1  /**
           * @file
           *
           * @ingroup ClassicChains
           *
           * @brief rtems_chain_append_with_notification(   ) implementation.
           */
          
          /*
           * Copyright (  c ) 2010 embedded brains GmbH. All rights reserved.
           *
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * 82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/chain.h>
          
      29  rtems_status_code rtems_chain_append_with_notification(  
           rtems_chain_control *chain,  
           rtems_chain_node *node,  
           rtems_id task,  
           rtems_event_set events
           )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           bool was_empty = rtems_chain_append_with_empty_check(   chain,   node  );
          
           if (   was_empty  ) {
           sc = rtems_event_send(   task,   events  );
           }
          
           return sc;
          }

sapi/src/chaingetnotify.c

       1  /**
           * @file
           *
           * @ingroup ClassicChains
           *
           * @brief rtems_chain_get_with_notification(   ) implementation.
           */
          
          /*
           * Copyright (  c ) 2010 embedded brains GmbH. All rights reserved.
           *
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * 82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/chain.h>
          
      29  rtems_status_code rtems_chain_get_with_notification(  
           rtems_chain_control *chain,  
           rtems_id task,  
           rtems_event_set events,  
           rtems_chain_node **node
           )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           bool is_empty = rtems_chain_get_with_empty_check(   chain,   node  );
          
           if (   is_empty  ) {
           sc = rtems_event_send(   task,   events  );
           }
          
           return sc;
          }

sapi/src/chaingetwait.c

       1  /**
           * @file
           *
           * @ingroup ClassicChains
           *
           * @brief rtems_chain_get_with_wait(   ) implementation.
           */
          
          /*
           * Copyright (  c ) 2010 embedded brains GmbH. All rights reserved.
           *
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * 82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/chain.h>
          
      29  rtems_status_code rtems_chain_get_with_wait(  
           rtems_chain_control *chain,  
           rtems_event_set events,  
           rtems_interval timeout,  
           rtems_chain_node **node_ptr
           )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           rtems_chain_node *node = NULL;
          
           while (  
           sc == RTEMS_SUCCESSFUL
           && (  node = rtems_chain_get(   chain  ) ) == NULL
            ) {
           rtems_event_set out;
           sc = rtems_event_receive(  
           events,  
           RTEMS_EVENT_ALL | RTEMS_WAIT,  
           timeout,  
           &out
            );
           }
          
           *node_ptr = node;
          
           return sc;
          }

sapi/src/chainprependnotify.c

       1  /**
           * @file
           *
           * @ingroup ClassicChains
           *
           * @brief rtems_chain_prepend_with_notification(   ) implementation.
           */
          
          /*
           * Copyright (  c ) 2010 embedded brains GmbH. All rights reserved.
           *
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * 82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/chain.h>
          
      29  rtems_status_code rtems_chain_prepend_with_notification(  
           rtems_chain_control *chain,  
           rtems_chain_node *node,  
           rtems_id task,  
           rtems_event_set events
           )
          {
           rtems_status_code sc = RTEMS_SUCCESSFUL;
           bool was_empty = rtems_chain_prepend_with_empty_check(   chain,   node  );
          
           if (  was_empty ) {
           sc = rtems_event_send(   task,   events  );
           }
          
           return sc;
          }

sapi/src/debug.c

       1  /*
           * Debug Manager
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: debug.c,  v 1.14 2009/07/21 19:27:44 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/debug.h>
          
          /*
           *
           * _Debug_Manager_initialization
           */
      25  void _Debug_Manager_initialization(   void  )
          {
           rtems_debug_disable(   RTEMS_DEBUG_ALL_MASK  );
          }
          
          /*PAGE
           *
           * rtems_debug_enable
           */
      34  void rtems_debug_enable (  
           rtems_debug_control to_be_enabled
           )
          {
           _Debug_Level |= to_be_enabled;
          }
          
          /*
           * rtems_debug_disable
           */
      44  void rtems_debug_disable (  
           rtems_debug_control to_be_disabled
           )
          {
           _Debug_Level &= ~to_be_disabled;
          }
          
          /*
           * rtems_debug_is_enabled
           */
      54  bool rtems_debug_is_enabled(  
           rtems_debug_control level
           )
          {
           return (  _Debug_Level & level ) ? true : false;
          }

sapi/src/exinit.c

       1  /*
           * Initialization Manager
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: exinit.c,  v 1.55 2010/07/29 17:52:09 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * SCORE_INIT and SAPI_INIT are defined so all of the super core and
           * super API data will be included in this object file.
           */
          
          #define SAPI_INIT
          #define SCORE_INIT
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/debug.h>
          #include <rtems/extension.h>
          #include <rtems/fatal.h>
          #include <rtems/init.h>
          #include <rtems/io.h>
          #include <rtems/score/sysstate.h>
          
          #include <rtems/score/apiext.h>
          #include <rtems/score/apimutex.h>
          #include <rtems/score/copyrt.h>
          #include <rtems/score/heap.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #endif
          #include <rtems/score/priority.h>
          #include <rtems/score/prioritybitmap.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/score/wkspace.h>
          
          #include <rtems/sptables.h>
          
          
          #include <rtems/rtems/rtemsapi.h>
          #ifdef RTEMS_POSIX_API
           #include <rtems/posix/posixapi.h>
          #endif
          
          Objects_Information *_Internal_Objects[ OBJECTS_INTERNAL_CLASSES_LAST + 1 ];
          
      62  void rtems_initialize_data_structures(  void )
          {
           /*
           * Dispatching and interrupts are disabled until the end of the
           * initialization sequence. This prevents an inadvertent context
           * switch before the executive is initialized.
           *
           * WARNING: Interrupts should have been disabled by the BSP and
           * are disabled by boot_card(   ).
           */
          
           #if defined(  RTEMS_MULTIPROCESSING )
           /*
           * Initialize the system state based on whether this is an MP system.
           * In an MP configuration,   internally we view single processor
           * systems as a very restricted multiprocessor system.
           */
           _Configuration_MP_table = Configuration.User_multiprocessing_table;
          
           if (   _Configuration_MP_table == NULL  ) {
           _Configuration_MP_table =
           (  void * )&_Initialization_Default_multiprocessing_table;
           _System_state_Handler_initialization(   FALSE  );
           } else {
           _System_state_Handler_initialization(   TRUE  );
           }
           #else
           _System_state_Handler_initialization(   FALSE  );
           #endif
          
           /*
           * Initialize any target architecture specific support as early as possible
           */
           _CPU_Initialize(   );
          
           #if defined(  RTEMS_MULTIPROCESSING )
           _Objects_MP_Handler_early_initialization(   );
           #endif
          
           /*
           * Do this as early as possible to ensure no debugging output
           * is even attempted to be printed.
           */
           _Debug_Manager_initialization(   );
          
           _API_extensions_Initialization(   );
          
           _Thread_Dispatch_initialization(   );
          
           /*
           * Before this is called,   we are not allowed to allocate memory
           * from the Workspace because it is not initialized.
           */
           _Workspace_Handler_initialization(   );
          
           _User_extensions_Handler_initialization(   );
           _ISR_Handler_initialization(   );
          
           /*
           * Initialize the internal support API and allocator Mutex
           */
           _Objects_Information_table[OBJECTS_INTERNAL_API] = _Internal_Objects;
          
           _API_Mutex_Initialization(   1  );
           _API_Mutex_Allocate(   &_RTEMS_Allocator_Mutex  );
          
           _Priority_bit_map_Handler_initialization(   );
           _Watchdog_Handler_initialization(   );
           _TOD_Handler_initialization(   );
          
           _Thread_Handler_initialization(   );
          
           #if defined(  RTEMS_MULTIPROCESSING )
           _Objects_MP_Handler_initialization(   );
           _MPCI_Handler_initialization(   RTEMS_TIMEOUT  );
           #endif
          
          /* MANAGERS */
          
           _RTEMS_API_Initialize(   );
          
           _Extension_Manager_initialization(   );
          
           _IO_Manager_initialization(   );
          
           #ifdef RTEMS_POSIX_API
           _POSIX_API_Initialize(   );
           #endif
          
           _System_state_Set(   SYSTEM_STATE_BEFORE_MULTITASKING  );
          
           /*
           * No threads should be created before this point!!!
           * _Thread_Executing and _Thread_Heir are not set.
           *
           * At this point all API extensions are in place. After the call to
           * _Thread_Create_idle(   ) _Thread_Executing and _Thread_Heir will be set.
           */
           _Thread_Create_idle(   );
          
           /*
           * Scheduling can properly occur now as long as we avoid dispatching.
           */
          }
          
     167  void rtems_initialize_before_drivers(  void )
          {
          
           #if defined(  RTEMS_MULTIPROCESSING )
           _MPCI_Create_server(   );
           #endif
          
           #if defined(  FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API )
           /*
           * Run the API and BSPs predriver hook.
           */
           _API_extensions_Run_predriver(   );
           #endif
          }
          
     182  void rtems_initialize_device_drivers(  void )
          {
           /*
           * Initialize all the device drivers and initialize the MPCI layer.
           *
           * NOTE: The MPCI may be build upon a device driver.
           */
          
           _IO_Initialize_all_drivers(   );
          
           #if defined(  RTEMS_MULTIPROCESSING )
           if (   _System_state_Is_multiprocessing  ) {
           _MPCI_Initialization(   );
           _MPCI_Internal_packets_Send_process_packet(  
           MPCI_PACKETS_SYSTEM_VERIFY
            );
           }
           #endif
          
           /*
           * Run the APIs and BSPs postdriver hooks.
           *
           * The API extensions are supposed to create user initialization tasks.
           */
           _API_extensions_Run_postdriver(   );
          }
          
     209  void rtems_initialize_start_multitasking(  void )
          {
          
           _System_state_Set(   SYSTEM_STATE_BEGIN_MULTITASKING  );
          
           _Thread_Start_multitasking(   );
          
           /*******************************************************************
           *******************************************************************
           *******************************************************************
           ****** APPLICATION RUNS HERE ******
           ****** RETURNS WHEN SYSTEM IS SHUT DOWN ******
           *******************************************************************
           *******************************************************************
           *******************************************************************/
          }

sapi/src/exshutdown.c

       1  /*
           * Initialization Manager
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: exshutdown.c,  v 1.4 2010/08/10 22:56:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/interr.h>
          
          /*
           * rtems_shutdown_executive
           *
           * This kernel routine shutdowns the executive. It halts multitasking
           * and returns control to the application execution "thread" which
           * initialially invoked the rtems_initialize_executive directive.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      35  void rtems_shutdown_executive(  
           uint32_t result
           )
          {
           if (   _System_state_Is_up(   _System_state_Get(   )  )  ) {
           _System_state_Set(   SYSTEM_STATE_SHUTDOWN  );
           _Thread_Stop_multitasking(   );
           }
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_SHUTDOWN_WHEN_NOT_UP
            );
          
          }

sapi/src/extension.c

       1  /*
           * Extension Manager
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: extension.c,  v 1.21 2008/12/17 22:46:04 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/extension.h>
          
          /*PAGE
           *
           * _Extension_Manager_initialization
           *
           * This routine initializes all extension manager related data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      36  void _Extension_Manager_initialization(  void )
          {
           _Objects_Initialize_information(  
           &_Extension_Information,  
           OBJECTS_CLASSIC_API,   /* object API */
           OBJECTS_RTEMS_EXTENSIONS,  
           Configuration.maximum_extensions,  
           sizeof(   Extension_Control  ),  
           false,   /* true if the name is a string */
           RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

sapi/src/extensioncreate.c

       1  /**
           * @file
           *
           * @ingroup ClassicUserExtensions
           *
           * @brief User Extensions Implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: extensioncreate.c,  v 1.8 2010/01/26 15:01:56 thomas Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/extension.h>
          
      30  rtems_status_code rtems_extension_create(  
           rtems_name name,  
           const rtems_extensions_table *extension_table,  
           rtems_id *id
           )
          {
           Extension_Control *the_extension;
          
           if (   !id  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   !rtems_is_name_valid(   name  )  )
           return RTEMS_INVALID_NAME;
          
           _Thread_Disable_dispatch(   ); /* to prevent deletion */
          
           the_extension = _Extension_Allocate(   );
          
           if (   !the_extension  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_TOO_MANY;
           }
          
           _User_extensions_Add_set_with_table(   &the_extension->Extension,   extension_table  );
          
           _Objects_Open(  
           &_Extension_Information,  
           &the_extension->Object,  
           (  Objects_Name ) name
            );
          
           *id = the_extension->Object.id;
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          }

sapi/src/extensiondata.c

       1  /*
           * Extension Manager -- Instantiate Data
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: extensiondata.c,  v 1.1 2007/05/21 23:19:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate extension data */
          #define SAPI_EXT_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/extension.h>
          

sapi/src/extensiondelete.c

       1  /**
           * @file
           *
           * @ingroup ClassicUserExtensions
           *
           * @brief User Extensions Implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: extensiondelete.c,  v 1.7 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/extension.h>
          
      30  rtems_status_code rtems_extension_delete(  
           rtems_id id
           )
          {
           Extension_Control *the_extension;
           Objects_Locations location;
          
           the_extension = _Extension_Get(   id,   &location  );
           switch (   location  ) {
           case OBJECTS_LOCAL:
           _User_extensions_Remove_set(   &the_extension->Extension  );
           _Objects_Close(   &_Extension_Information,   &the_extension->Object  );
           _Extension_Free(   the_extension  );
           _Thread_Enable_dispatch(   );
           return RTEMS_SUCCESSFUL;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* should never return this */
          #endif
           case OBJECTS_ERROR:
           break;
           }
          
           return RTEMS_INVALID_ID;
          }

sapi/src/extensionident.c

       1  /**
           * @file
           *
           * @ingroup ClassicUserExtensions
           *
           * @brief User Extensions Implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: extensionident.c,  v 1.9 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/rtems/support.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/extension.h>
          
      30  rtems_status_code rtems_extension_ident(  
           rtems_name name,  
           rtems_id *id
           )
          {
           Objects_Name_or_id_lookup_errors status;
          
           status = _Objects_Name_to_id_u32(  
           &_Extension_Information,  
           name,  
           OBJECTS_SEARCH_LOCAL_NODE,  
           id
            );
          
           return _Status_Object_name_errors_to_status[ status ];
          }

sapi/src/fatal.c

       1  /*
           * Fatal Error Manager
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: fatal.c,  v 1.15 2009/11/09 15:03:18 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/fatal.h>
          #include <rtems/score/interr.h>
          
          /*
           * rtems_fatal_error_occurred
           *
           * This directive will invoke the internal fatal error handler.
           *
           * Input parameters:
           * the_error - fatal error status code
           *
           * Output parameters: NONE
           */
          
      33  void rtems_fatal_error_occurred(  
           uint32_t the_error
           )
          {
           _Internal_error_Occurred(   INTERNAL_ERROR_RTEMS_API,   FALSE,   the_error  );
          
          /* will not return from this routine */
          }

sapi/src/getversionstring.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: getversionstring.c,  v 1.1 2008/07/15 22:56:45 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          
      18  const char *rtems_get_version_string(  void )
          {
           return _RTEMS_version;
          }

sapi/src/io.c

       1  /*
           * Input/Output Manager - Initialize Device Driver Subsystem
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: io.c,  v 1.31 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/io.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          
          #include <string.h>
          
          /*
           * _IO_Manager_initialization
           *
           * The IO manager has been extended to support runtime driver
           * registration. The driver table is now allocated in the
           * workspace.
           *
           */
          
      36  void _IO_Manager_initialization(  void )
          {
           uint32_t index;
           rtems_driver_address_table *driver_table;
           uint32_t drivers_in_table;
           uint32_t number_of_drivers;
          
           driver_table = Configuration.Device_driver_table;
           drivers_in_table = Configuration.number_of_device_drivers;
           number_of_drivers = Configuration.maximum_drivers;
          
           /*
           * If the user claims there are less drivers than are actually in
           * the table,   then let's just go with the table's count.
           */
           if (   number_of_drivers <= drivers_in_table  )
           number_of_drivers = drivers_in_table;
          
           /*
           * If the maximum number of driver is the same as the number in the
           * table,   then we do not have to copy the driver table. They can't
           * register any dynamically.
           */
           if (   number_of_drivers == drivers_in_table  ) {
           _IO_Driver_address_table = driver_table;
           _IO_Number_of_drivers = number_of_drivers;
           return;
           }
          
           /*
           * The application requested extra slots in the driver table,   so we
           * have to allocate a new driver table and copy theirs to it.
           */
          
           _IO_Driver_address_table = (  rtems_driver_address_table * )
           _Workspace_Allocate_or_fatal_error(  
           sizeof(   rtems_driver_address_table  ) * (   number_of_drivers  )
            );
           _IO_Number_of_drivers = number_of_drivers;
          
           memset(  
           _IO_Driver_address_table,   0,  
           sizeof(   rtems_driver_address_table  ) * (   number_of_drivers  )
            );
          
           for (   index = 0 ; index < drivers_in_table ; index++  )
           _IO_Driver_address_table[index] = driver_table[index];
           number_of_drivers = drivers_in_table;
          }
          
          /*
           * _IO_Initialize_all_drivers
           *
           * This routine initializes all device drivers
           *
           * Input Paramters: NONE
           *
           * Output Parameters: NONE
           */
          
      96  void _IO_Initialize_all_drivers(   void  )
          {
           rtems_device_major_number major;
          
           for (   major=0 ; major < _IO_Number_of_drivers ; major ++  )
           (  void ) rtems_io_initialize(   major,   0,   NULL  );
          }

sapi/src/ioclose.c

       1  /*
           * Input/Output Manager -- Close Device
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ioclose.c,  v 1.1 2007/05/29 19:56:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/io.h>
          
          /*
           * rtems_io_close
           *
           * This routine is the close directive of the IO manager.
           *
           * Input Paramters:
           * major - device driver number
           * minor - device number
           * argument - pointer to argument(  s )
           *
           * Output Parameters:
           * returns - return code
           */
          
      35  rtems_status_code rtems_io_close(  
           rtems_device_major_number major,  
           rtems_device_minor_number minor,  
           void *argument
           )
          {
           rtems_device_driver_entry callout;
          
           if (   major >= _IO_Number_of_drivers  )
           return RTEMS_INVALID_NUMBER;
          
           callout = _IO_Driver_address_table[major].close_entry;
           return callout ? callout(  major,   minor,   argument ) : RTEMS_SUCCESSFUL;
          }

sapi/src/iocontrol.c

       1  /*
           * Input/Output Manager - Device Control
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: iocontrol.c,  v 1.1 2007/05/29 19:56:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/io.h>
          
          /*
           * rtems_io_control
           *
           * This routine is the control directive of the IO manager.
           *
           * Input Paramters:
           * major - device driver number
           * minor - device number
           * argument - pointer to argument(  s )
           *
           * Output Parameters:
           * returns - return code
           */
          
      35  rtems_status_code rtems_io_control(  
           rtems_device_major_number major,  
           rtems_device_minor_number minor,  
           void *argument
           )
          {
           rtems_device_driver_entry callout;
          
           if (   major >= _IO_Number_of_drivers  )
           return RTEMS_INVALID_NUMBER;
          
           callout = _IO_Driver_address_table[major].control_entry;
           return callout ? callout(  major,   minor,   argument ) : RTEMS_SUCCESSFUL;
          }

sapi/src/iodata.c

       1  /*
           * RTEMS Task Manager -- Instantiate Data
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: iodata.c,  v 1.1 2007/05/29 19:56:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /* instantiate RTEMS IO manager data */
          #define SAPI_IO_EXTERN
          
          #include <rtems/system.h>
          #include <rtems/io.h>

sapi/src/ioinitialize.c

       1  /*
           * Input/Output Manager - Initialize Device
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ioinitialize.c,  v 1.1 2007/05/29 19:56:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/io.h>
          
          /*
           * rtems_io_initialize
           *
           * This routine is the initialization directive of the IO manager.
           *
           * Input Paramters:
           * major - device driver number
           * minor - device number
           * argument - pointer to argument(  s )
           *
           * Output Parameters:
           * returns - return code
           */
          
      35  rtems_status_code rtems_io_initialize(  
           rtems_device_major_number major,  
           rtems_device_minor_number minor,  
           void *argument
           )
          {
           rtems_device_driver_entry callout;
          
           if (   major >= _IO_Number_of_drivers  )
           return RTEMS_INVALID_NUMBER;
          
           callout = _IO_Driver_address_table[major].initialization_entry;
           return callout ? callout(  major,   minor,   argument ) : RTEMS_SUCCESSFUL;
          }

sapi/src/ioopen.c

       1  /*
           * Input/Output Manager - Open Device
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ioopen.c,  v 1.1 2007/05/29 19:56:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/io.h>
          
          /*
           * rtems_io_open
           *
           * This routine is the open directive of the IO manager.
           *
           * Input Paramters:
           * major - device driver number
           * minor - device number
           * argument - pointer to argument(  s )
           *
           * Output Parameters:
           * returns - return code
           */
          
      35  rtems_status_code rtems_io_open(  
           rtems_device_major_number major,  
           rtems_device_minor_number minor,  
           void *argument
           )
          {
           rtems_device_driver_entry callout;
          
           if (   major >= _IO_Number_of_drivers  )
           return RTEMS_INVALID_NUMBER;
          
           callout = _IO_Driver_address_table[major].open_entry;
           return callout ? callout(  major,   minor,   argument ) : RTEMS_SUCCESSFUL;
          }

sapi/src/ioread.c

       1  /*
           * Input/Output Manager - Device Read
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ioread.c,  v 1.1 2007/05/29 19:56:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/io.h>
          
          /*
           * rtems_io_read
           *
           * This routine is the read directive of the IO manager.
           *
           * Input Paramters:
           * major - device driver number
           * minor - device number
           * argument - pointer to argument(  s )
           *
           * Output Parameters:
           * returns - return code
           */
          
      35  rtems_status_code rtems_io_read(  
           rtems_device_major_number major,  
           rtems_device_minor_number minor,  
           void *argument
           )
          {
           rtems_device_driver_entry callout;
          
           if (   major >= _IO_Number_of_drivers  )
           return RTEMS_INVALID_NUMBER;
          
           callout = _IO_Driver_address_table[major].read_entry;
           return callout ? callout(  major,   minor,   argument ) : RTEMS_SUCCESSFUL;
          }

sapi/src/ioregisterdriver.c

       1  /**
           * @file
           *
           * @ingroup ClassicIO
           *
           * @brief Classic Input/Output Manager implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2009.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * Copyright (  c ) 2009 embedded brains GmbH.
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: ioregisterdriver.c,  v 1.9 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/io.h>
          #include <rtems/rtems/intr.h>
          #include <rtems/score/thread.h>
          
      31  static inline bool rtems_io_is_empty_table(  
           const rtems_driver_address_table *table
           )
          {
           return table->initialization_entry == NULL && table->open_entry == NULL;
          }
          
      38  static rtems_status_code rtems_io_obtain_major_number(  
           rtems_device_major_number *major
           )
          {
           rtems_device_major_number n = _IO_Number_of_drivers;
           rtems_device_major_number m = 0;
          
           /* major is error checked by caller */
          
           for (   m = 0; m < n; ++m  ) {
           rtems_driver_address_table *const table = _IO_Driver_address_table + m;
          
           if (   rtems_io_is_empty_table(   table  )  )
           break;
           }
          
           /* Assigns invalid value in case of failure */
           *major = m;
          
           if (   m != n  )
           return RTEMS_SUCCESSFUL;
          
           return RTEMS_TOO_MANY;
          }
          
      63  rtems_status_code rtems_io_register_driver(  
           rtems_device_major_number major,  
           const rtems_driver_address_table *driver_table,  
           rtems_device_major_number *registered_major
           )
          {
           rtems_device_major_number major_limit = _IO_Number_of_drivers;
          
           if (   rtems_interrupt_is_in_progress(   )  )
           return RTEMS_CALLED_FROM_ISR;
          
           if (   registered_major == NULL  )
           return RTEMS_INVALID_ADDRESS;
          
           /* Set it to an invalid value */
           *registered_major = major_limit;
          
           if (   driver_table == NULL  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   rtems_io_is_empty_table(   driver_table  )  )
           return RTEMS_INVALID_ADDRESS;
          
           if (   major >= major_limit  )
           return RTEMS_INVALID_NUMBER;
          
           _Thread_Disable_dispatch(   );
          
           if (   major == 0  ) {
           rtems_status_code sc = rtems_io_obtain_major_number(   registered_major  );
          
           if (   sc != RTEMS_SUCCESSFUL  ) {
           _Thread_Enable_dispatch(   );
           return sc;
           }
           major = *registered_major;
           } else {
           rtems_driver_address_table *const table = _IO_Driver_address_table + major;
          
           if (   !rtems_io_is_empty_table(   table  )  ) {
           _Thread_Enable_dispatch(   );
           return RTEMS_RESOURCE_IN_USE;
           }
          
           *registered_major = major;
           }
          
           _IO_Driver_address_table [major] = *driver_table;
          
           _Thread_Enable_dispatch(   );
          
           return rtems_io_initialize(   major,   0,   NULL  );
          }

sapi/src/iounregisterdriver.c

       1  /*
           * Input/Output Manager - Dynamically Unregister Device Driver
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: iounregisterdriver.c,  v 1.2 2009/10/09 13:46:39 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/io.h>
          #include <rtems/rtems/intr.h>
          #include <rtems/score/thread.h>
          #include <string.h>
          
          /*
           * rtems_io_unregister_driver
           *
           * Unregister a driver from the device driver table.
           *
           * Input Paramters:
           * major - device major number
           *
           * Output Parameters:
           * RTEMS_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      37  rtems_status_code rtems_io_unregister_driver(  
           rtems_device_major_number major
           )
          {
           if (   rtems_interrupt_is_in_progress(   )  )
           return RTEMS_CALLED_FROM_ISR;
          
           if (   major < _IO_Number_of_drivers  ) {
           _Thread_Disable_dispatch(   );
           memset(  
           &_IO_Driver_address_table[major],  
           0,  
           sizeof(   rtems_driver_address_table  )
            );
           _Thread_Enable_dispatch(   );
          
           return RTEMS_SUCCESSFUL;
           }
          
           return RTEMS_UNSATISFIED;
          }

sapi/src/iowrite.c

       1  /*
           * Input/Output Manager - Device Write
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: iowrite.c,  v 1.1 2007/05/29 19:56:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/io.h>
          
          /*
           * rtems_io_write
           *
           * This routine is the write directive of the IO manager.
           *
           * Input Paramters:
           * major - device driver number
           * minor - device number
           * argument - pointer to argument(  s )
           *
           * Output Parameters:
           * returns - return code
           */
          
      35  rtems_status_code rtems_io_write(  
           rtems_device_major_number major,  
           rtems_device_minor_number minor,  
           void *argument
           )
          {
           rtems_device_driver_entry callout;
          
           if (   major >= _IO_Number_of_drivers  )
           return RTEMS_INVALID_NUMBER;
          
           callout = _IO_Driver_address_table[major].write_entry;
           return callout ? callout(  major,   minor,   argument ) : RTEMS_SUCCESSFUL;
          }

sapi/src/posixapi.c

       1  /*
           * RTEMS API Initialization Support
           *
           * NOTE:
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: posixapi.c,  v 1.30 2010/07/04 14:53:47 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * POSIX_API_INIT is defined so all of the POSIX API
           * data will be included in this object file.
           */
          
          #define POSIX_API_INIT
          
          #include <rtems/system.h> /* include this before checking RTEMS_POSIX_API */
          #ifdef RTEMS_POSIX_API
          
          #include <sys/types.h>
          #include <mqueue.h>
          #include <rtems/config.h>
          #include <rtems/score/object.h>
          #include <rtems/posix/barrier.h>
          #include <rtems/posix/cond.h>
          #include <rtems/posix/config.h>
          #include <rtems/posix/key.h>
          #include <rtems/posix/mqueue.h>
          #include <rtems/posix/mutex.h>
          #include <rtems/posix/posixapi.h>
          #include <rtems/posix/priority.h>
          #include <rtems/posix/psignal.h>
          #include <rtems/posix/pthread.h>
          #include <rtems/posix/rwlock.h>
          #include <rtems/posix/timer.h>
          #include <rtems/posix/semaphore.h>
          #include <rtems/posix/spinlock.h>
          #include <rtems/posix/time.h>
          
          /*PAGE
           *
           * _POSIX_API_Initialize
           *
           * XXX
           */
          
          Objects_Information *_POSIX_Objects[ OBJECTS_POSIX_CLASSES_LAST + 1 ];
          
      59  void _POSIX_API_Initialize(  void )
          {
           /*
           * If there are any type size assumptions in the POSIX API,   this is
           * the appropriate place to place them.
           *
           * Currently,   there are no none type size assumptions.
           */
          
           /*
           * Install our API Object Management Table and initialize the
           * various managers.
           */
           _Objects_Information_table[OBJECTS_POSIX_API] = _POSIX_Objects;
          
           _POSIX_signals_Manager_Initialization(   );
           _POSIX_Threads_Manager_initialization(   );
           _POSIX_Condition_variables_Manager_initialization(   );
           _POSIX_Key_Manager_initialization(   );
           _POSIX_Mutex_Manager_initialization(   );
           _POSIX_Message_queue_Manager_initialization(   );
           _POSIX_Semaphore_Manager_initialization(   );
           _POSIX_Timer_Manager_initialization(   );
           _POSIX_Barrier_Manager_initialization(   );
           _POSIX_RWLock_Manager_initialization(   );
           _POSIX_Spinlock_Manager_initialization(   );
          }
          
          #endif
          /* end of file */

sapi/src/rtemsapi.c

       1  /*
           * POSIX API Initialization Support
           *
           * NOTE:
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: rtemsapi.c,  v 1.18 2008/12/17 20:21:40 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          /*
           * RTEMS_API_INIT is defined so all of the RTEMS API
           * data will be included in this object file.
           */
          
          #define RTEMS_API_INIT
          
          #include <rtems/system.h>
          #include <rtems/rtems/status.h>
          #include <rtems/rtems/rtemsapi.h>
          
          #include <rtems/rtems/intr.h>
          #include <rtems/rtems/barrier.h>
          #include <rtems/rtems/clock.h>
          #include <rtems/rtems/tasks.h>
          #include <rtems/rtems/dpmem.h>
          #include <rtems/rtems/event.h>
          #include <rtems/rtems/message.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/rtems/mp.h>
          #endif
          #include <rtems/rtems/part.h>
          #include <rtems/rtems/ratemon.h>
          #include <rtems/rtems/region.h>
          #include <rtems/rtems/sem.h>
          #include <rtems/rtems/signal.h>
          #include <rtems/rtems/timer.h>
          
          Objects_Information *_RTEMS_Objects[ OBJECTS_RTEMS_CLASSES_LAST + 1 ];
          
          /*PAGE
           *
           * _RTEMS_API_Initialize
           *
           * XXX
           */
          
      57  void _RTEMS_API_Initialize(  void )
          {
           /*
           * Install our API Object Management Table and initialize the
           * various managers.
           */
           _Objects_Information_table[OBJECTS_CLASSIC_API] = _RTEMS_Objects;
          
           #if defined(  RTEMS_MULTIPROCESSING )
           _Multiprocessing_Manager_initialization(   );
           #endif
          
           _RTEMS_tasks_Manager_initialization(   );
           _Timer_Manager_initialization(   );
           _Signal_Manager_initialization(   );
           _Event_Manager_initialization(   );
           _Message_queue_Manager_initialization(   );
           _Semaphore_Manager_initialization(   );
           _Partition_Manager_initialization(   );
           _Region_Manager_initialization(   );
           _Dual_ported_memory_Manager_initialization(   );
           _Rate_monotonic_Manager_initialization(   );
           _Barrier_Manager_initialization(   );
          }
          
          /* end of file */

score/cpu/arm/arm_exc_handler_high.c

       1  /**
           * @file
           *
           * @ingroup ScoreCPU
           *
           * @brief ARM exception support implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 2000 Canon Research Centre France SA.
           * Emmanuel Raguet,   mailto:raguet@crf.canon.fr
           *
           * Copyright (  c ) 2002 Advent Networks,   Inc
           * Jay Monkman <jmonkman@adventnetworks.com>
           *
           * Copyright (  c ) 2007 Ray xu <rayx.cn@gmail.com>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * Moved from file 'cpukit/score/cpu/arm/cpu.c'.
           *
           * $Id: arm_exc_handler_high.c,  v 1.4 2010/04/08 10:13:46 thomas Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems.h>
          #include <rtems/bspIo.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/cpu.h>
          
      39  static void _defaultExcHandler (  CPU_Exception_frame *ctx )
          {
           printk(  "\n\r" );
           printk(  "----------------------------------------------------------\n\r" );
          #if 1
           printk(  "Exception 0x%x caught at PC 0x%x by thread %d\n",  
           ctx->register_ip,   ctx->register_lr - 4,  
           _Thread_Executing->Object.id );
          #endif
           printk(  "----------------------------------------------------------\n\r" );
           printk(  "Processor execution context at time of the fault was :\n\r" );
           printk(  "----------------------------------------------------------\n\r" );
          #if 0
           printk(  " r0 = %8x r1 = %8x r2 = %8x r3 = %8x\n\r",  
           ctx->register_r0,   ctx->register_r1,  
           ctx->register_r2,   ctx->register_r3 );
           printk(  " r4 = %8x r5 = %8x r6 = %8x r7 = %8x\n\r",  
           ctx->register_r4,   ctx->register_r5,  
           ctx->register_r6,   ctx->register_r7 );
           printk(  " r8 = %8x r9 = %8x r10 = %8x\n\r",  
           ctx->register_r8,   ctx->register_r9,   ctx->register_r10 );
           printk(  " fp = %8x ip = %8x sp = %8x pc = %8x\n\r",  
           ctx->register_fp,   ctx->register_ip,  
           ctx->register_sp,   ctx->register_lr - 4 );
           printk(  "----------------------------------------------------------\n\r" );
          #endif
           if (  _ISR_Nest_level > 0 ) {
           /*
           * In this case we shall not delete the task interrupted as
           * it has nothing to do with the fault. We cannot return either
           * because the eip points to the faulty instruction so...
           */
           printk(  "Exception while executing ISR!!!. System locked\n\r" );
           while(  1 );
           }
           else {
           printk(  "*********** FAULTY THREAD WILL BE DELETED **************\n\r" );
           rtems_task_delete(  _Thread_Executing->Object.id );
           }
          }
          
          typedef void (  *cpuExcHandlerType ) (  CPU_Exception_frame* );
          
          cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
          
      84  extern void _Exception_Handler_Undef_Swi(  void );
      85  extern void _Exception_Handler_Abort(  void );
      86  extern void _exc_data_abort(  void );
          
          
          
          /* FIXME: put comments here */
      91  void rtems_exception_init_mngt(  void )
          {
           ISR_Level level;
          
           _CPU_ISR_Disable(  level );
           _CPU_ISR_install_vector(  ARM_EXCEPTION_UNDEF,  
           _Exception_Handler_Undef_Swi,  
           NULL );
          
           _CPU_ISR_install_vector(  ARM_EXCEPTION_SWI,  
           _Exception_Handler_Undef_Swi,  
           NULL );
          
           _CPU_ISR_install_vector(  ARM_EXCEPTION_PREF_ABORT,  
           _Exception_Handler_Abort,  
           NULL );
          
           _CPU_ISR_install_vector(  ARM_EXCEPTION_DATA_ABORT,  
           _exc_data_abort,  
           NULL );
          
           _CPU_ISR_install_vector(  ARM_EXCEPTION_FIQ,  
           _Exception_Handler_Abort,  
           NULL );
          
           _CPU_ISR_install_vector(  ARM_EXCEPTION_IRQ,  
           _Exception_Handler_Abort,  
           NULL );
          
           _CPU_ISR_Enable(  level );
          }

score/cpu/arm/cpu.c

       1  /**
           * @file
           *
           * @ingroup ScoreCPU
           *
           * @brief ARM architecture support implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 2000 Canon Research Centre France SA.
           * Emmanuel Raguet,   mailto:raguet@crf.canon.fr
           *
           * Copyright (  c ) 2002 Advent Networks,   Inc
           * Jay Monkman <jmonkman@adventnetworks.com>
           *
           * Copyright (  c ) 2007 Ray xu <rayx.cn@gmail.com>
           *
           * Copyright (  c ) 2009 embedded brains GmbH
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.31 2010/04/08 10:13:46 thomas Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems.h>
          #include <rtems/bspIo.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/cpu.h>
          
          /*
           * This variable can be used to change the running mode of the execution
           * contexts.
           */
          uint32_t arm_cpu_mode = 0x13;
          
      45  void _CPU_Context_Initialize(  
           Context_Control *the_context,  
           uint32_t *stack_base,  
           uint32_t size,  
           uint32_t new_level,  
           void *entry_point,  
           bool is_fp
           )
          {
           the_context->register_sp = (  uint32_t ) stack_base + size ;
           the_context->register_lr = (  uint32_t ) entry_point;
           the_context->register_cpsr = new_level | arm_cpu_mode;
          }
          
          /* Preprocessor magic for stringification of x */
          #define _CPU_ISR_LEVEL_DO_STRINGOF(   x ) #x
          #define _CPU_ISR_LEVEL_STRINGOF(   x ) _CPU_ISR_LEVEL_DO_STRINGOF(   x )
          
      63  void _CPU_ISR_Set_level(   uint32_t level  )
          {
           uint32_t arm_switch_reg;
          
           asm volatile (  
           ARM_SWITCH_TO_ARM
           "mrs %[arm_switch_reg],   cpsr\n"
           "bic %[arm_switch_reg],   #" _CPU_ISR_LEVEL_STRINGOF(   CPU_MODES_INTERRUPT_MASK  ) "\n"
           "orr %[arm_switch_reg],   %[level]\n"
           "msr cpsr,   %0\n"
           ARM_SWITCH_BACK
           : [arm_switch_reg] "=&r" (  arm_switch_reg )
           : [level] "r" (  level )
            );
          }
          
      79  uint32_t _CPU_ISR_Get_level(   void  )
          {
           ARM_SWITCH_REGISTERS;
           uint32_t level;
          
           asm volatile (  
           ARM_SWITCH_TO_ARM
           "mrs %[level],   cpsr\n"
           "and %[level],   #" _CPU_ISR_LEVEL_STRINGOF(   CPU_MODES_INTERRUPT_MASK  ) "\n"
           ARM_SWITCH_BACK
           : [level] "=&r" (  level ) ARM_SWITCH_ADDITIONAL_OUTPUT
            );
          
           return level;
          }
          
      95  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           /* Redirection table starts at the end of the vector table */
           volatile uint32_t *table = (  volatile uint32_t * ) (  MAX_EXCEPTIONS * 4 );
          
           uint32_t current_handler = table [vector];
          
           /* The current handler is now the old one */
           if (  old_handler != NULL ) {
           *old_handler = (  proc_ptr ) current_handler;
           }
          
           /* Write only if necessary to avoid writes to a maybe read-only memory */
           if (  current_handler != (  uint32_t ) new_handler ) {
           table [vector] = (  uint32_t ) new_handler;
           }
          }
          
     117  void _CPU_Install_interrupt_stack(   void  )
          {
           /* This function is empty since the BSP must set up the interrupt stacks */
          }
          
     122  void _CPU_Initialize(   void  )
          {
           /* Do nothing */
          }

score/cpu/avr/cpu.c

       1  /*
           * AVR CPU Dependent Source
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.16 2010/03/27 15:01:24 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/wkspace.h>
          
          #include <rtems/bspIo.h> /* XXX remove me later */
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
      35  void _CPU_Initialize(  void )
          {
          
           /*
           * If there is not an easy way to initialize the FP context
           * during Context_Initialize,   then it is usually easier to
           * save an "uninitialized" FP context here and copy it to
           * the task's during Context_Initialize.
           */
          
           /* FP context initialization support goes here */
          }
          
          /*PAGE
           *
           * _CPU_ISR_Get_level
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      57  uint32_t _CPU_ISR_Get_level(   void  )
          {
           /*
           * This routine returns the current interrupt level.
           */
           if(  (  SREG & 0x80 ) )return 1;
           else return 0;
          
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      76  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           /*
           * This is where we install the interrupt handler into the "raw" interrupt
           * table used by the CPU to dispatch interrupt handlers.
           */
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * old_handler - former ISR for this vector number
           * new_handler - replacement ISR for this vector number
           *
           * Output parameters: NONE
           *
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     108  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           *old_handler = _ISR_Vector_table[ vector ];
          
           /*
           * If the interrupt vector table is a table of pointer to isr entry
           * points,   then we need to install the appropriate RTEMS interrupt
           * handler for this vector number.
           */
          
           _CPU_ISR_install_raw_handler(   vector,   new_handler,   old_handler  );
          
           /*
           * We put the actual user ISR address in '_ISR_vector_table'. This will
           * be used by the _ISR_Handler so the user gets control.
           */
          
           _ISR_Vector_table[ vector ] = new_handler;
          }
          
          /*PAGE
           *
           * _CPU_Install_interrupt_stack
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     141  void _CPU_Install_interrupt_stack(   void  )
          {
          }
          
          /*PAGE
           *
           * _CPU_Thread_Idle_body
           *
           * NOTES:
           *
           * 1. This is the same as the regular CPU independent algorithm.
           *
           * 2. If you implement this using a "halt",   "idle",   or "shutdown"
           * instruction,   then don't forget to put it in an infinite loop.
           *
           * 3. Be warned. Some processors with onboard DMA have been known
           * to stop the DMA if the CPU were put in IDLE mode. This might
           * also be a problem with other on-chip peripherals. So use this
           * hook with caution.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     166  void *_CPU_Thread_Idle_body(   uintptr_t ignored  )
          {
          
           for(   ; ;  ) asm volatile (  "sleep":: );
           /* insert your "halt" instruction here */ ;
           return (  void * ) 0;
          }

score/cpu/bfin/cpu.c

       1  /* Blackfin CPU Dependent Source
           *
           * COPYRIGHT (  c ) 2006 by Atos Automacao Industrial Ltda.
           * written by Alain Schaefer <alain.schaefer@easc.ch>
           * and Antonio Giovanini <antonio@atos.com.br>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.15 2010/04/17 19:24:16 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/bfin.h>
          #include <rtems/bfin/bfin.h>
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
          
      36  extern void _ISR15_Handler(  void );
      37  extern void _CPU_Emulation_handler(  void );
      38  extern void _CPU_Reset_handler(  void );
      39  extern void _CPU_NMI_handler(  void );
      40  extern void _CPU_Exception_handler(  void );
      41  extern void _CPU_Unhandled_Interrupt_handler(  void );
          
      43  void _CPU_Initialize(  void )
          {
           /*
           * If there is not an easy way to initialize the FP context
           * during Context_Initialize,   then it is usually easier to
           * save an "uninitialized" FP context here and copy it to
           * the task's during Context_Initialize.
           */
          
           /* FP context initialization support goes here */
          
          
          
           proc_ptr ignored;
          
          #if 0
           /* occassionally useful debug stuff */
           int i;
           _CPU_ISR_install_raw_handler(  0,   _CPU_Emulation_handler,   &ignored );
           _CPU_ISR_install_raw_handler(  1,   _CPU_Reset_handler,   &ignored );
           _CPU_ISR_install_raw_handler(  2,   _CPU_NMI_handler,   &ignored );
           _CPU_ISR_install_raw_handler(  3,   _CPU_Exception_handler,   &ignored );
           for (  i = 5; i < 15; i++ )
           _CPU_ISR_install_raw_handler(  i,   _CPU_Unhandled_Interrupt_handler,   &ignored );
          #endif
          
           /* install handler that will be used to call _Thread_Dispatch */
           _CPU_ISR_install_raw_handler(   15,   _ISR15_Handler,   &ignored  );
           /* enable self nesting */
           __asm__ __volatile__ (  "syscfg = %0" : : "d" (  0x00000004 ) );
          }
          
          
          
          
          /*PAGE
           *
           * _CPU_ISR_Get_level
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      87  uint32_t _CPU_ISR_Get_level(   void  )
          {
           /*
           * This routine returns the current interrupt level.
           */
          
           register uint32_t _tmpimask;
          
           /*read from the IMASK registers*/
          
           _tmpimask = *(  (  uint32_t* )IMASK );
          
           return (  _tmpimask & 0xffe0 ) ? 0 : 1;
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     111  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           proc_ptr *interrupt_table = NULL;
           /*
           * This is where we install the interrupt handler into the "raw" interrupt
           * table used by the CPU to dispatch interrupt handlers.
           */
          
           /* base of vector table on blackfin architecture */
           interrupt_table = (  void* )0xFFE02000;
          
           *old_handler = interrupt_table[ vector ];
           interrupt_table[ vector ] = new_handler;
          
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * old_handler - former ISR for this vector number
           * new_handler - replacement ISR for this vector number
           *
           * Output parameters: NONE
           *
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     151  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           proc_ptr ignored;
          
           *old_handler = _ISR_Vector_table[ vector ];
          
           /*
           * We put the actual user ISR address in '_ISR_vector_table'. This will
           * be used by the _ISR_Handler so the user gets control.
           */
          
           _ISR_Vector_table[ vector ] = new_handler;
          
           _CPU_ISR_install_raw_handler(   vector,   _ISR_Handler,   &ignored  );
          }
          
          #if (  CPU_PROVIDES_IDLE_THREAD_BODY == TRUE )
     172  void *_CPU_Thread_Idle_body(  uint32_t ignored )
          {
           while (  1 ) {
           __asm__ __volatile__(  "ssync; idle; ssync" );
           }
          }
          #endif
          
          /*
           * Copied from the arm port.
           */
     183  void _CPU_Context_Initialize(  
           Context_Control *the_context,  
           uint32_t *stack_base,  
           uint32_t size,  
           uint32_t new_level,  
           void *entry_point,  
           bool is_fp
           )
          {
           uint32_t stack_high; /* highest "stack aligned" address */
           stack_high = (  (  uint32_t )(  stack_base ) + size );
          
           /* blackfin abi requires caller to reserve 12 bytes on stack */
           the_context->register_sp = stack_high - 12;
           the_context->register_rets = (  uint32_t ) entry_point;
           the_context->imask = new_level ? 0 : 0xffff;
          }
          
          
          
          /*PAGE
           *
           * _CPU_Install_interrupt_stack
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     212  void _CPU_Install_interrupt_stack(   void  )
          {
          }

score/cpu/h8300/cpu.c

       1  /*
           * Hitachi H8300 CPU Dependent Source
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.11 2010/03/27 15:01:35 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/wkspace.h>
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           */
          
          
      30  void _CPU_Initialize(  void )
          {
           /*
           * If there is not an easy way to initialize the FP context
           * during Context_Initialize,   then it is usually easier to
           * save an "uninitialized" FP context here and copy it to
           * the task's during Context_Initialize.
           */
          
           /* FP context initialization support goes here */
          }
          
          /*PAGE
           *
           * _CPU_ISR_Get_level
           *
           * This routine returns the current interrupt level.
           */
          
      49  uint32_t _CPU_ISR_Get_level(   void  )
          {
           unsigned int _ccr;
          
          #if defined(  __H8300__ )
          #warning "How do we get ccr on base CPU models"
          #else
           asm volatile (   "stc ccr,   %0" : "=m" (  _ccr ) :  );
          #endif
          
           if (   _ccr & 0x80  )
           return 1;
           return 0;
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           */
          
      69  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           /*
           * This is where we install the interrupt handler into the "raw" interrupt
           * table used by the CPU to dispatch interrupt handlers.
           * Use Debug level IRQ Handlers
           */
           H8BD_Install_IRQ(  vector,  new_handler,  old_handler );
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * old_handler - former ISR for this vector number
           * new_handler - replacement ISR for this vector number
           *
           * Output parameters: NONE
           *
           */
          
      99  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           *old_handler = _ISR_Vector_table[ vector ];
          
           /*
           * If the interrupt vector table is a table of pointer to isr entry
           * points,   then we need to install the appropriate RTEMS interrupt
           * handler for this vector number.
           */
          
           _CPU_ISR_install_raw_handler(   vector,   new_handler,   old_handler  );
          
           /*
           * We put the actual user ISR address in '_ISR_vector_table'. This will
           * be used by the _ISR_Handler so the user gets control.
           */
          
           _ISR_Vector_table[ vector ] = new_handler;
          }
          
          /*PAGE
           *
           * _CPU_Install_interrupt_stack
           */
          
     128  void _CPU_Install_interrupt_stack(   void  )
          {
          }
          
          /*PAGE
           *
           * _CPU_Thread_Idle_body
           *
           * NOTES:
           *
           * 1. This is the same as the regular CPU independent algorithm.
           *
           * 2. If you implement this using a "halt",   "idle",   or "shutdown"
           * instruction,   then don't forget to put it in an infinite loop.
           *
           * 3. Be warned. Some processors with onboard DMA have been known
           * to stop the DMA if the CPU were put in IDLE mode. This might
           * also be a problem with other on-chip peripherals. So use this
           * hook with caution.
           */
          
          #if 0
     150  void *_CPU_Thread_Idle_body(   uintptr_t ignored  )
          {
          
           for(   ; ;  )
           IDLE_Monitor(   );
           /*asm(  " sleep \n" ); */
           /* insert your "halt" instruction here */ ;
          }
          #endif

score/cpu/i386/cpu.c

       1  /*
           * Intel i386 Dependent Source
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.46 2010/03/27 15:01:47 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems.h>
          #include <rtems/system.h>
          #include <rtems/score/types.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/idtr.h>
          
          #include <rtems/bspIo.h>
          #include <rtems/score/thread.h>
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           */
          
      35  void _CPU_Initialize(  void )
          {
          #if CPU_HARDWARE_FP
           register uint16_t fp_status asm (  "ax" );
           register Context_Control_fp *fp_context;
          #endif
          
           /*
           * The following code saves a NULL i387 context which is given
           * to each task at start and restart time. The following code
           * is based upon that provided in the i386 Programmer's
           * Manual and should work on any coprocessor greater than
           * the i80287.
           *
           * NOTE: The NO WAIT form of the coprocessor instructions
           * MUST be used in case there is not a coprocessor
           * to wait for.
           */
          
          #if CPU_HARDWARE_FP
           fp_status = 0xa5a5;
           asm volatile(   "fninit"  );
           asm volatile(   "fnstsw %0" : "=a" (  fp_status ) : "0" (  fp_status )  );
          
           if (   fp_status == 0  ) {
          
           fp_context = &_CPU_Null_fp_context;
          
          #ifdef __SSE__
           asm volatile(   "fstcw %0":"=m"(  fp_context->fpucw )  );
          #else
           asm volatile(   "fsave (  %0 )" : "=r" (  fp_context )
           : "0" (  fp_context )
            );
          #endif
           }
          #endif
          
          #ifdef __SSE__
          
           asm volatile(  "stmxcsr %0":"=m"(  fp_context->mxcsr ) );
          
           /* The BSP must enable the SSE extensions (  early ).
           * If any SSE instruction was already attempted
           * then that crashed the system.
           * As a courtesy,   we double-check here but it
           * may be too late (  which is also why we don't
           * enable SSE here ).
           */
           {
           uint32_t cr4;
           __asm__ __volatile__(  "mov %%cr4,   %0":"=r"(  cr4 ) );
           if (   0x600 != (  cr4 & 0x600 )  ) {
           printk(  "PANIC: RTEMS was compiled for SSE but BSP did not enable it (  CR4: 0x%08x )\n",   cr4 );
           while (   1  ) {
           __asm__ __volatile__(  "hlt" );
           }
           }
           }
          #endif
          }
          
          /*PAGE
           *
           * _CPU_ISR_Get_level
           */
          
     102  uint32_t _CPU_ISR_Get_level(   void  )
          {
           uint32_t level;
          
           i386_get_interrupt_level(   level  );
          
           return level;
          }
          
     111  void *_CPU_Thread_Idle_body(   uintptr_t ignored  )
          {
           while(  1 ){
           asm volatile (  "hlt" );
           }
           return NULL;
          }
          
          struct Frame_ {
           struct Frame_ *up;
           uintptr_t pc;
          };
          
     124  void _defaultExcHandler (  CPU_Exception_frame *ctx )
          {
           unsigned int faultAddr = 0;
           printk(  "----------------------------------------------------------\n" );
           printk(  "Exception %d caught at PC %x by thread %d\n",  
           ctx->idtIndex,  
           ctx->eip,  
           _Thread_Executing->Object.id );
           printk(  "----------------------------------------------------------\n" );
           printk(  "Processor execution context at time of the fault was :\n" );
           printk(  "----------------------------------------------------------\n" );
           printk(  " EAX = %x EBX = %x ECX = %x EDX = %x\n",  
           ctx->eax,   ctx->ebx,   ctx->ecx,   ctx->edx );
           printk(  " ESI = %x EDI = %x EBP = %x ESP = %x\n",  
           ctx->esi,   ctx->edi,   ctx->ebp,   ctx->esp0 );
           printk(  "----------------------------------------------------------\n" );
           printk(  "Error code pushed by processor itself (  if not 0 ) = %x\n",  
           ctx->faultCode );
           printk(  "----------------------------------------------------------\n" );
           if (  ctx->idtIndex == I386_EXCEPTION_PAGE_FAULT ){
           faultAddr = i386_get_cr2(   );
           printk(  "Page fault linear address (  CR2 ) = %x\n",   faultAddr );
           printk(  "----------------------------------------------------------\n\n" );
           }
           if (  _ISR_Nest_level > 0 ) {
           /*
           * In this case we shall not delete the task interrupted as
           * it has nothing to do with the fault. We cannot return either
           * because the eip points to the faulty instruction so...
           */
           printk(  "Exception while executing ISR!!!. System locked\n" );
           _CPU_Fatal_halt(  faultAddr );
           }
           else {
           struct Frame_ *fp = (  struct Frame_* )ctx->ebp;
           int i;
          
           printk(  "Call Stack Trace of EIP:\n" );
           if (   fp  ) {
           for (   i=1; fp->up; fp=fp->up,   i++  ) {
           printk(  "0x%08x ",  fp->pc );
           if (   ! (  i&3 )  )
           printk(  "\n" );
           }
           }
           printk(  "\n" );
           /*
           * OK I could probably use a simplified version but at least this
           * should work.
           */
           printk(  " ************ FAULTY THREAD WILL BE SUSPENDED **************\n" );
           rtems_task_suspend(  _Thread_Executing->Object.id );
           }
          }
          
          cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
          
     181  extern void rtems_exception_prologue_0(  void );
     182  extern void rtems_exception_prologue_1(  void );
     183  extern void rtems_exception_prologue_2(  void );
     184  extern void rtems_exception_prologue_3(  void );
     185  extern void rtems_exception_prologue_4(  void );
     186  extern void rtems_exception_prologue_5(  void );
     187  extern void rtems_exception_prologue_6(  void );
     188  extern void rtems_exception_prologue_7(  void );
     189  extern void rtems_exception_prologue_8(  void );
     190  extern void rtems_exception_prologue_9(  void );
     191  extern void rtems_exception_prologue_10(  void );
     192  extern void rtems_exception_prologue_11(  void );
     193  extern void rtems_exception_prologue_12(  void );
     194  extern void rtems_exception_prologue_13(  void );
     195  extern void rtems_exception_prologue_14(  void );
     196  extern void rtems_exception_prologue_16(  void );
     197  extern void rtems_exception_prologue_17(  void );
     198  extern void rtems_exception_prologue_18(  void );
          #ifdef __SSE__
     200  extern void rtems_exception_prologue_19(  void );
          #endif
          
          static rtems_raw_irq_hdl tbl[] = {
           rtems_exception_prologue_0,  
           rtems_exception_prologue_1,  
           rtems_exception_prologue_2,  
           rtems_exception_prologue_3,  
           rtems_exception_prologue_4,  
           rtems_exception_prologue_5,  
           rtems_exception_prologue_6,  
           rtems_exception_prologue_7,  
           rtems_exception_prologue_8,  
           rtems_exception_prologue_9,  
           rtems_exception_prologue_10,  
           rtems_exception_prologue_11,  
           rtems_exception_prologue_12,  
           rtems_exception_prologue_13,  
           rtems_exception_prologue_14,  
           0,  
           rtems_exception_prologue_16,  
           rtems_exception_prologue_17,  
           rtems_exception_prologue_18,  
          #ifdef __SSE__
           rtems_exception_prologue_19,  
          #endif
          };
          
     228  void rtems_exception_init_mngt(  void )
          {
           size_t i,  j;
           interrupt_gate_descriptor *currentIdtEntry;
           unsigned limit;
           unsigned level;
          
           i = sizeof(  tbl ) / sizeof (  rtems_raw_irq_hdl );
          
           i386_get_info_from_IDTR (  &currentIdtEntry,   &limit );
          
           _CPU_ISR_Disable(  level );
           for (  j = 0; j < i; j++ ) {
           create_interrupt_gate_descriptor (  &currentIdtEntry[j],   tbl[j] );
           }
           _CPU_ISR_Enable(  level );
          }

score/cpu/i386/sse_test.c

          /* $Id: sse_test.c,  v 1.3 2010/03/27 15:01:47 joel Exp $ */
          
          /*
           * Authorship
           * ----------
           * This software was created by
           * Till Straumann <strauman@slac.stanford.edu>,   2009,  
           * Stanford Linear Accelerator Center,   Stanford University.
           *
           * Acknowledgement of sponsorship
           * ------------------------------
           * This software was produced by
           * the Stanford Linear Accelerator Center,   Stanford University,  
           * under Contract DE-AC03-76SFO0515 with the Department of Energy.
           *
           * Government disclaimer of liability
           * ----------------------------------
           * Neither the United States nor the United States Department of Energy,  
           * nor any of their employees,   makes any warranty,   express or implied,   or
           * assumes any legal liability or responsibility for the accuracy,  
           * completeness,   or usefulness of any data,   apparatus,   product,   or process
           * disclosed,   or represents that its use would not infringe privately owned
           * rights.
           *
           * Stanford disclaimer of liability
           * --------------------------------
           * Stanford University makes no representations or warranties,   express or
           * implied,   nor assumes any liability for the use of this software.
           *
           * Stanford disclaimer of copyright
           * --------------------------------
           * Stanford University,   owner of the copyright,   hereby disclaims its
           * copyright and all other rights in this software. Hence,   anyone may
           * freely use it for any purpose without restriction.
           *
           * Maintenance of notices
           * ----------------------
           * In the interest of clarity regarding the origin and status of this
           * SLAC software,   this and all the preceding Stanford University notices
           * are to remain affixed to any copy or derivative of this software made
           * or distributed by the recipient and are to be affixed to any copy of
           * software made or distributed by the recipient that contains a copy or
           * derivative of this software.
           *
           * ------------------ SLAC Software Notices,   Set 4 OTT.002a,   2004 FEB 03
           */
          
          
          /* Code for testing FPU/SSE context save/restore across exceptions
           * (  including interrupts ).
           *
           * There are two tasks and an IRQ/EXC handler involved. One task (  LP )
           * is of lower priority than the other (  HP ) task.
           *
           * 1 ) LP task sets up a context area in memory (  known contents; every
           * register is loaded with different values )
           *
           * 2 ) LP task
           * 2a saves original FP/SSE context
           * 2b loads context from 1 ) into FPU/SSE
           * 2c raises an exception or interrupt
           *
           * * (  2d save FPU/SSE context after irq/exception returns to
           * separate area for verification
           * 2e reload original FP/SSE context. )
           *
           * * All these five steps are coded in assembly to prevent
           * gcc from manipulating the FP/SSE state. The last two steps,  
           * however,   are effectively executed during 6 when control is
           * returned to the LP task.
           *
           * 3 ) IRQ/EXC handler OS wrapper saves context,   initializes FPU and
           * MXCSR.
           *
           * 4 ) user (  our ) irq/exc handler clears exception condition,   clobbers
           * FPU and XMM regs and finally releases a semaphore on which HP
           * task is waiting.
           *
           * 5 ) context switch to HP task. HP task clobbers FPU and XMM regs.
           * Then it tries to re-acquire the synchronization semaphore and
           * blocks.
           *
           * 6 ) task switch back to (  interrupted ) LP task. Original context is
           * restored and verified against the context that was setup in 1 ).
           *
           *
           * Three methods for interrupting the LP task are tested
           *
           * a ) FP exception (  by setting an exception status in the context from 1 )
           * b ) SSE exception (  by computing the square root of a vector of negative
           * numbers.
           * c ) IRQ (  software IRQ via 'INT xx' instruction )
           *
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #ifdef __rtems__
          #include <rtems.h>
          #include <rtems/score/cpu.h>
          #include <rtems/irq.h>
          #include <rtems/error.h>
          #endif
          
          #include <inttypes.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <math.h>
          
          /* This is currently hardcoded (  int xx opcode requires immediate operand ) */
          #define SSE_TEST_IRQ 10
          
     116  typedef uint8_t __v8 __attribute__(  (  vector_size(  16 ) ) );
          typedef uint32_t __v32 __attribute__(  (  vector_size(  16 ) ) );
          typedef float __vf __attribute__(  (  vector_size(  16 ) ) );
          
          #ifndef __rtems__
          /* Clone of what is defined in rtems/score/cpu.h (  for testing under linux ) */
          typedef struct Context_Control_sse {
           uint16_t fcw;
           uint16_t fsw;
           uint8_t ftw;
           uint8_t res_1;
           uint16_t fop;
           uint32_t fpu_ip;
           uint16_t cs;
           uint16_t res_2;
           uint32_t fpu_dp;
           uint16_t ds;
           uint16_t res_3;
           uint32_t mxcsr;
           uint32_t mxcsr_mask;
           struct {
           uint8_t fpreg[10];
           uint8_t res_4[ 6];
           } fp_mmregs[8];
           uint8_t xmmregs[8][16];
           uint8_t res_5[224];
          } Context_Control_sse
          __attribute__(  (  aligned(  16 ) ) )
          ;
          #endif
          
          #define MXCSR_FZ (  1<<15 ) /* Flush to zero */
          #define MXCSR_RC(  x ) (  (  (  x )&3 )<<13 ) /* Rounding ctrl */
          #define MXCSR_PM (  1<<12 ) /* Precision msk */
          #define MXCSR_UM (  1<<11 ) /* Underflow msk */
          #define MXCSR_OM (  1<<10 ) /* Overflow msk */
          #define MXCSR_ZM (  1<< 9 ) /* Divbyzero msk */
          #define MXCSR_DM (  1<< 8 ) /* Denormal msk */
          #define MXCSR_IM (  1<< 7 ) /* Invalidop msk */
          #define MXCSR_DAZ (  1<< 6 ) /* Denorml are 0 */
          #define MXCSR_PE (  1<< 5 ) /* Precision flg */
          #define MXCSR_UE (  1<< 4 ) /* Underflow flg */
          #define MXCSR_OE (  1<< 3 ) /* Overflow flg */
          #define MXCSR_ZE (  1<< 2 ) /* Divbyzero flg */
          #define MXCSR_DE (  1<< 1 ) /* Denormal flg */
          #define MXCSR_IE (  1<< 0 ) /* Invalidop flg */
          
          #define MXCSR_ALLM (  MXCSR_PM | MXCSR_UM | MXCSR_OM | MXCSR_ZM | MXCSR_DM | MXCSR_IM )
          #define MXCSR_ALLE (  MXCSR_PE | MXCSR_UE | MXCSR_OE | MXCSR_ZE | MXCSR_DE | MXCSR_IE )
          
          #define FPSR_B (  1<<15 ) /* FPU busy */
          #define FPSR_C3 (  1<<14 ) /* Cond code C3 */
          #define FPSR_TOP(  x ) (  (  (  x )&7 )<<11 ) /* TOP */
          #define FPSR_C2 (  1<<10 ) /* Cond code C2 */
          #define FPSR_C1 (  1<< 9 ) /* Cond code C1 */
          #define FPSR_C0 (  1<< 8 ) /* Cond code C0 */
          #define FPSR_ES (  1<< 7 ) /* Error summary */
          #define FPSR_SF (  1<< 6 ) /* Stack fault */
          #define FPSR_PE (  1<< 5 ) /* Precision flg */
          #define FPSR_UE (  1<< 4 ) /* Underflow flg */
          #define FPSR_OE (  1<< 3 ) /* Overflow flg */
          #define FPSR_ZE (  1<< 2 ) /* Divbyzero flg */
          #define FPSR_DE (  1<< 1 ) /* Denormal flg */
          #define FPSR_IE (  1<< 0 ) /* Invalidop flg */
          
          #define FPCW_X (  1<<12 ) /* Infinity ctrl */
          #define FPCW_RC(  x ) (  (  (  x )&3 )<<10 ) /* Rounding ctrl */
          #define FPCW_PC(  x ) (  (  (  x )&3 )<< 8 ) /* Precision ctl */
          #define FPCW_PM (  1<< 5 ) /* Precision msk */
          #define FPCW_UM (  1<< 4 ) /* Underflow msk */
          #define FPCW_OM (  1<< 3 ) /* Overflow msk */
          #define FPCW_ZM (  1<< 2 ) /* Divbyzero msk */
          #define FPCW_DM (  1<< 1 ) /* Denormal msk */
          #define FPCW_IM (  1<< 0 ) /* Invalidop msk */
          
          #define FPCW_ALLM (  FPCW_PM | FPCW_UM | FPCW_OM | FPCW_ZM | FPCW_DM | FPCW_IM )
          #define FPSR_ALLE (  FPSR_ES | FPSR_SF | FPSR_PE | FPSR_UE | FPSR_OE | FPSR_ZE | FPSR_DE | FPSR_IE )
          
          /* Store 'double' into 80-bit register image */
          void
          fp_st1(  uint8_t (  *p_dst )[10],   double v )
          {
           asm volatile(  "fstpt %0":"=m"(  *p_dst ):"t"(  v ):"st" );
          }
          
          /* Store 'double' into 80-bit register image #i in context */
          void
          fp_st(  Context_Control_sse *p_ctxt,   int i,   double v )
          {
           fp_st1(  &p_ctxt->fp_mmregs[i].fpreg,  v );
          }
          
          /* Load 'double' from 80-bit register image */
          double
          fp_ld1(  uint8_t (  *p_src )[10] )
          {
          double v;
          
           asm volatile(  "fldt %1":"=t"(  v ):"m"(  (  *p_src )[0] ),  "m"(  *p_src ) );
           return v;
          }
          
          /* Load 'double' from 80-bit register image #i in context */
          double
          fp_ld(  Context_Control_sse *p_ctxt,   int i )
          {
           return fp_ld1(  &p_ctxt->fp_mmregs[i].fpreg );
          }
          
          #define FPUCLOBBER \
           "st",  "st(  1 )",  "st(  2 )",  "st(  3 )",   \
           "st(  4 )",  "st(  5 )",  "st(  6 )",  "st(  7 )",  \
           "fpsr",  "fpcr"
          
          /* There seems to be no way to say that mxcsr was clobbered */
          
          #define SSECLOBBER \
           "xmm0",  "xmm1",  "xmm2",  "xmm3",   \
           "xmm4",  "xmm5",  "xmm6",  "xmm7"
          
          static void
          sse_clobber(  uint32_t x )
          {
          __v32 v = { x,   x,   x,   x };
           asm volatile (  
           " movdqa %0,   %%xmm0 \n"
           " movdqa %%xmm0,   %%xmm1 \n"
           " movdqa %%xmm0,   %%xmm2 \n"
           " movdqa %%xmm0,   %%xmm3 \n"
           " movdqa %%xmm0,   %%xmm4 \n"
           " movdqa %%xmm0,   %%xmm5 \n"
           " movdqa %%xmm0,   %%xmm6 \n"
           " movdqa %%xmm0,   %%xmm7 \n"
           :
           :"m"(  v )
           :SSECLOBBER
            );
          }
          
          void
          all_clobber(  uint32_t v1,   uint32_t v2 );
          
          asm(  
          "all_clobber: \n"
          " finit \n"
          " movq 0(  %esp ),   %xmm0 \n"
          " punpcklqdq %xmm0,   %xmm0 \n"
          " movdqa %xmm0,   %xmm1 \n"
          " movdqa %xmm0,   %xmm2 \n"
          " movdqa %xmm0,   %xmm3 \n"
          " movdqa %xmm0,   %xmm4 \n"
          " movdqa %xmm0,   %xmm5 \n"
          " movdqa %xmm0,   %xmm6 \n"
          " movdqa %xmm0,   %xmm7 \n"
          " ret \n"
           );
          
          /* Clear FPU and save FPU/SSE registers to context area */
          
          void
          init_ctxt(  Context_Control_sse *p_ctxt );
          
          asm(  
          "init_ctxt: \n"
          " finit \n"
          " mov 4(  %esp ),   %eax\n"
          " fxsave (  %eax ) \n"
          " fwait \n"
          " ret \n"
           );
          
          /* Save FPU/SSE registers to context area */
          
          static void
          stor_ctxt(  Context_Control_sse *p_ctxt )
          {
           memset(  p_ctxt,   0,   sizeof(  *p_ctxt ) );
           asm volatile(  
          /* " finit \n" */
           " fxsave %0 \n"
           " fwait \n"
           : "=m"(  *p_ctxt )
           :
           : FPUCLOBBER
            );
          }
          
          #define H08 "0x%02"PRIx8
          #define H16 "0x%04"PRIx16
          #define H32 "0x%08"PRIx32
          
          #define F16 "mismatch (  "H16" != "H16" )\n"
          
          #define FLDCMP(  fld,   fmt ) \
           if (   a->fld != b->fld  ) { \
           rval = 1; \
           if (   !quiet  ) \
           fprintf(  stderr,  #fld" mismatch (  "fmt" != "fmt" )\n",  a->fld,   b->fld ); \
           }
          
          #define FLTCMP(  i ) \
           do { \
           if (   (   (  a->ftw ^ b->ftw ) & (  1<<i ) ) \
           || (   (  a->ftw & b->ftw & (  1<<i ) ) && \
           memcmp(  a->fp_mmregs[i].fpreg,   \
           b->fp_mmregs[i].fpreg,   \
           sizeof(  a->fp_mmregs[i].fpreg ) ) \
            ) \
            ) { \
           rval = 1; \
           if (   !quiet  ) { \
           double fa = fp_ld(  a,   i ); \
           double fb = fp_ld(  b,   i ); \
           if (   (  (  a->ftw ^ b->ftw ) & (  1<<i ) )  ) \
           fprintf(  stderr,  "fpreg[%u] TAG mismatch (  %u != %u )\n",  i,  (  a->ftw & (  1<<i ) ) ? 1 : 0,  (  b->ftw & (  1<<i ) ) ? 1 : 0 ); \
           else \
           fprintf(  stderr,  "fpreg[%u] mismatch (  %g != %g )\n",  i,  fa,  fb ); \
           } \
           } \
           } while (  0 )
          
          #define XMMCMP(  i ) \
           do { \
           if (   memcmp(  &a->xmmregs[i],   \
           &b->xmmregs[i],   \
           sizeof(  a->xmmregs[i] ) ) \
            ) { \
           rval = 1; \
           if (   !quiet  ) { \
           int _jj; \
           fprintf(  stderr,  "xmmreg[%u] mismatch:\n",   i ); \
           fprintf(  stderr,  " " ); \
           for (  _jj=0; _jj<16; _jj++ ) \
           fprintf(  stderr,  "%02x ",  a->xmmregs[i][_jj] ); \
           fprintf(  stderr,  "\n !=\n" ); \
           fprintf(  stderr,  " " ); \
           for (  _jj=0; _jj<16; _jj++ ) \
           fprintf(  stderr,  "%02x ",  b->xmmregs[i][_jj] ); \
           fprintf(  stderr,  "\n" ); \
           } \
           } \
           } while (  0 )
          
          
          /* Compare two FPU/SSE context areas and flag differences;
           * RETURNS: zero if the contexts match and nonzero otherwise
           */
          static int
          cmp_ctxt(  Context_Control_sse *a,   Context_Control_sse *b,   int quiet )
          {
          int rval = 0;
          int i;
           FLDCMP(  fcw,  H16 );
           FLDCMP(  fsw,  H16 );
           FLDCMP(  ftw,  H08 );
           FLDCMP(  fop,  H16 );
           FLDCMP(  fpu_ip,  H32 );
           FLDCMP(  cs,  H16 );
           FLDCMP(  fpu_dp,  H32 );
           FLDCMP(  ds,  H16 );
           FLDCMP(  mxcsr,  H32 );
           FLDCMP(  mxcsr_mask,  H32 );
           for (   i=0; i<8; i++  ) {
           FLTCMP(  i );
           }
           for (   i=0; i<8; i++  ) {
           XMMCMP(  i );
           }
           return rval;
          }
          
          /* Possible arguments to exc_raise(   ) */
          
          #define FP_EXC 0
          #define IRQ_EXC 1
          #define SSE_EXC -1
          
          /* Check stack alignment by raising the interrupt from a
           * non-16-byte aligned section of code. The exception/IRQ
           * handler must align the stack and SSE context area
           * properly or it will crash.
           */
          #define __INTRAISE(  x ) " int $32+"#x" \n"
          #define INTRAISE(  x ) __INTRAISE(  x )
          
          asm(  
          "do_raise: \n"
          " fwait \n"
          " test %eax,   %eax \n"
          " je 2f \n"
          " jl 1f \n"
          INTRAISE(  SSE_TEST_IRQ )
          " jmp 2f \n"
          "1: sqrtps %xmm0,   %xmm0 \n"
          "2: \n"
          " ret \n"
           );
          
          #define SSE_TEST_HP_FAILED 1
          #define SSE_TEST_FSPR_FAILED 2
          #define SSE_TEST_CTXTCMP_FAILED 4
          
          static const char *fail_msgs[] = {
           "Seems that HP task was not executing",  
           "FPSR 'Invalid-operation' flag should be clear",  
           "Restored context does NOT match the saved one",  
          };
          
          static void prstat(  int st,   const char *where )
          {
          int i,  msk;
           for (   i=0,   msk=1; i<sizeof(  fail_msgs )/sizeof(  fail_msgs[0] ); i++,   msk<<=1  ) {
           if (   (  st & msk )  ) {
           fprintf(  stderr,  "sse_test ERROR: %s (  testing: %s )\n",   fail_msgs[i],   where );
           }
           }
          }
          
          int sse_test_debug = 0;
          
          static int
          exc_raise(  int kind )
          {
          Context_Control_sse nctxt;
          Context_Control_sse octxt;
          Context_Control_sse orig_ctxt;
          int i,  j,  rval;
          double s2;
          uint16_t fsw;
          __vf f4 = { -1.,   -2.,   -3.,   -4. };
          __vf tmp;
          __v32 sgn = { (  1<<31 ),   (  1<<31 ),   (  1<<31 ),   (  1<<31 ) };
          
           stor_ctxt(  &octxt );
          
           octxt.fsw &= ~FPSR_ALLE;
           octxt.mxcsr &= ~MXCSR_ALLE;
          
           for (   i=0; i<8; i++  ) {
           fp_st(  &octxt,   i,   (  double )i+0.1 );
           for (  j=0; j<16; j++ ) {
           octxt.xmmregs[i][j]=(  i<<4 )+j;
           }
           }
          
          
           if (   SSE_EXC == kind  ) {
           memcpy(  octxt.xmmregs[0],   &f4,   sizeof(  f4 ) );
           octxt.mxcsr &= ~MXCSR_IM;
           }
          
           /* set tags to 'valid' */
           octxt.ftw = 0xff;
          
           /* enable 'invalid arg' exception */
           octxt.fcw &= ~ (   FPCW_IM  );
          
           if (   FP_EXC == kind  ) {
           octxt.fsw |= (   FPSR_IE | FPSR_ES  );
           }
          
           if (   sse_test_debug  )
           printk(  "RAISE (  fsw was 0x%04x )\n",   orig_ctxt.fsw );
           asm volatile(  
           " fxsave %2 \n"
          #ifdef __rtems__
           " movl %4,   sse_test_check\n"
          #endif
           " fxrstor %3 \n"
           " call do_raise \n"
          #ifdef __rtems__
           " movl sse_test_check,   %1\n"
          #else
           " movl $0,   %1 \n"
          #endif
          #ifdef TEST_MISMATCH
           " pxor %%xmm0,   %%xmm0 \n"
          #endif
           " fxsave %0 \n"
           " fxrstor %2 \n"
           : "=m"(  nctxt ),  "=&r"(  rval ),  "=m"(  orig_ctxt )
           : "m"(  octxt ),   "i"(  SSE_TEST_HP_FAILED ),  "a"(  kind )
           : "xmm0"
            );
          
           if (   (   FPSR_IE & nctxt.fsw  )  ) {
           rval |= SSE_TEST_FSPR_FAILED;
           }
           if (   FP_EXC == kind  )
           nctxt.fsw |= (  FPSR_IE | FPSR_ES );
           else if (   SSE_EXC == kind  ) {
           tmp = __builtin_ia32_sqrtps(   (  __vf )(  ~sgn & (  __v32 )f4 )  );
           /* sqrt raises PE; just clear it */
           nctxt.mxcsr &= ~MXCSR_PE;
           memcpy(   octxt.xmmregs[0],   &tmp,   sizeof(  tmp )  );
           }
          
           if (   cmp_ctxt(  &nctxt,   &octxt,   0 )  ) {
           rval |= SSE_TEST_CTXTCMP_FAILED;
           }
          
           s2 = sqrt(  2.0 );
          
           asm volatile(  "fstsw %0":"=m"(  fsw ) );
          
           if (   sse_test_debug  )
           printf(  "sqrt(  2 ): %f (  FSTW: 0x%02"PRIx16" )\n",   sqrt(  2.0 ),   fsw );
          
           return rval;
          }
          
          #ifdef __rtems__
          static void
          sse_test_ehdl(  CPU_Exception_frame *p_f );
          
          rtems_id sse_test_sync = 0;
          cpuExcHandlerType sse_test_ohdl = 0;
          
          CPU_Exception_frame *sse_test_frame = 0;
          volatile int sse_test_check = SSE_TEST_HP_FAILED;
          unsigned sse_tests = 0;
          
          rtems_task
          sse_test_hp_task(  rtems_task_argument arg )
          {
          rtems_id sync = (  rtems_id )arg;
          
          uint16_t fp_cw;
          uint32_t mxcsr;
          rtems_status_code sc;
          const char * msgs[] = {"FPU_EXC",   "SSE_EXC",   "IRQ_EXC"};
          int i;
          
           /* verify that FPU control word is default value */
           asm volatile(  "fstcw %0":"=m"(  fp_cw ) );
           if (   fp_cw != _CPU_Null_fp_context.fpucw  ) {
           fprintf(  
           stderr,  
           "ERROR: FPU CW initialization mismatch: got 0x%04"PRIx16"; expected 0x%04"PRIx16"\n",  
           fp_cw,  
           _CPU_Null_fp_context.fpucw
            );
           }
          
           /* check MXCSR default value */
           asm volatile(  "stmxcsr %0":"=m"(  mxcsr ) );
           if (   mxcsr != _CPU_Null_fp_context.mxcsr  ) {
           fprintf(  
           stderr,  
           "ERROR: MXCSR initialization mismatch: got 0x%08"PRIx32"; expected 0x%08"PRIx32"\n",  
           mxcsr,  
           _CPU_Null_fp_context.mxcsr
            );
           }
          
          
           for (  i=0; i<sizeof(  msgs )/sizeof(  msgs[0] ); i++  ) {
           if (   (   sse_tests & (  1<<i )  )  ) {
           if (   sse_test_debug  )
           printk(  "HP task will now block for %s\n",  msgs[i] );
          
           /* Blocking here lets the low-priority task continue */
           sc = rtems_semaphore_obtain(  sync,   RTEMS_WAIT,   500 );
          
           all_clobber(  0xaffeaffe,   0xcafecafe );
          
           if (   RTEMS_SUCCESSFUL != sc  ) {
           rtems_error(  sc,  "ERROR: sse_test hp task wasn't notified of exception\n" );
           goto bail;
           }
          
           /* set flag indicating that we executed until here */
           sse_test_check = 0;
           }
           }
          
          bail:
           rtems_task_suspend(  RTEMS_SELF );
          }
          
          /* Flags to skip individual tests */
          #define SSE_TEST_FPU_EXC (  1<<0 )
          #define SSE_TEST_SSE_EXC (  1<<1 )
          #define SSE_TEST_IRQ_EXC (  1<<2 )
          
          #define SSE_TEST_ALL 7
          
          /* If this flag is given the executing task is not deleted
           * when the test finishes. This is useful if you want to
           * execute from a shell or similar.
           */
          #define SSE_TEST_NO_DEL (  1<<0 )
          
          /* Task arg is bitmask of these flags */
          rtems_task
          sse_test_lp_task(  rtems_task_argument arg )
          {
          rtems_id hp_task = 0;
          rtems_status_code sc;
          rtems_task_priority pri;
          uint16_t fp_cw,  fp_cw_set;
          uint32_t mxcsr,   mxcsr_set;
          rtems_irq_connect_data irqd;
          int flags = (  int )arg;
          int st;
          int errs = 0;
          
           sse_tests = SSE_TEST_ALL & ~(  flags>>1 );
          
           sse_test_ohdl = 0;
          
           fp_cw_set = _CPU_Null_fp_context.fpucw | FPCW_RC(  3 ) ;
           mxcsr_set = _CPU_Null_fp_context.mxcsr | MXCSR_RC(  3 ) ;
           asm volatile(  "ldmxcsr %0"::"m"(  mxcsr_set ) );
           asm volatile(  "fldcw %0"::"m"(  fp_cw_set ) );
          
           sc = rtems_semaphore_create(  
           rtems_build_name(  's',  's',  'e',  'S' ),  
           0,  
           RTEMS_SIMPLE_BINARY_SEMAPHORE,  
           0,  
           &sse_test_sync
            );
           if (   RTEMS_SUCCESSFUL != sc  ) {
           rtems_error(  sc,   "sse_test ERROR: creation of 'sync' semaphore failed" );
           errs++;
           goto bail;
           }
          
           rtems_task_set_priority(   RTEMS_SELF,   RTEMS_CURRENT_PRIORITY,   &pri  );
          
           sc = rtems_task_create(  
           rtems_build_name(  's',  's',  'e',  'H' ),  
           pri - 2,  
           20000,  
           RTEMS_DEFAULT_MODES,  
           RTEMS_FLOATING_POINT,  
           &hp_task
            );
           if (   RTEMS_SUCCESSFUL != sc  ) {
           hp_task = 0;
           rtems_error(   sc,   "sse_test ERROR: creation of high-priority task failed" );
           errs++;
           goto bail;
           }
          
           sc = rtems_task_start(   hp_task,   sse_test_hp_task,   (  rtems_task_argument )sse_test_sync  );
           if (   RTEMS_SUCCESSFUL != sc  ) {
           rtems_error(   sc,   "sse_test ERROR: start of high-priority task failed" );
           goto bail;
           }
          
           /* Test if FP/SSE context is saved/restored across an exception */
           sse_test_ohdl = _currentExcHandler;
           _currentExcHandler = sse_test_ehdl;
          
           if (   (  sse_tests & SSE_TEST_FPU_EXC )  ) {
           if (   (  st = exc_raise(  FP_EXC ) )  ) {
           prstat(  st,  "FP_EXC" );
           errs++;
           }
          
           /* Test modified FPCW/MXCSR */
           asm volatile(  "fstcw %0":"=m"(  fp_cw ) );
           asm volatile(  "stmxcsr %0":"=m"(  mxcsr ) );
           mxcsr &= ~(  MXCSR_ALLE );
           if (   fp_cw != fp_cw_set  ) {
           fprintf(  stderr,  "sse_test ERROR: FPCW mismatch (  after FP_EXC ): expected 0x%04"PRIx16",   got 0x%04"PRIx16"\n",   fp_cw_set,   fp_cw );
           errs++;
           }
           if (   mxcsr != mxcsr_set  ) {
           fprintf(  stderr,  "sse_test ERROR: MXCSR mismatch (  after FP_EXC ): expected 0x%08"PRIx32",   got 0x%08"PRIx32"\n",   mxcsr_set,   mxcsr );
           errs++;
           }
           }
          
           if (   (  sse_tests & SSE_TEST_SSE_EXC )  ) {
           if (   (  st = exc_raise(  SSE_EXC ) )  ) {
           prstat(  st,   "SSE_EXC" );
           errs++;
           }
          
           /* Test modified FPCW/MXCSR */
           asm volatile(  "fstcw %0":"=m"(  fp_cw ) );
           asm volatile(  "stmxcsr %0":"=m"(  mxcsr ) );
           mxcsr &= ~(  MXCSR_ALLE );
           if (   fp_cw != fp_cw_set  ) {
           fprintf(  stderr,  "sse_test ERROR: FPCW mismatch (  after SSE_EXC ): expected 0x%04"PRIx16",   got 0x%04"PRIx16"\n",   fp_cw_set,   fp_cw );
           errs++;
           }
           if (   mxcsr != mxcsr_set  ) {
           fprintf(  stderr,  "sse_test ERROR: MXCSR mismatch (  after SSE_EXC ): expected 0x%08"PRIx32",   got 0x%08"PRIx32"\n",   mxcsr_set,   mxcsr );
           errs++;
           }
           }
          
          
           if (   (  sse_tests & SSE_TEST_IRQ_EXC )  ) {
           memset(   &irqd,   0,   sizeof(  irqd )  );
           irqd.name = SSE_TEST_IRQ;
           irqd.hdl = (  void* )sse_test_ehdl;
           irqd.handle = 0;
          
           if (   ! BSP_install_rtems_irq_handler(   &irqd  )  ) {
           fprintf(  stderr,   "sse_test ERROR: Unable to install ISR\n" );
           errs++;
           goto bail;
           }
          
           /* Test if FP/SSE context is saved/restored across an interrupt */
           if (   (  st = exc_raise(  IRQ_EXC ) )  ) {
           prstat(  st,   "IRQ" );
           errs++;
           }
          
           if (   ! BSP_remove_rtems_irq_handler(   &irqd  )  ) {
           fprintf(  stderr,   "sse_test ERROR: Unable to uninstall ISR\n" );
           }
          
           /* Test modified FPCW/MXCSR */
           asm volatile(  "fstcw %0":"=m"(  fp_cw ) );
           asm volatile(  "stmxcsr %0":"=m"(  mxcsr ) );
           mxcsr &= ~(  MXCSR_ALLE );
           if (   fp_cw != fp_cw_set  ) {
           fprintf(  stderr,  "sse_test ERROR: FPCW mismatch (  after IRQ ): expected 0x%04"PRIx16",   got 0x%04"PRIx16"\n",   fp_cw_set,   fp_cw );
           errs++;
           }
           if (   mxcsr != mxcsr_set  ) {
           fprintf(  stderr,  "sse_test ERROR: MXCSR mismatch (  after IRQ ): expected 0x%08"PRIx32",   got 0x%08"PRIx32"\n",   mxcsr_set,   mxcsr );
           errs++;
           }
           }
          
          
          bail:
           /* Wait for console to calm down... */
           rtems_task_wake_after(  5 );
           fprintf(  stderr,  "SSE/FPU Test %s (  %u errors )\n",   errs ? "FAILED":"PASSED",   errs );
           if (   sse_test_ohdl  ) {
           _currentExcHandler = sse_test_ohdl;
           sse_test_ohdl = 0;
           }
           if (   sse_test_sync  )
           rtems_semaphore_delete(   sse_test_sync  );
           sse_test_sync = 0;
           if (   hp_task  )
           rtems_task_delete(   hp_task  );
          
           if (   ! (  flags & SSE_TEST_NO_DEL )  )
           rtems_task_delete(   RTEMS_SELF  );
          }
          
          static void
          sse_test_ehdl(  CPU_Exception_frame *p_f )
          {
          int i,  j,  start = 0;
          int mismatch;
          __vf f4;
          
           if (   p_f  ) {
           printk(  "Got exception #%u\n",   p_f->idtIndex );
           printk(  "EIP: 0x%08x,   ESP: 0x%08x\n",   p_f->eip,   p_f->esp0 );
           printk(  "TID: 0x%08x\n",   _Thread_Executing->Object.id );
          
           if (   ! p_f->fp_ctxt  ) {
           printk(  "ERROR: NO FP/SSE CONTEXT ATTACHED ??\n" );
           sse_test_ohdl(  p_f );
           }
           if (   16 == p_f->idtIndex  ) {
           printk(  "Resetting FP status (  0x%04"PRIx16" )\n",   p_f->fp_ctxt->fsw );
           p_f->fp_ctxt->fsw = 0;
           } else if (   19 == p_f->idtIndex  ) {
           start = 1;
           memcpy(  &f4,   p_f->fp_ctxt->xmmregs[0],   sizeof(  f4 ) );
           f4 = -f4;
           memcpy(  p_f->fp_ctxt->xmmregs[0],   &f4,   sizeof(  f4 ) );
           p_f->fp_ctxt->mxcsr &= ~MXCSR_ALLE;
           } else {
           printk(  "(  skipping non-FP exception )\n" );
           sse_test_ohdl(  p_f );
           }
          
           printk(  "Checking XMM regs -- " );
           for (   mismatch=0,   i=start; i<8; i++  ) {
           for (   j=0; j<16; j++  ) {
           if (   p_f->fp_ctxt->xmmregs[i][j] != (  (  i<<4 ) | j )  )
           mismatch++;
           }
           }
           if (   mismatch  ) {
           printk(  "%u mismatches; dump:\n",   mismatch );
           for (   i=0; i<8; i++  ) {
           for (   j=0; j<16; j++  ) {
           printk(  "0x%02x ",   p_f->fp_ctxt->xmmregs[i][j] );
           }
           printk(  "\n" );
           }
           } else {
           printk(  "OK\n" );
           }
           } else {
           printk(  "IRQ %u\n",   SSE_TEST_IRQ );
           }
           printk(  "Clobbering FPU/SSE state\n" );
           asm volatile(  "finit" );
           sse_clobber(  0xdeadbeef );
           printk(  "Notifying task\n" );
           rtems_semaphore_release(   sse_test_sync  );
          }
          
          #else
          
          /* Code using signals for testing under linux; unfortunately,   32-bit
           * linux seems to pass no SSE context info to the sigaction...
           */
          
          #include <signal.h>
          #include <ucontext.h>
          
          #define MKCASE(  X ) case FPE_##X: msg="FPE_"#X; break;
          
          #define CLRXMM(  i ) asm volatile(  "pxor %%xmm"#i",   %%xmm"#i:::"xmm"#i )
          
          static void
          fpe_act(  int signum,   siginfo_t *p_info,   void *arg3 )
          {
          ucontext_t *p_ctxt = arg3;
          const char *msg = "FPE_UNKNOWN";
          uint16_t *p_fst;
          
           if (   SIGFPE != signum  ) {
           fprintf(  stderr,  "WARNING: fpe_act handles SIGFPE\n" );
           return;
           }
           switch (   p_info->si_code  ) {
           default:
           fprintf(  stderr,  "WARNING: fpe_act got unkown code %u\n",   p_info->si_code );
           return;
           MKCASE(  INTDIV );
           MKCASE(  INTOVF );
           MKCASE(  FLTDIV );
           MKCASE(  FLTOVF );
           MKCASE(  FLTUND );
           MKCASE(  FLTRES );
           MKCASE(  FLTINV );
           MKCASE(  FLTSUB );
           }
           fprintf(  stderr,  "Got SIGFPE (  %s ) @%p\n",   msg,   p_info->si_addr );
          #ifdef __linux__
           fprintf(  stderr,  "Resetting FP status 0x%02lx\n",   p_ctxt->uc_mcontext.fpregs->sw );
           p_ctxt->uc_mcontext.fpregs->sw = 0;
          #ifdef TEST_MISMATCH
           fp_st1(  (  void* )&p_ctxt->uc_mcontext.fpregs->_st[3],  2.345 );
          #endif
          #endif
          
           /* Clear FPU; if context is properly saved/restored around exception
           * then this shouldn't disturb the register contents of the interrupted
           * task/process.
           */
           asm volatile(  "finit" );
           sse_clobber(  0xdeadbeef );
          }
          
          static void
          test(  void )
          {
          Context_Control_sse ctxt;
          
           stor_ctxt(  &ctxt );
           printf(  "FPCW: 0x%"PRIx16"\nFPSW: 0x%"PRIx16"\n",   ctxt.fcw,   ctxt.fsw );
           printf(  "FTAG: 0x%"PRIx8"\n",  ctxt.ftw );
          }
          
          int
          main(  int argc,   char **argv )
          {
          struct sigaction a1,   a2;
          uint32_t mxcsr;
          
           memset(  &a1,   0,   sizeof(  a1 ) );
          
           a1.sa_sigaction = fpe_act;
           a1.sa_flags = SA_SIGINFO;
          
           if (   sigaction(  SIGFPE,   &a1,   &a2 )  ) {
           perror(  "sigaction" );
           return 1;
           }
          
           asm volatile(  "stmxcsr %0":"=m"(  mxcsr ) );
           printf(  "MXCSR: 0x%08"PRIx32"\n",   mxcsr );
          
           test(   );
           exc_raise(  0 );
           return 0;
          }
          #endif
          
          /* Helpers to access CR4 and MXCSR */
          
          uint32_t
          mfcr4(   )
          {
          uint32_t rval;
           asm volatile(  "mov %%cr4,   %0":"=r"(  rval ) );
           return rval;
          }
          
          void
          mtcr4(  uint32_t rval )
          {
           asm volatile(  "mov %0,   %%cr4"::"r"(  rval ) );
          }
          
          uint32_t
          mfmxcsr(   )
          {
          uint32_t rval;
           asm volatile(  "stmxcsr %0":"=m"(  rval ) );
           return rval;
          }
          
          void
          mtmxcsr(  uint32_t rval )
          {
           asm volatile(  "ldmxcsr %0"::"m"(  rval ) );
          }
          
          
          float
          sseraise(   )
          {
          __vf f4={-2.,   -2.,   -2. -2.};
          float f;
           f4 = __builtin_ia32_sqrtps(   f4  );
           memcpy(  &f,  &f4,  sizeof(  f ) );
           return f;
          }

score/cpu/lm32/cpu.c

       1  /*
           * Lattice Mico32 (  lm32 ) CPU Dependent Source
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.7 2010/03/27 15:01:51 joel Exp $
           *
           * Jukka Pietarinen <jukka.pietarinen@mrf.fi>,   2008,  
           * Micro-Research Finland Oy
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/wkspace.h>
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           *
           * LM32 Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      37  void _CPU_Initialize(  void )
          {
           /*
           * If there is not an easy way to initialize the FP context
           * during Context_Initialize,   then it is usually easier to
           * save an "uninitialized" FP context here and copy it to
           * the task's during Context_Initialize.
           */
          
           /* FP context initialization support goes here */
          }
          
          /*PAGE
           *
           * _CPU_ISR_Get_level
           *
           * LM32 Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      58  uint32_t _CPU_ISR_Get_level(   void  )
          {
           /*
           * This routine returns the current interrupt level.
           */
          
           return 0;
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           *
           * LM32 Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      76  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           /*
           * This is where we install the interrupt handler into the "raw" interrupt
           * table used by the CPU to dispatch interrupt handlers.
           */
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * old_handler - former ISR for this vector number
           * new_handler - replacement ISR for this vector number
           *
           * Output parameters: NONE
           *
           *
           * LM32 Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     108  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           *old_handler = _ISR_Vector_table[ vector ];
          
           /*
           * If the interrupt vector table is a table of pointer to isr entry
           * points,   then we need to install the appropriate RTEMS interrupt
           * handler for this vector number.
           */
          
           _CPU_ISR_install_raw_handler(   vector,   new_handler,   old_handler  );
          
           /*
           * We put the actual user ISR address in '_ISR_vector_table'. This will
           * be used by the _ISR_Handler so the user gets control.
           */
          
           _ISR_Vector_table[ vector ] = new_handler;
          }
          
          /*PAGE
           *
           * _CPU_Install_interrupt_stack
           *
           * LM32 Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     141  void _CPU_Install_interrupt_stack(   void  )
          {
          }
          
          /*PAGE
           *
           * _CPU_Thread_Idle_body
           *
           * NOTES:
           *
           * 1. This is the same as the regular CPU independent algorithm.
           *
           * 2. If you implement this using a "halt",   "idle",   or "shutdown"
           * instruction,   then don't forget to put it in an infinite loop.
           *
           * 3. Be warned. Some processors with onboard DMA have been known
           * to stop the DMA if the CPU were put in IDLE mode. This might
           * also be a problem with other on-chip peripherals. So use this
           * hook with caution.
           *
           * LM32 Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     166  void *_CPU_Thread_Idle_body(   uintptr_t ignored  )
          {
           for(   ; ;  ) {
           /* The LM32 softcore itself hasn't any HLT instruction. But the
           * LM32 qemu target interprets this nop instruction as HLT.
           */
           asm volatile(  "and r0,   r0,   r0" );
           }
          }

score/cpu/lm32/irq.c

       1  /*
           * lm32 interrupt handler
           *
           * Derived from c4x/irq.c and nios2/irq.c
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: irq.c,  v 1.6 2010/07/30 18:52:06 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/cpu.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/percpu.h>
          
          /*
           * This routine provides the RTEMS interrupt management.
           *
           * Upon entry,   interrupts are disabled
           */
          
          #if(   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
           unsigned long *_old_stack_ptr;
          #endif
          
          void *_exception_stack_frame;
          
      38  register unsigned long *stack_ptr asm(  "sp" );
          
      40  void __ISR_Handler(  uint32_t vector,   CPU_Interrupt_frame *ifr )
          {
           register uint32_t level;
           _exception_stack_frame = NULL;
          
           /* Interrupts are disabled upon entry to this Handler */
          
           _Thread_Dispatch_disable_level++;
          
          #if(   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
           if (   _ISR_Nest_level == 0  ) {
           /* Install irq stack */
           _old_stack_ptr = stack_ptr;
           stack_ptr = _CPU_Interrupt_stack_high - 4;
           }
          #endif
          
           _ISR_Nest_level++;
          
           if (   _ISR_Vector_table[ vector]  )
           {
           (  *_ISR_Vector_table[ vector ] )(  vector,   ifr );
           };
          
           /* Make sure that interrupts are disabled again */
           _CPU_ISR_Disable(   level  );
          
           _ISR_Nest_level--;
          
          #if(   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
           if(   _ISR_Nest_level == 0 )
           stack_ptr = _old_stack_ptr;
          #endif
          
           _Thread_Dispatch_disable_level--;
          
           _CPU_ISR_Enable(   level  );
          
           if (   _ISR_Nest_level  )
           return;
          
           if (   _Thread_Dispatch_necessary  ) {
          
           /* save off our stack frame so the context switcher can get to it */
           _exception_stack_frame = ifr;
          
           _Thread_Dispatch(   );
          
           /* and make sure its clear in case we didn't dispatch. if we did,   its
           * already cleared */
           _exception_stack_frame = NULL;
           }
          }
          

score/cpu/m32c/context_init.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: context_init.c,  v 1.6 2010/05/10 20:08:50 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdint.h>
          #include <rtems/system.h>
          
          typedef struct {
           uint16_t sbLow;
           uint16_t sbHigh; /* push/pop sb */
           uint16_t flg; /* push/pop flg */
           uint32_t a1; /* pushm */
           uint32_t a0;
           uint32_t r0r2;
           uint32_t r1r3;
           uint16_t frameLow; /* exitd */
           uint16_t frameHigh;
           uint16_t startLow;
           uint16_t startHigh;
           uint16_t zero;
          } Starting_Frame;
          
          #if defined(  __r8c_cpu__ )
           #warning "_get_sb: not implemented on R8C"
           #define _get_sb(   _sb  )
          #else
           #define _get_sb(   _sb  ) \
           asm volatile(   "stc sb,   %0" : "=r" (  _sb ) )
          #endif
      41  
          void _CPU_Context_Initialize(  
           Context_Control *the_context,  
           uint32_t *stack_base,  
           size_t size,  
           uint32_t new_level,  
           void *entry_point,  
           bool is_fp
           )
          {
           void *stackEnd = stack_base;
           register uint32_t sb;
           Starting_Frame *frame;
          
           _get_sb(   sb  );
           stackEnd += size;
          
           frame = (  Starting_Frame * )stackEnd;
           frame--;
          
           frame->zero = 0;
           frame->sbLow = (  (  uint32_t )sb ) & 0xffff;
           frame->sbHigh = (  (  uint32_t )sb >> 16 ) & 0xffff;
           frame->flg = 0x80; /* User stack */
           if (   !new_level  ) /* interrupt level 0 --> enabled */
           frame->flg |= 0x40;
           frame->a0 = 0x01020304;
           frame->a1 =0xa1a2a3a4;
           frame->r0r2 = 0;
           frame->r1r3 = 0;
          #if defined(  __r8c_cpu__ )
           #warning "not implemented on R8C"
          #else
           frame->frameLow = (  uint16_t ) (  (  (  uint32_t )frame ) & 0xffff );
           frame->frameHigh = (  uint16_t ) (  (  (  uint32_t )frame >> 16 ) & 0xffff );
           frame->startLow = (  uint16_t ) (  (  (  uint32_t )entry_point ) & 0xffff );
           frame->startHigh = (  uint16_t ) (  (  (  uint32_t )entry_point >> 16 ) & 0xffff );
          #endif
           the_context->sp = (  uintptr_t )frame;
           the_context->fb = (  uintptr_t )&frame->frameLow;
          }

score/cpu/m32c/cpu.c

       1  /*
           * XXX CPU Dependent Source
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.8 2010/05/10 20:08:50 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <varvects.h>
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      33  void _CPU_Initialize(  void )
          {
           #if !defined(  __r8c_cpu__ )
           asm volatile(   "ldc #__var_vects,  intb"  );
           #endif
          }
          
          /*
           * This routine returns the current interrupt level.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      48  uint32_t _CPU_ISR_Get_level(   void  )
          {
           int flag;
           m32c_get_flg(   flag  );
          
           return (  (  flag & 0x40 ) ? 0 : 1 );
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      65  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           /*
           * This is where we install the interrupt handler into the "raw" interrupt
           * table used by the CPU to dispatch interrupt handlers.
           */
          #if defined(  __r8c_cpu__ )
           #warning "_CPU_ISR_install_raw_handler not implemented on R8C"
          #else
           _set_var_vect(  new_handler,  vector );
          #endif
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * old_handler - former ISR for this vector number
           * new_handler - replacement ISR for this vector number
           *
           * Output parameters: NONE
           *
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     102  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           *old_handler = _ISR_Vector_table[ vector ];
          
           /*
           * If the interrupt vector table is a table of pointer to isr entry
           * points,   then we need to install the appropriate RTEMS interrupt
           * handler for this vector number.
           */
          
           _CPU_ISR_install_raw_handler(   vector,   new_handler,   old_handler  );
          
           /*
           * We put the actual user ISR address in '_ISR_vector_table'. This will
           * be used by the _ISR_Handler so the user gets control.
           */
          
           _ISR_Vector_table[ vector ] = new_handler;
          }
          
          /*PAGE
           *
           * _CPU_Install_interrupt_stack
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     135  void _CPU_Install_interrupt_stack(   void  )
          {
          }
          
          /*PAGE
           *
           * _CPU_Thread_Idle_body
           *
           * NOTES:
           *
           * 1. This is the same as the regular CPU independent algorithm.
           *
           * 2. If you implement this using a "halt",   "idle",   or "shutdown"
           * instruction,   then don't forget to put it in an infinite loop.
           *
           * 3. Be warned. Some processors with onboard DMA have been known
           * to stop the DMA if the CPU were put in IDLE mode. This might
           * also be a problem with other on-chip peripherals. So use this
           * hook with caution.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     160  void *_CPU_Thread_Idle_body(   uintptr_t ignored  )
          {
          
           for(   ; ;  )
           /* insert your "halt" instruction here */ ;
          }

score/cpu/m32c/cpu_asm.c

       1  /* cpu_asm.c ===> cpu_asm.S or cpu_asm.s
           *
           * This file contains the basic algorithms for all assembly code used
           * in an specific CPU port of RTEMS. These algorithms must be implemented
           * in assembly language
           *
           * NOTE: This is supposed to be a .S or .s file NOT a C file.
           *
           * M32C does not yet have interrupt support. When this functionality
           * is written,   this file should become obsolete.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu_asm.c,  v 1.7 2010/07/30 18:52:08 joel Exp $
           */
          
          /*
           * This is supposed to be an assembly file. This means that system.h
           * and cpu.h should not be included in a "real" cpu_asm file. An
           * implementation in assembly should include "cpu_asm.h>
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/cpu.h>
          
          /* void __ISR_Handler(   )
           *
           * This routine provides the RTEMS interrupt management.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      44  void _ISR_Handler(  void )
          {
           /*
           * This discussion ignores a lot of the ugly details in a real
           * implementation such as saving enough registers/state to be
           * able to do something real. Keep in mind that the goal is
           * to invoke a user's ISR handler which is written in C and
           * uses a certain set of registers.
           *
           * Also note that the exact order is to a large extent flexible.
           * Hardware will dictate a sequence for a certain subset of
           * _ISR_Handler while requirements for setting
           */
          
           /*
           * At entry to "common" _ISR_Handler,   the vector number must be
           * available. On some CPUs the hardware puts either the vector
           * number or the offset into the vector table for this ISR in a
           * known place. If the hardware does not give us this information,  
           * then the assembly portion of RTEMS for this port will contain
           * a set of distinct interrupt entry points which somehow place
           * the vector number in a known place (  which is safe if another
           * interrupt nests this one ) and branches to _ISR_Handler.
           *
           * save some or all context on stack
           * may need to save some special interrupt information for exit
           *
           * #if (   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE  )
           * if (   _ISR_Nest_level == 0  )
           * switch to software interrupt stack
           * #endif
           *
           * _ISR_Nest_level++;
           *
           * _Thread_Dispatch_disable_level++;
           *
           * (  *_ISR_Vector_table[ vector ] )(   vector  );
           *
           * _Thread_Dispatch_disable_level--;
           *
           * --_ISR_Nest_level;
           *
           * if (   _ISR_Nest_level  )
           * goto the label "exit interrupt (  simple case )"
           *
           * if (   _Thread_Dispatch_disable_level  )
           * goto the label "exit interrupt (  simple case )"
           *
           * if (   _Thread_Dispatch_necessary  ) {
           * call _Thread_Dispatch(   ) or prepare to return to _ISR_Dispatch
           * prepare to get out of interrupt
           * return from interrupt (  maybe to _ISR_Dispatch )
           *
           * LABEL "exit interrupt (  simple case ):
           * #if (   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE  )
           * if outermost interrupt
           * restore stack
           * #endif
           * prepare to get out of interrupt
           * return from interrupt
           */
          }

score/cpu/m32r/context_init.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: context_init.c,  v 1.2 2010/03/27 15:02:02 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <stdint.h>
          #include <rtems/system.h>
          
          typedef struct {
           uint32_t marker;
          } Starting_Frame;
          
          #define _get_r12(   _r12  ) \
           asm volatile(   "mv r12,   %0" : "=r" (  _r12 ) )
      25  
          void _CPU_Context_Initialize(  
           Context_Control *the_context,  
           uint32_t *stack_base,  
           uint32_t size,  
           uint32_t new_level,  
           void *entry_point,  
           bool is_fp
           )
          {
           void *stackEnd = stack_base;
           Starting_Frame *frame;
           uint32_t r12;
          
           stackEnd += size;
          
           frame = (  Starting_Frame * )stackEnd;
           frame--;
           frame->marker = 0xa5a5a5a5;
          
           _get_r12(   r12  );
          
           the_context->r8 = 0x88888888;
           the_context->r9 = 0x99999999;
           the_context->r10 = 0xaaaaaaaa;
           the_context->r11 = 0xbbbbbbbb;
           the_context->r12 = r12;
           the_context->r13_fp = 0;
           the_context->r14_lr = (  uintptr_t ) entry_point;
           the_context->r15_sp = (  uintptr_t ) frame;
          
          }

score/cpu/m32r/cpu.c

       1  /*
           * M32R CPU Dependent Source
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.5 2010/03/27 15:02:02 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      32  void _CPU_Initialize(  void )
          {
          }
          
          /*
           * This routine returns the current interrupt level.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      44  uint32_t _CPU_ISR_Get_level(   void  )
          {
           return 0;
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      58  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           /*
           * This is where we install the interrupt handler into the "raw" interrupt
           * table used by the CPU to dispatch interrupt handlers.
           */
           /* _set_var_vect(  new_handler,  vector ); */
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * old_handler - former ISR for this vector number
           * new_handler - replacement ISR for this vector number
           *
           * Output parameters: NONE
           *
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      91  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           *old_handler = _ISR_Vector_table[ vector ];
          
           /*
           * If the interrupt vector table is a table of pointer to isr entry
           * points,   then we need to install the appropriate RTEMS interrupt
           * handler for this vector number.
           */
          
           _CPU_ISR_install_raw_handler(   vector,   new_handler,   old_handler  );
          
           /*
           * We put the actual user ISR address in '_ISR_vector_table'. This will
           * be used by the _ISR_Handler so the user gets control.
           */
          
           _ISR_Vector_table[ vector ] = new_handler;
          }
          
          /*PAGE
           *
           * _CPU_Install_interrupt_stack
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     124  void _CPU_Install_interrupt_stack(   void  )
          {
          }

score/cpu/m32r/cpu_asm.c

       1  /* cpu_asm.c ===> cpu_asm.S or cpu_asm.s
           *
           * NOTE: This is supposed to be a .S or .s file NOT a C file.
           *
           * M32R does not yet have interrupt support. When this functionality
           * is written,   this file should become obsolete.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu_asm.c,  v 1.5 2010/07/30 18:52:10 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/cpu.h>
          
          /* void __ISR_Handler(   )
           *
           * This routine provides the RTEMS interrupt management.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      34  void _ISR_Handler(  void )
          {
           /*
           * This discussion ignores a lot of the ugly details in a real
           * implementation such as saving enough registers/state to be
           * able to do something real. Keep in mind that the goal is
           * to invoke a user's ISR handler which is written in C and
           * uses a certain set of registers.
           *
           * Also note that the exact order is to a large extent flexible.
           * Hardware will dictate a sequence for a certain subset of
           * _ISR_Handler while requirements for setting
           */
          
           /*
           * At entry to "common" _ISR_Handler,   the vector number must be
           * available. On some CPUs the hardware puts either the vector
           * number or the offset into the vector table for this ISR in a
           * known place. If the hardware does not give us this information,  
           * then the assembly portion of RTEMS for this port will contain
           * a set of distinct interrupt entry points which somehow place
           * the vector number in a known place (  which is safe if another
           * interrupt nests this one ) and branches to _ISR_Handler.
           *
           * save some or all context on stack
           * may need to save some special interrupt information for exit
           *
           * #if (   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE  )
           * if (   _ISR_Nest_level == 0  )
           * switch to software interrupt stack
           * #endif
           *
           * _ISR_Nest_level++;
           *
           * _Thread_Dispatch_disable_level++;
           *
           * (  *_ISR_Vector_table[ vector ] )(   vector  );
           *
           * _Thread_Dispatch_disable_level--;
           *
           * --_ISR_Nest_level;
           *
           * if (   _ISR_Nest_level  )
           * goto the label "exit interrupt (  simple case )"
           *
           * if (   _Thread_Dispatch_disable_level  )
           * goto the label "exit interrupt (  simple case )"
           *
           * if (   _Thread_Dispatch_necessary  ) {
           * call _Thread_Dispatch(   ) or prepare to return to _ISR_Dispatch
           * prepare to get out of interrupt
           * return from interrupt (  maybe to _ISR_Dispatch )
           *
           * LABEL "exit interrupt (  simple case ):
           * #if (   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE  )
           * if outermost interrupt
           * restore stack
           * #endif
           * prepare to get out of interrupt
           * return from interrupt
           */
          }

score/cpu/m68k/cpu.c

       1  /*
           * Motorola MC68xxx Dependent Source
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.35 2010/03/27 15:02:07 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          
          #if defined(   __mcoldfire__  ) && (   M68K_HAS_FPU == 1  )
           uint32_t _CPU_cacr_shadow;
          #endif
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           *
           * OUTPUT PARAMETERS: NONE
           */
          
      34  void _CPU_Initialize(  void )
          {
          #if (   M68K_HAS_VBR == 0  )
           /* fill the isr redirect table with the code to place the format/id
           onto the stack */
          
           uint32_t slot;
          
           for (  slot = 0; slot < CPU_INTERRUPT_NUMBER_OF_VECTORS; slot++ )
           {
           _CPU_ISR_jump_table[slot].move_a7 = M68K_MOVE_A7;
           _CPU_ISR_jump_table[slot].format_id = slot << 2;
           _CPU_ISR_jump_table[slot].jmp = M68K_JMP;
           _CPU_ISR_jump_table[slot].isr_handler = (  uint32_t ) 0xDEADDEAD;
           }
          #endif /* M68K_HAS_VBR */
          }
          
          /*PAGE
           *
           * _CPU_ISR_Get_level
           */
          
      57  uint32_t _CPU_ISR_Get_level(   void  )
          {
           uint32_t level;
          
           m68k_get_interrupt_level(   level  );
          
           return level;
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           */
          
      71  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           proc_ptr *interrupt_table = NULL;
          
          #if (  M68K_HAS_FPSP_PACKAGE == 1 )
           /*
           * If this vector being installed is one related to FP,   then the
           * FPSP will install the handler itself and handle it completely
           * with no intervention from RTEMS.
           */
          
           if (  *_FPSP_install_raw_handler &&
           (  *_FPSP_install_raw_handler )(  vector,   new_handler,   *old_handler ) )
           return;
          #endif
          
          
           /*
           * On CPU models without a VBR,   it is necessary for there to be some
           * header code for each ISR which saves a register,   loads the vector
           * number,   and jumps to _ISR_Handler.
           */
          
           m68k_get_vbr(   interrupt_table  );
          #if (   M68K_HAS_VBR == 1  )
           *old_handler = interrupt_table[ vector ];
           interrupt_table[ vector ] = new_handler;
          #else
          
           /*
           * Install handler into RTEMS jump table and if VBR table is in
           * RAM,   install the pointer to the appropriate jump table slot.
           * If the VBR table is in ROM,   it is the BSP's responsibility to
           * load it appropriately to vector to the RTEMS jump table.
           */
          
           *old_handler = (  proc_ptr ) _CPU_ISR_jump_table[vector].isr_handler;
           _CPU_ISR_jump_table[vector].isr_handler = (  uint32_t ) new_handler;
           if (   (  uint32_t ) interrupt_table != 0xFFFFFFFF  )
           interrupt_table[ vector ] = (  proc_ptr ) &_CPU_ISR_jump_table[vector];
          #endif /* M68K_HAS_VBR */
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * new_handler - replacement ISR for this vector number
           * old_handler - former ISR for this vector number
           *
           * Output parameters: NONE
           */
          
     133  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           proc_ptr ignored = 0; /* to avoid warning */
          
           *old_handler = _ISR_Vector_table[ vector ];
          
           _CPU_ISR_install_raw_handler(   vector,   _ISR_Handler,   &ignored  );
          
           _ISR_Vector_table[ vector ] = new_handler;
          }
          
          
          /*PAGE
           *
           * _CPU_Install_interrupt_stack
           */
          
     154  void _CPU_Install_interrupt_stack(   void  )
          {
          #if (   M68K_HAS_SEPARATE_STACKS == 1  )
           void *isp = _CPU_Interrupt_stack_high;
          
           asm volatile (   "movec %0,  %%isp" : "=r" (  isp ) : "0" (  isp )  );
          #endif
          }
          
          #if (   M68K_HAS_BFFFO != 1  )
          /*
           * Returns table for duplication of the BFFFO instruction (  16 bits only )
           */
          const unsigned char _CPU_m68k_BFFFO_table[256] = {
           8,   7,   6,   6,   5,   5,   5,   5,   4,   4,   4,   4,   4,   4,   4,   4,  
           3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,  
           2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,  
           2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,  
           1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,  
           1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,  
           1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,  
           1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,  
           0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  
           0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  
           0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  
           0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  
           0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  
           0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  
           0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  
           0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
          };
          #endif
          
          /*PAGE
           *
           * The following code context switches the software FPU emulation
           * code provided with GCC.
           */
          
          #if (  CPU_SOFTWARE_FP == TRUE )
          extern Context_Control_fp _fpCCR;
          
     196  void _CPU_Context_save_fp (  Context_Control_fp **fp_context_ptr )
          {
           Context_Control_fp *fp;
          
           fp = *fp_context_ptr;
          
           *fp = _fpCCR;
          }
          
     205  void _CPU_Context_restore_fp (  Context_Control_fp **fp_context_ptr )
          {
           Context_Control_fp *fp;
          
           fp = *fp_context_ptr;
          
           _fpCCR = *fp;
          }
          #endif

score/cpu/mips/cpu.c

       1  /*
           * Mips CPU Dependent Source
           *
           * 2002: Greg Menke (  gregory.menke@gsfc.nasa.gov )
           * Overhauled interrupt level and interrupt enable/disable code
           * to more exactly support MIPS. Our mods were for MIPS1 processors
           * MIPS3 ports are affected,   though apps written to the old behavior
           * should still work OK.
           *
           * Conversion to MIPS port by Alan Cudmore <alanc@linuxstart.com> and
           * Joel Sherrill <joel@OARcorp.com>.
           *
           * These changes made the code conditional on standard cpp predefines,  
           * merged the mips1 and mips3 code sequences as much as possible,  
           * and moved some of the assembly code to C. Alan did much of the
           * initial analysis and rework. Joel took over from there and
           * wrote the JMR3904 BSP so this could be tested. Joel also
           * added the new interrupt vectoring support in libcpu and
           * tried to better support the various interrupt controllers.
           *
           * Original MIP64ORION port by Craig Lebakken <craigl@transition.com>
           * COPYRIGHT (  c ) 1996 by Transition Networks Inc.
           *
           * To anyone who acknowledges that this file is provided "AS IS"
           * without any express or implied warranty:
           * permission to use,   copy,   modify,   and distribute this file
           * for any purpose is hereby granted without fee,   provided that
           * the above copyright notice and this notice appears in all
           * copies,   and that the name of Transition Networks not be used in
           * advertising or publicity pertaining to distribution of the
           * software without specific,   written prior permission.
           * Transition Networks makes no representations about the
           * suitability of this software for any purpose.
           *
           * COPYRIGHT (  c ) 1989-2001.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.35 2010/04/25 21:37:46 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/wkspace.h>
          
          /*
          ** Exception stack frame pointer used in cpu_asm to pass the exception stack frame
          ** address to the context switch code.
          */
          #if (  __mips == 1 ) || (  __mips == 32 )
          typedef uint32_t ESF_PTR_TYPE;
          #elif (  __mips == 3 )
          typedef uint64_t ESF_PTR_TYPE;
          #else
          #error "unknown MIPS ISA"
          #endif
          
          ESF_PTR_TYPE __exceptionStackFrame = 0;
          
          
          
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * thread_dispatch - address of dispatching routine
           */
          
      77  void _CPU_Initialize(  void )
          {
           /*
           * If there is not an easy way to initialize the FP context
           * during Context_Initialize,   then it is usually easier to
           * save an "uninitialized" FP context here and copy it to
           * the task's during Context_Initialize.
           */
          
          #if CPU_HARDWARE_FP
           /* FP context initialization support goes here */
           _CPU_Null_fp_context.fpcs = 0x1000000; /* Set FS flag in floating point coprocessor
           control register to prevent underflow and
           inexact exceptions */
          #endif
          }
          
          /*PAGE
           *
           * _CPU_ISR_Get_level
           *
           * This routine returns the current interrupt level.
           */
          
     101  uint32_t _CPU_ISR_Get_level(   void  )
          {
           unsigned int sr;
          
           mips_get_sr(  sr );
          
           /* printf(  "current sr=%08X,   ",  sr ); */
          
          #if (  __mips == 3 ) || (  __mips == 32 )
          /* IE bit and shift down hardware ints into bits 1 thru 6 */
           sr = (  sr & SR_IE ) | (  (  sr & mips_interrupt_mask(   ) ) >> 9 );
          
          #elif __mips == 1
          /* IEC bit and shift down hardware ints into bits 1 thru 6 */
           sr = (  sr & SR_IEC ) | (  (  sr & mips_interrupt_mask(   ) ) >> 9 );
          
          #else
          #error "CPU ISR level: unknown MIPS level for SR handling"
          #endif
           return sr;
          }
          
          
     124  void _CPU_ISR_Set_level(   uint32_t new_level  )
          {
           unsigned int sr,   srbits;
          
           /*
           ** mask off the int level bits only so we can
           ** preserve software int settings and FP enable
           ** for this thread. Note we don't force software ints
           ** enabled when changing level,   they were turned on
           ** when this task was created,   but may have been turned
           ** off since,   so we'll just leave them alone.
           */
          
           new_level &= 0xff;
          
           mips_get_sr(  sr );
          
          #if (  __mips == 3 ) || (  __mips == 32 )
           mips_set_sr(   (  sr & ~SR_IE )  ); /* first disable ie bit (  recommended ) */
          
           srbits = sr & ~(  0xfc00 | SR_IE );
          
           sr = srbits | (  (  new_level==0 )? (  mips_interrupt_mask(   ) | SR_IE ): \
           (  (  (  new_level<<9 ) & mips_interrupt_mask(   ) ) | \
           (  (  new_level & 1 )?SR_IE:0 ) ) );
          /*
           if (   (  new_level & SR_EXL ) == (  sr & SR_EXL )  )
           return;
          
           if (   (  new_level & SR_EXL ) == 0  ) {
           sr &= ~SR_EXL; * clear the EXL bit *
           mips_set_sr(  sr );
           } else {
          
           sr |= SR_EXL|SR_IE; * enable exception level *
           mips_set_sr(  sr ); * first disable ie bit (  recommended ) *
           }
          */
          
          #elif __mips == 1
           mips_set_sr(   (  sr & ~SR_IEC )  );
           srbits = sr & ~(  0xfc00 | SR_IEC );
           sr = srbits | (  (  new_level==0 )?0xfc01:(   (  (  new_level<<9 ) & 0xfc00 ) | \
           (  new_level & SR_IEC ) ) );
          #else
          #error "CPU ISR level: unknown MIPS level for SR handling"
          #endif
           mips_set_sr(   sr  );
          }
          
          
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           *
           * Input parameters:
           * vector - interrupt vector number
           * old_handler - former ISR for this vector number
           * new_handler - replacement ISR for this vector number
           *
           * Output parameters: NONE
           *
           */
          
     189  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           /*
           * This is where we install the interrupt handler into the "raw" interrupt
           * table used by the CPU to dispatch interrupt handlers.
           *
           * Because all interrupts are vectored through the same exception handler
           * this is not necessary on thi sport.
           */
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * old_handler - former ISR for this vector number
           * new_handler - replacement ISR for this vector number
           *
           * Output parameters: NONE
           *
           */
          
     220  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           *old_handler = _ISR_Vector_table[ vector ];
          
           /*
           * If the interrupt vector table is a table of pointer to isr entry
           * points,   then we need to install the appropriate RTEMS interrupt
           * handler for this vector number.
           */
          
           _CPU_ISR_install_raw_handler(   vector,   _ISR_Handler,   old_handler  );
          
           /*
           * We put the actual user ISR address in '_ISR_vector_table'. This will
           * be used by the _ISR_Handler so the user gets control.
           */
          
           _ISR_Vector_table[ vector ] = new_handler;
          }
          
          /*PAGE
           *
           * _CPU_Install_interrupt_stack
           */
          
     249  void _CPU_Install_interrupt_stack(   void  )
          {
          /* we don't support this yet */
          }
          
          /*
           * _CPU_Context_Initialize
           *
           * This kernel routine initializes the basic non-FP context area associated
           * with each thread.
           *
           * Input parameters:
           * the_context - pointer to the context area
           * stack_base - address of memory for the SPARC
           * size - size in bytes of the stack area
           * new_level - interrupt level for this context area
           * entry_point - the starting execution point for this this context
           * is_fp - TRUE if this context is associated with an FP thread
           *
           * Output parameters: NONE
           */
     270  void _CPU_Context_Initialize(  
           Context_Control *the_context,  
           uintptr_t *stack_base,  
           uint32_t size,  
           uint32_t new_level,  
           void *entry_point,  
           bool is_fp
           )
          {
           uintptr_t stack_tmp;
           __MIPS_REGISTER_TYPE intlvl = new_level & 0xff;
          
           stack_tmp = (  uintptr_t )stack_base;
           stack_tmp += (  (  size ) - CPU_STACK_ALIGNMENT );
           stack_tmp &= (  __MIPS_REGISTER_TYPE ) ~(  CPU_STACK_ALIGNMENT - 1 );
          
           the_context->sp = (  __MIPS_REGISTER_TYPE ) stack_tmp;
           the_context->fp = (  __MIPS_REGISTER_TYPE ) stack_tmp;
           the_context->ra = (  __MIPS_REGISTER_TYPE ) (  uintptr_t )entry_point;
           the_context->c0_sr =
           (  (  intlvl==0 )? (  mips_interrupt_mask(   ) | 0x300 | _INTON ):
           (   (  (  intlvl<<9 ) & mips_interrupt_mask(   ) ) | 0x300 |
           (  (  intlvl & 1 )?_INTON:0 ) )  ) |
           SR_CU0 | (  (  is_fp )?SR_CU1:0 ) | _EXTRABITS;
          }
          
          
          /*PAGE
           *
           * _CPU_Internal_threads_Idle_thread_body
           *
           * NOTES:
           *
           * 1. This is the same as the regular CPU independent algorithm.
           *
           * 2. If you implement this using a "halt",   "idle",   or "shutdown"
           * instruction,   then don't forget to put it in an infinite loop.
           *
           * 3. Be warned. Some processors with onboard DMA have been known
           * to stop the DMA if the CPU were put in IDLE mode. This might
           * also be a problem with other on-chip peripherals. So use this
           * hook with caution.
           */
          
     314  void *_CPU_Thread_Idle_body(   uintptr_t ignored  )
          {
          #if (  __mips == 3 ) || (  __mips == 32 )
           for(   ; ;  )
           asm volatile(  "wait" ); /* use wait to enter low power mode */
          #elif __mips == 1
           for(   ; ;  )
           ;
          #else
          #error "IDLE: __mips not set to 1 or 3"
          #endif
          }

score/cpu/nios2/cpu.c

       1  /*
           * NIOS2 CPU Dependent Source
           *
           * COPYRIGHT (  c ) 1989-2006
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.12 2010/03/27 15:02:21 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/wkspace.h>
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      33  void _CPU_Initialize(  void )
          {
           /*
           * If there is not an easy way to initialize the FP context
           * during Context_Initialize,   then it is usually easier to
           * save an "uninitialized" FP context here and copy it to
           * the task's during Context_Initialize.
           */
          
           /* FP context initialization support goes here */
          }
          
          /*PAGE
           *
           * _CPU_ISR_Get_level
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      54  uint32_t _CPU_ISR_Get_level(   void  )
          {
           /*
           * This routine returns the current interrupt level.
           */
          
           return 0;
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      72  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           /*
           * This is where we install the interrupt handler into the "raw" interrupt
           * table used by the CPU to dispatch interrupt handlers.
           */
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * old_handler - former ISR for this vector number
           * new_handler - replacement ISR for this vector number
           *
           * Output parameters: NONE
           *
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     104  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           *old_handler = _ISR_Vector_table[ vector ];
          
           /*
           * If the interrupt vector table is a table of pointer to isr entry
           * points,   then we need to install the appropriate RTEMS interrupt
           * handler for this vector number.
           */
          
           _CPU_ISR_install_raw_handler(   vector,   new_handler,   old_handler  );
          
           /*
           * We put the actual user ISR address in '_ISR_vector_table'. This will
           * be used by the _ISR_Handler so the user gets control.
           */
          
           _ISR_Vector_table[ vector ] = new_handler;
          }
          
          /*PAGE
           *
           * _CPU_Install_interrupt_stack
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     137  void _CPU_Install_interrupt_stack(   void  )
          {
          }
          
          /*PAGE
           *
           * _CPU_Thread_Idle_body
           *
           * NOTES:
           *
           * 1. This is the same as the regular CPU independent algorithm.
           *
           * 2. If you implement this using a "halt",   "idle",   or "shutdown"
           * instruction,   then don't forget to put it in an infinite loop.
           *
           * 3. Be warned. Some processors with onboard DMA have been known
           * to stop the DMA if the CPU were put in IDLE mode. This might
           * also be a problem with other on-chip peripherals. So use this
           * hook with caution.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     162  void *_CPU_Thread_Idle_body(   uintptr_t ignored  )
          {
          #if 1
           for(  ;; );
          #else
           for(  ;; )
           {
           uint32_t st = __builtin_rdctl(  0 ); /* read status register */
          
           /* Differentiate between IRQ off and on (  for debugging ) */
           if(  st & 1 )
           for(  ;; );
           else
           for(  ;; );
          
           /* insert your "halt" instruction here */ ;
           }
          #endif
          }

score/cpu/nios2/irq.c

       1  /*
           * NIOS2 exception and interrupt handler
           *
           * Derived from c4x/irq.c
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: irq.c,  v 1.7 2010/07/30 18:52:14 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/cpu.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          
          /*
           * This routine provides the RTEMS interrupt management.
           *
           * Upon entry,   interrupts are disabled
           */
          
          #if(   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
           unsigned long *_old_stack_ptr;
          #endif
          
      35  register unsigned long *stack_ptr asm(  "sp" );
          
      37  void __ISR_Handler(  uint32_t vector,   CPU_Interrupt_frame *ifr )
          {
           register uint32_t level;
          
           /* Interrupts are disabled upon entry to this Handler */
          
          #if(   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
           if (   _ISR_Nest_level == 0  ) {
           /* Install irq stack */
           _old_stack_ptr = stack_ptr;
           stack_ptr = _CPU_Interrupt_stack_high - 4;
           }
          #endif
          
           _ISR_Nest_level++;
          
           _Thread_Dispatch_disable_level++;
          
           if (   _ISR_Vector_table[ vector]  )
           {
           (  *_ISR_Vector_table[ vector ] )(  vector,   ifr );
           };
          
           /* Make sure that interrupts are disabled again */
           _CPU_ISR_Disable(   level  );
          
           _Thread_Dispatch_disable_level--;
          
           _ISR_Nest_level--;
          
           if(   _ISR_Nest_level == 0 ) {
          #if(   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
           stack_ptr = _old_stack_ptr;
          #endif
          
           if(   _Thread_Dispatch_disable_level == 0  )
           {
           if (   _Thread_Dispatch_necessary  ) {
           _CPU_ISR_Enable(   level  );
           _Thread_Dispatch(   );
           /* may have switched to another task and not return here immed. */
           _CPU_ISR_Disable(   level  ); /* Keep _pairs_ of Enable/Disable */
           }
           }
           }
          
           _CPU_ISR_Enable(   level  );
          }
          
      86  void __Exception_Handler(  CPU_Exception_frame *efr )
          {
           _CPU_Fatal_halt(  0xECC0 );
          }
          
          

score/cpu/no_cpu/cpu.c

       1  /*
           * XXX CPU Dependent Source
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.24 2010/03/27 15:02:26 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/wkspace.h>
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      34  void _CPU_Initialize(  void )
          {
           /*
           * If there is not an easy way to initialize the FP context
           * during Context_Initialize,   then it is usually easier to
           * save an "uninitialized" FP context here and copy it to
           * the task's during Context_Initialize.
           */
          
           /* FP context initialization support goes here */
          }
          
          /*PAGE
           *
           * _CPU_ISR_Get_level
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      55  uint32_t _CPU_ISR_Get_level(   void  )
          {
           /*
           * This routine returns the current interrupt level.
           */
          
           return 0;
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      73  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           /*
           * This is where we install the interrupt handler into the "raw" interrupt
           * table used by the CPU to dispatch interrupt handlers.
           */
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * old_handler - former ISR for this vector number
           * new_handler - replacement ISR for this vector number
           *
           * Output parameters: NONE
           *
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     105  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           *old_handler = _ISR_Vector_table[ vector ];
          
           /*
           * If the interrupt vector table is a table of pointer to isr entry
           * points,   then we need to install the appropriate RTEMS interrupt
           * handler for this vector number.
           */
          
           _CPU_ISR_install_raw_handler(   vector,   new_handler,   old_handler  );
          
           /*
           * We put the actual user ISR address in '_ISR_vector_table'. This will
           * be used by the _ISR_Handler so the user gets control.
           */
          
           _ISR_Vector_table[ vector ] = new_handler;
          }
          
          /*PAGE
           *
           * _CPU_Install_interrupt_stack
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     138  void _CPU_Install_interrupt_stack(   void  )
          {
          }
          
          /*PAGE
           *
           * _CPU_Thread_Idle_body
           *
           * NOTES:
           *
           * 1. This is the same as the regular CPU independent algorithm.
           *
           * 2. If you implement this using a "halt",   "idle",   or "shutdown"
           * instruction,   then don't forget to put it in an infinite loop.
           *
           * 3. Be warned. Some processors with onboard DMA have been known
           * to stop the DMA if the CPU were put in IDLE mode. This might
           * also be a problem with other on-chip peripherals. So use this
           * hook with caution.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     163  void *_CPU_Thread_Idle_body(   uintptr_t ignored  )
          {
          
           for(   ; ;  )
           /* insert your "halt" instruction here */ ;
          }

score/cpu/no_cpu/cpu_asm.c

       1  /* cpu_asm.c ===> cpu_asm.S or cpu_asm.s
           *
           * This file contains the basic algorithms for all assembly code used
           * in an specific CPU port of RTEMS. These algorithms must be implemented
           * in assembly language
           *
           * NOTE: This is supposed to be a .S or .s file NOT a C file.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu_asm.c,  v 1.20 2010/07/30 18:52:16 joel Exp $
           */
          
          /*
           * This is supposed to be an assembly file. This means that system.h
           * and cpu.h should not be included in a "real" cpu_asm file. An
           * implementation in assembly should include "cpu_asm.h>
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/cpu.h>
          /* #include "cpu_asm.h> */
          
          /*
           * _CPU_Context_save_fp_context
           *
           * This routine is responsible for saving the FP context
           * at *fp_context_ptr. If the point to load the FP context
           * from is changed then the pointer is modified by this routine.
           *
           * Sometimes a macro implementation of this is in cpu.h which dereferences
           * the ** and a similarly named routine in this file is passed something
           * like a (  Context_Control_fp * ). The general rule on making this decision
           * is to avoid writing assembly language.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      50  void _CPU_Context_save_fp(  
           Context_Control_fp **fp_context_ptr
           )
          {
          }
          
          /*
           * _CPU_Context_restore_fp_context
           *
           * This routine is responsible for restoring the FP context
           * at *fp_context_ptr. If the point to load the FP context
           * from is changed then the pointer is modified by this routine.
           *
           * Sometimes a macro implementation of this is in cpu.h which dereferences
           * the ** and a similarly named routine in this file is passed something
           * like a (  Context_Control_fp * ). The general rule on making this decision
           * is to avoid writing assembly language.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      73  void _CPU_Context_restore_fp(  
           Context_Control_fp **fp_context_ptr
           )
          {
          }
          
          /* _CPU_Context_switch
           *
           * This routine performs a normal non-FP context switch.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
      88  void _CPU_Context_switch(  
           Context_Control *run,  
           Context_Control *heir
           )
          {
          }
          
          /*
           * _CPU_Context_restore
           *
           * This routine is generally used only to restart self in an
           * efficient manner. It may simply be a label in _CPU_Context_switch.
           *
           * NOTE: May be unnecessary to reload some registers.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     108  void _CPU_Context_restore(  
           Context_Control *new_context
           )
          {
          }
          
          /* void __ISR_Handler(   )
           *
           * This routine provides the RTEMS interrupt management.
           *
           * NO_CPU Specific Information:
           *
           * XXX document implementation including references if appropriate
           */
          
     123  void _ISR_Handler(  void )
          {
           /*
           * This discussion ignores a lot of the ugly details in a real
           * implementation such as saving enough registers/state to be
           * able to do something real. Keep in mind that the goal is
           * to invoke a user's ISR handler which is written in C and
           * uses a certain set of registers.
           *
           * Also note that the exact order is to a large extent flexible.
           * Hardware will dictate a sequence for a certain subset of
           * _ISR_Handler while requirements for setting
           */
          
           /*
           * At entry to "common" _ISR_Handler,   the vector number must be
           * available. On some CPUs the hardware puts either the vector
           * number or the offset into the vector table for this ISR in a
           * known place. If the hardware does not give us this information,  
           * then the assembly portion of RTEMS for this port will contain
           * a set of distinct interrupt entry points which somehow place
           * the vector number in a known place (  which is safe if another
           * interrupt nests this one ) and branches to _ISR_Handler.
           *
           * save some or all context on stack
           * may need to save some special interrupt information for exit
           *
           * #if (   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE  )
           * if (   _ISR_Nest_level == 0  )
           * switch to software interrupt stack
           * #endif
           *
           * _ISR_Nest_level++;
           *
           * _Thread_Dispatch_disable_level++;
           *
           * (  *_ISR_Vector_table[ vector ] )(   vector  );
           *
           * _Thread_Dispatch_disable_level--;
           *
           * --_ISR_Nest_level;
           *
           * if (   _ISR_Nest_level  )
           * goto the label "exit interrupt (  simple case )"
           *
           * if (   _Thread_Dispatch_disable_level  )
           * goto the label "exit interrupt (  simple case )"
           *
           * if (   _Thread_Dispatch_necessary  ) {
           * call _Thread_Dispatch(   ) or prepare to return to _ISR_Dispatch
           * prepare to get out of interrupt
           * return from interrupt (  maybe to _ISR_Dispatch )
           *
           * LABEL "exit interrupt (  simple case ):
           * #if (   CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE  )
           * if outermost interrupt
           * restore stack
           * #endif
           * prepare to get out of interrupt
           * return from interrupt
           */
          }

score/cpu/powerpc/cpu.c

       1  /*
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.2 2010/03/27 15:02:31 joel Exp $
           */
          
          /*
           * For now,   this file is just a stub to work around
           * structural deficiencies of the powerpc port.
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          

score/cpu/sh/context.c

       1  /*
           * Authors: Ralf Corsepius (  corsepiu@faw.uni-ulm.de ) and
           * Bernd Becker (  becker@faw.uni-ulm.de )
           *
           * COPYRIGHT (  c ) 1997-1998,   FAW Ulm,   Germany
           *
           * This program 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.
           *
           * COPYRIGHT (  c ) 1998.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: context.c,  v 1.2 2010/03/27 15:02:35 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/cpu.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/sh.h>
          
          /*
           * _CPU_Context_save_fp_context
           *
           * This routine is responsible for saving the FP context
           * at *fp_context_ptr. If the point to load the FP context
           * from is changed then the pointer is modified by this routine.
           *
           * Sometimes a macro implementation of this is in cpu.h which dereferences
           * the ** and a similarly named routine in this file is passed something
           * like a (  Context_Control_fp * ). The general rule on making this decision
           * is to avoid writing assembly language.
           */
          
      44  void _CPU_Context_save_fp(  
           Context_Control_fp **fp_context_ptr
           )
          {
          #if SH_HAS_FPU
          
          asm volatile(  "\n\
           mov.l @%0,  r4 \n\
           add %1,  r4\n\
           sts.l fpscr,  @-r4\n\
           sts.l fpul,  @-r4\n\
           lds %2,  fpscr\n\
           fmov dr14,  @-r4\n\
           fmov dr12,  @-r4\n\
           fmov dr10,  @-r4\n\
           fmov dr8,  @-r4\n\
           fmov dr6,  @-r4\n\
           fmov dr4,  @-r4\n\
           fmov dr2,  @-r4\n\
           fmov dr0,  @-r4\n\
           "
          #ifdef SH4_USE_X_REGISTERS
           "\
           lds %3,  fpscr\n\
           fmov xd14,  @-r4\n\
           fmov xd12,  @-r4\n\
           fmov xd10,  @-r4\n\
           fmov xd8,  @-r4\n\
           fmov xd6,  @-r4\n\
           fmov xd4,  @-r4\n\
           fmov xd2,  @-r4\n\
           fmov xd0,  @-r4\n\
           "
          #endif
           "lds %4,  fpscr\n\
           "
           :
           : "r"(  fp_context_ptr ),   "r"(  sizeof(  Context_Control_fp ) ),  
           "r"(  SH4_FPSCR_SZ ),   "r"(  SH4_FPSCR_PR | SH4_FPSCR_SZ ),   "r"(  SH4_FPSCR_PR )
           : "r4",   "r0" );
          
          #endif
          
          }
          
          /*
           * _CPU_Context_restore_fp_context
           *
           * This routine is responsible for restoring the FP context
           * at *fp_context_ptr. If the point to load the FP context
           * from is changed then the pointer is modified by this routine.
           *
           * Sometimes a macro implementation of this is in cpu.h which dereferences
           * the ** and a similarly named routine in this file is passed something
           * like a (  Context_Control_fp * ). The general rule on making this decision
           * is to avoid writing assembly language.
           */
          
     102  void _CPU_Context_restore_fp(  
           Context_Control_fp **fp_context_ptr
           )
          {
          
          #if SH_HAS_FPU
          
          asm volatile(  "\n\
           mov.l @%0,  r4 \n\
           "
          #ifdef SH4_USE_X_REGISTERS
           "\n\
           lds %1,  fpscr\n\
           fmov @r4+,  xd0\n\
           fmov @r4+,  xd2\n\
           fmov @r4+,  xd4\n\
           fmov @r4+,  xd6\n\
           fmov @r4+,  xd8\n\
           fmov @r4+,  xd10\n\
           fmov @r4+,  xd12\n\
           fmov @r4+,  xd14\n\
           "
          #endif
           "\n\
           lds %2,  fpscr\n\
           fmov @r4+,  dr0\n\
           fmov @r4+,  dr2\n\
           fmov @r4+,  dr4\n\
           fmov @r4+,  dr6\n\
           fmov @r4+,  dr8\n\
           fmov @r4+,  dr10\n\
           fmov @r4+,  dr12\n\
           fmov @r4+,  dr14\n\
           lds.l @r4+,  fpul\n\
           lds.l @r4+,  fpscr\n\
           " :
           : "r"(  fp_context_ptr ),   "r"(  SH4_FPSCR_PR | SH4_FPSCR_SZ ),   "r"(  SH4_FPSCR_SZ )
           : "r4",   "r0" );
          #endif
          }
          
          /* _CPU_Context_switch
           *
           * This routine performs a normal non-FP context switch.
           */
          
          /* within __CPU_Context_switch:
           * _CPU_Context_switch
           * _CPU_Context_restore
           *
           * This routine is generally used only to restart self in an
           * efficient manner. It may simply be a label in _CPU_Context_switch.
           *
           * NOTE: It should be safe not to store r4,   r5
           *
           * NOTE: It is doubtful if r0 is really needed to be stored
           *
           * NOTE: gbr is added,   but should not be necessary,   as it is
           * only used globally in this port.
           */
          
          /*
           * FIXME: This is an ugly hack,   but we wanted to avoid recalculating
           * the offset each time Context_Control is changed
           */
     167  void __CPU_Context_switch(  
           Context_Control *run,   /* r4 */
           Context_Control *heir /* r5 */
           )
          {
          
          asm volatile(  "\n\
           .global __CPU_Context_switch\n\
          __CPU_Context_switch:\n\
          \n\
           add %0,  r4\n\
           \n\
           stc.l sr,  @-r4\n\
           stc.l gbr,  @-r4\n\
           mov.l r0,  @-r4\n\
           mov.l r1,  @-r4\n\
           mov.l r2,  @-r4\n\
           mov.l r3,  @-r4\n\
          \n\
           mov.l r6,  @-r4\n\
           mov.l r7,  @-r4\n\
           mov.l r8,  @-r4\n\
           mov.l r9,  @-r4\n\
           mov.l r10,  @-r4\n\
           mov.l r11,  @-r4\n\
           mov.l r12,  @-r4\n\
           mov.l r13,  @-r4\n\
           mov.l r14,  @-r4\n\
           sts.l pr,  @-r4\n\
           sts.l mach,  @-r4\n\
           sts.l macl,  @-r4\n\
           mov.l r15,  @-r4\n\
          \n\
           mov r5,   r4"
           :: "i" (  sizeof(  Context_Control ) )
            );
          
           asm volatile(  "\n\
           .global __CPU_Context_restore\n\
          __CPU_Context_restore:\n\
           mov.l @r4+,  r15\n\
           lds.l @r4+,  macl\n\
           lds.l @r4+,  mach\n\
           lds.l @r4+,  pr\n\
           mov.l @r4+,  r14\n\
           mov.l @r4+,  r13\n\
           mov.l @r4+,  r12\n\
           mov.l @r4+,  r11\n\
           mov.l @r4+,  r10\n\
           mov.l @r4+,  r9\n\
           mov.l @r4+,  r8\n\
           mov.l @r4+,  r7\n\
           mov.l @r4+,  r6\n\
          \n\
           mov.l @r4+,  r3\n\
           mov.l @r4+,  r2\n\
           mov.l @r4+,  r1\n\
           mov.l @r4+,  r0\n\
           ldc.l @r4+,  gbr\n\
           ldc.l @r4+,  sr\n\
          \n\
           rts\n\
           nop"  );
          }

score/cpu/sh/cpu.c

       1  /*
           * This file contains information pertaining to the Hitachi SH
           * processor.
           *
           * Authors: Ralf Corsepius (  corsepiu@faw.uni-ulm.de ) and
           * Bernd Becker (  becker@faw.uni-ulm.de )
           *
           * COPYRIGHT (  c ) 1997-1998,   FAW Ulm,   Germany
           *
           * This program 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.
           *
           *
           * COPYRIGHT (  c ) 1998-2001.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.21 2010/05/23 05:47:27 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/sh_io.h>
          #include <rtems/score/cpu.h>
          #include <rtems/score/sh.h>
          
          /* referenced in start.S */
          extern proc_ptr vectab[] ;
          
          proc_ptr vectab[256] ;
          
          extern proc_ptr _Hardware_isr_Table[];
          
          /* _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           */
          
      49  void _CPU_Initialize(  void )
          {
           register uint32_t level = 0;
          
           /*
           * If there is not an easy way to initialize the FP context
           * during Context_Initialize,   then it is usually easier to
           * save an "uninitialized" FP context here and copy it to
           * the task's during Context_Initialize.
           */
          
           /* FP context initialization support goes here */
           /* FIXME: When not to use SH4_FPSCR_PR ? */
          #ifdef __SH4__
           _CPU_Null_fp_context.fpscr = SH4_FPSCR_DN | SH4_FPSCR_RM | SH4_FPSCR_PR;
          #endif
          #ifdef __SH3E__
           /* FIXME: Wild guess : ) */
           _CPU_Null_fp_context.fpscr = SH4_FPSCR_DN | SH4_FPSCR_RM;
          #endif
          
           /* enable interrupts */
           _CPU_ISR_Set_level(   level  ) ;
          }
          
          /*PAGE
           *
           * _CPU_ISR_Get_level
           */
          
      79  uint32_t _CPU_ISR_Get_level(   void  )
          {
           /*
           * This routine returns the current interrupt level.
           */
          
           register uint32_t _mask ;
          
           sh_get_interrupt_level(   _mask  );
          
           return (   _mask );
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           */
          
      97  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           /*
           * This is where we install the interrupt handler into the "raw" interrupt
           * table used by the CPU to dispatch interrupt handlers.
           */
           volatile proc_ptr *vbr ;
          
          #if SH_PARANOID_ISR
           uint32_t level ;
          
           sh_disable_interrupts(   level  );
          #endif
          
           /* get vbr */
           asm (   "stc vbr,  %0" : "=r" (  vbr )  );
          
           *old_handler = vbr[vector] ;
           vbr[vector] = new_handler ;
          
          #if SH_PARANOID_ISR
           sh_enable_interrupts(   level  );
          #endif
          }
          
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * old_handler - former ISR for this vector number
           * new_handler - replacement ISR for this vector number
           *
           * Output parameters: NONE
           *
           */
          
     143  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
          #if defined(  __sh1__ ) || defined(  __sh2__ )
           proc_ptr ignored ;
          #endif
           *old_handler = _ISR_Vector_table[ vector ];
          
           /*
           * If the interrupt vector table is a table of pointer to isr entry
           * points,   then we need to install the appropriate RTEMS interrupt
           * handler for this vector number.
           */
          #if defined(  __sh1__ ) || defined(  __sh2__ )
           _CPU_ISR_install_raw_handler(  vector,   _Hardware_isr_Table[vector],   &ignored  );
          #endif
          
           /*
           * We put the actual user ISR address in '_ISR_Vector_table'.
           * This will be used by __ISR_Handler so the user gets control.
           */
          
           _ISR_Vector_table[ vector ] = new_handler;
          }
          
          /*PAGE
           *
           * _CPU_Thread_Idle_body
           *
           * NOTES:
           *
           * 1. This is the same as the regular CPU independent algorithm.
           *
           * 2. If you implement this using a "halt",   "idle",   or "shutdown"
           * instruction,   then don't forget to put it in an infinite loop.
           *
           * 3. Be warned. Some processors with onboard DMA have been known
           * to stop the DMA if the CPU were put in IDLE mode. This might
           * also be a problem with other on-chip peripherals. So use this
           * hook with caution.
           */
          
          #if (  CPU_PROVIDES_IDLE_THREAD_BODY == TRUE )
     189  void *_CPU_Thread_Idle_body(   uintptr_t ignored  )
          {
          
           for(   ; ;  )
           {
           asm volatile(  "nop" );
           }
           /* insert your "halt" instruction here */ ;
          }
          #endif
          
          #if (  CPU_USE_GENERIC_BITFIELD_CODE == FALSE )
          
          uint8_t _bit_set_table[16] =
           { 4,   4,   4,   4,   4,   4,   4,   4,   3,   3,   3,   3,   2,   2,   1,  0};
          
          
          #endif
          
     208  void _CPU_Context_Initialize(  
           Context_Control *_the_context,  
           void *_stack_base,  
           uint32_t _size,  
           uint32_t _isr,  
           void (  *_entry_point )(  void ),  
           int _is_fp  )
          {
           _the_context->r15 = (  uint32_t * ) (  (  uint32_t ) (  _stack_base ) + (  _size )  );
          #if defined(  __sh1__ ) || defined(  __sh2__ ) || defined(  __SH2E__ )
           _the_context->sr = (  _isr << 4 ) & 0x00f0 ;
          #else
           _the_context->sr = SH4_SR_MD | (  (  _isr << 4 ) & 0x00f0 );
          #endif
           _the_context->pr = (  uint32_t * ) _entry_point ;
          
          
          #if 0 && SH_HAS_FPU
           /* Disable FPU if it is non-fp task */
           if(  !_is_fp )
           _the_context->sr |= SH4_SR_FD;
          #endif
          }

score/cpu/sparc/cpu.c

       1  /*
           * SPARC Dependent Source
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.30 2010/03/27 15:03:09 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/rtems/cache.h>
          
          /*
           * This initializes the set of opcodes placed in each trap
           * table entry. The routine which installs a handler is responsible
           * for filling in the fields for the _handler address and the _vector
           * trap type.
           *
           * The constants following this structure are masks for the fields which
           * must be filled in when the handler is installed.
           */
          
          const CPU_Trap_table_entry _CPU_Trap_slot_template = {
           0xa1480000,   /* mov %psr,   %l0 */
           0x29000000,   /* sethi %hi(  _handler ),   %l4 */
           0x81c52000,   /* jmp %l4 + %lo(  _handler ) */
           0xa6102000 /* mov _vector,   %l3 */
          };
          
          /*PAGE
           *
           * _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           *
           * Output Parameters: NONE
           *
           * NOTE: There is no need to save the pointer to the thread dispatch routine.
           * The SPARC's assembly code can reference it directly with no problems.
           */
          
      53  void _CPU_Initialize(  void )
          {
          #if (  SPARC_HAS_FPU == 1 )
           Context_Control_fp *pointer;
          
           /*
           * This seems to be the most appropriate way to obtain an initial
           * FP context on the SPARC. The NULL fp context is copied it to
           * the task's FP context during Context_Initialize.
           */
          
           pointer = &_CPU_Null_fp_context;
           _CPU_Context_save_fp(   &pointer  );
          #endif
          
           /*
           * Since no tasks have been created yet and no interrupts have occurred,  
           * there is no way that the currently executing thread can have an
           * _ISR_Dispatch stack frame on its stack.
           */
           _CPU_ISR_Dispatch_disable = 0;
          }
          
          /*PAGE
           *
           * _CPU_ISR_Get_level
           *
           * Input Parameters: NONE
           *
           * Output Parameters:
           * returns the current interrupt level (  PIL field of the PSR )
           */
          
      86  uint32_t _CPU_ISR_Get_level(   void  )
          {
           uint32_t level;
          
           sparc_get_interrupt_level(   level  );
          
           return level;
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_raw_handler
           *
           * This routine installs the specified handler as a "raw" non-executive
           * supported trap handler (  a.k.a. interrupt service routine ).
           *
           * Input Parameters:
           * vector - trap table entry number plus synchronous
           * vs. asynchronous information
           * new_handler - address of the handler to be installed
           * old_handler - pointer to an address of the handler previously installed
           *
           * Output Parameters: NONE
           * *new_handler - address of the handler previously installed
           *
           * NOTE:
           *
           * On the SPARC,   there are really only 256 vectors. However,   the executive
           * has no easy,   fast,   reliable way to determine which traps are synchronous
           * and which are asynchronous. By default,   synchronous traps return to the
           * instruction which caused the interrupt. So if you install a software
           * trap handler as an executive interrupt handler (  which is desirable since
           * RTEMS takes care of window and register issues ),   then the executive needs
           * to know that the return address is to the trap rather than the instruction
           * following the trap.
           *
           * So vectors 0 through 255 are treated as regular asynchronous traps which
           * provide the "correct" return address. Vectors 256 through 512 are assumed
           * by the executive to be synchronous and to require that the return address
           * be fudged.
           *
           * If you use this mechanism to install a trap handler which must reexecute
           * the instruction which caused the trap,   then it should be installed as
           * an asynchronous trap. This will avoid the executive changing the return
           * address.
           */
          
     133  void _CPU_ISR_install_raw_handler(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           uint32_t real_vector;
           CPU_Trap_table_entry *tbr;
           CPU_Trap_table_entry *slot;
           uint32_t u32_tbr;
           uint32_t u32_handler;
          
           /*
           * Get the "real" trap number for this vector ignoring the synchronous
           * versus asynchronous indicator included with our vector numbers.
           */
          
           real_vector = SPARC_REAL_TRAP_NUMBER(   vector  );
          
           /*
           * Get the current base address of the trap table and calculate a pointer
           * to the slot we are interested in.
           */
          
           sparc_get_tbr(   u32_tbr  );
          
           u32_tbr &= 0xfffff000;
          
           tbr = (  CPU_Trap_table_entry * ) u32_tbr;
          
           slot = &tbr[ real_vector ];
          
           /*
           * Get the address of the old_handler from the trap table.
           *
           * NOTE: The old_handler returned will be bogus if it does not follow
           * the RTEMS model.
           */
          
          #define HIGH_BITS_MASK 0xFFFFFC00
          #define HIGH_BITS_SHIFT 10
          #define LOW_BITS_MASK 0x000003FF
          
           if (   slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0  ) {
           u32_handler =
           (  slot->sethi_of_handler_to_l4 << HIGH_BITS_SHIFT ) |
           (  slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK );
           *old_handler = (  proc_ptr ) u32_handler;
           } else
           *old_handler = 0;
          
           /*
           * Copy the template to the slot and then fix it.
           */
          
           *slot = _CPU_Trap_slot_template;
          
           u32_handler = (  uint32_t ) new_handler;
          
           slot->mov_vector_l3 |= vector;
           slot->sethi_of_handler_to_l4 |=
           (  u32_handler & HIGH_BITS_MASK ) >> HIGH_BITS_SHIFT;
           slot->jmp_to_low_of_handler_plus_l4 |= (  u32_handler & LOW_BITS_MASK );
          
           /* need to flush icache after this !!! */
          
           rtems_cache_invalidate_entire_instruction(   );
          
          }
          
          /*PAGE
           *
           * _CPU_ISR_install_vector
           *
           * This kernel routine installs the RTEMS handler for the
           * specified vector.
           *
           * Input parameters:
           * vector - interrupt vector number
           * new_handler - replacement ISR for this vector number
           * old_handler - pointer to former ISR for this vector number
           *
           * Output parameters:
           * *old_handler - former ISR for this vector number
           *
           */
          
     220  void _CPU_ISR_install_vector(  
           uint32_t vector,  
           proc_ptr new_handler,  
           proc_ptr *old_handler
           )
          {
           uint32_t real_vector;
           proc_ptr ignored;
          
           /*
           * Get the "real" trap number for this vector ignoring the synchronous
           * versus asynchronous indicator included with our vector numbers.
           */
          
           real_vector = SPARC_REAL_TRAP_NUMBER(   vector  );
          
           /*
           * Return the previous ISR handler.
           */
          
           *old_handler = _ISR_Vector_table[ real_vector ];
          
           /*
           * Install the wrapper so this ISR can be invoked properly.
           */
          
           _CPU_ISR_install_raw_handler(   vector,   _ISR_Handler,   &ignored  );
          
           /*
           * We put the actual user ISR address in '_ISR_vector_table'. This will
           * be used by the _ISR_Handler so the user gets control.
           */
          
           _ISR_Vector_table[ real_vector ] = new_handler;
          }
          
          /*PAGE
           *
           * _CPU_Context_Initialize
           *
           * This kernel routine initializes the basic non-FP context area associated
           * with each thread.
           *
           * Input parameters:
           * the_context - pointer to the context area
           * stack_base - address of memory for the SPARC
           * size - size in bytes of the stack area
           * new_level - interrupt level for this context area
           * entry_point - the starting execution point for this this context
           * is_fp - TRUE if this context is associated with an FP thread
           *
           * Output parameters: NONE
           */
          
     274  void _CPU_Context_Initialize(  
           Context_Control *the_context,  
           uint32_t *stack_base,  
           uint32_t size,  
           uint32_t new_level,  
           void *entry_point,  
           bool is_fp
           )
          {
           uint32_t stack_high; /* highest "stack aligned" address */
           uint32_t the_size;
           uint32_t tmp_psr;
          
           /*
           * On CPUs with stacks which grow down (  i.e. SPARC ),   we build the stack
           * based on the stack_high address.
           */
          
           stack_high = (  (  uint32_t )(  stack_base ) + size );
           stack_high &= ~(  CPU_STACK_ALIGNMENT - 1 );
          
           the_size = size & ~(  CPU_STACK_ALIGNMENT - 1 );
          
           /*
           * See the README in this directory for a diagram of the stack.
           */
          
           the_context->o7 = (  (  uint32_t ) entry_point ) - 8;
           the_context->o6_sp = stack_high - CPU_MINIMUM_STACK_FRAME_SIZE;
           the_context->i6_fp = 0;
          
           /*
           * Build the PSR for the task. Most everything can be 0 and the
           * CWP is corrected during the context switch.
           *
           * The EF bit determines if the floating point unit is available.
           * The FPU is ONLY enabled if the context is associated with an FP task
           * and this SPARC model has an FPU.
           */
          
           sparc_get_psr(   tmp_psr  );
           tmp_psr &= ~SPARC_PSR_PIL_MASK;
           tmp_psr |= (  new_level << 8 ) & SPARC_PSR_PIL_MASK;
           tmp_psr &= ~SPARC_PSR_EF_MASK; /* disabled by default */
          
          #if (  SPARC_HAS_FPU == 1 )
           /*
           * If this bit is not set,   then a task gets a fault when it accesses
           * a floating point register. This is a nice way to detect floating
           * point tasks which are not currently declared as such.
           */
          
           if (   is_fp  )
           tmp_psr |= SPARC_PSR_EF_MASK;
          #endif
           the_context->psr = tmp_psr;
          
           /*
           * Since THIS thread is being created,   there is no way that THIS
           * thread can have an _ISR_Dispatch stack frame on its stack.
           */
           the_context->isr_dispatch_disable = 0;
          }

score/cpu/sparc64/cpu.c

       1  /*
           * SPARC-v9 Dependent Source
           *
           * COPYRIGHT (  c ) 1989-2007.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * This file is based on the SPARC cpu.c file. Modifications are made to
           * provide support for the SPARC-v9.
           * COPYRIGHT (  c ) 2010. Gedare Bloom.
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: cpu.c,  v 1.1 2010/06/15 22:43:56 joel Exp $
           */
          
          #include <rtems/system.h>
          #include <rtems/asm.h>
          #include <rtems/score/isr.h>
          #include <rtems/rtems/cache.h>
          
          /*PAGE
           *
           * _CPU_Initialize
           *
           * This routine performs processor dependent initialization.
           *
           * INPUT PARAMETERS: NONE
           *
           * Output Parameters: NONE
           *
           * NOTE: There is no need to save the pointer to the thread dispatch routine.
           * The SPARC's assembly code can reference it directly with no problems.
           */
          
      37  void _CPU_Initialize(  void )
          {
          #if (  SPARC_HAS_FPU == 1 )
           Context_Control_fp *pointer;
          
           /*
           * This seems to be the most appropriate way to obtain an initial
           * FP context on the SPARC. The NULL fp context is copied in to
           * the task's FP context during Context_Initialize_fp.
           */
          
           pointer = &_CPU_Null_fp_context;
           _CPU_Context_save_fp(   &pointer  );
          
          #endif
          
           /*
           * Since no tasks have been created yet and no interrupts have occurred,  
           * there is no way that the currently executing thread can have an
           * _ISR_Dispatch stack frame on its stack.
           */
           _CPU_ISR_Dispatch_disable = 0;
          }
          
          /*PAGE
           *
           * _CPU_Context_Initialize
           *
           * This kernel routine initializes the basic non-FP context area associated
           * with each thread.
           *
           * Input parameters:
           * the_context - pointer to the context area
           * stack_base - address of memory for the SPARC
           * size - size in bytes of the stack area
           * new_level - interrupt level for this context area
           * entry_point - the starting execution point for this this context
           * is_fp - TRUE if this context is associated with an FP thread
           *
           * Output parameters: NONE
           */
          
      79  void _CPU_Context_Initialize(  
           Context_Control *the_context,  
           void *stack_base,  
           uint32_t size,  
           uint32_t new_level,  
           void *entry_point,  
           bool is_fp
           )
          {
           uint64_t stack_high; /* highest "stack aligned" address */
           uint32_t the_size;
          
           /*
           * On CPUs with stacks which grow down (  i.e. SPARC ),   we build the stack
           * based on the stack_high address.
           */
          
           stack_high = (  (  uint64_t )(  stack_base ) + size );
           stack_high &= ~(  CPU_STACK_ALIGNMENT - 1 );
          
           the_size = size & ~(  CPU_STACK_ALIGNMENT - 1 );
          
           /*
           * See the README in this directory for a diagram of the stack.
           */
          
           the_context->o7 = (  (  uint64_t ) entry_point ) - 8;
           the_context->o6_sp = stack_high - CPU_MINIMUM_STACK_FRAME_SIZE - STACK_BIAS;
           the_context->i6_fp = 0;
          
           /* PSTATE used to be built here,   but is no longer included in context */
          
           /*
           * Since THIS thread is being created,   there is no way that THIS
           * thread can have an _ISR_Dispatch stack frame on its stack.
           */
           the_context->isr_dispatch_disable = 0;
          }

score/src/apiext.c

       1  /* apiext.c
           *
           * XXX
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: apiext.c,  v 1.15 2010/06/18 03:59:55 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          
          /*PAGE
           *
           * _API_extensions_Initialization
           */
          
      27  void _API_extensions_Initialization(   void  )
          {
           _Chain_Initialize_empty(   &_API_extensions_List  );
          }
          
          /*PAGE
           *
           * _API_extensions_Add
           */
          
      37  void _API_extensions_Add(  
           API_extensions_Control *the_extension
           )
          {
           _Chain_Append(   &_API_extensions_List,   &the_extension->Node  );
          }
          
          #if defined(  FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API )
           /*PAGE
           *
           * _API_extensions_Run_predriver
           */
          
      50   void _API_extensions_Run_predriver(   void  )
           {
           Chain_Node *the_node;
           API_extensions_Control *the_extension;
          
           for (   the_node = _API_extensions_List.first ;
           !_Chain_Is_tail(   &_API_extensions_List,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_extension = (  API_extensions_Control * ) the_node;
          
           if (   the_extension->predriver_hook  )
           (  *the_extension->predriver_hook )(   );
           }
           }
          #endif
          
          /*PAGE
           *
           * _API_extensions_Run_postdriver
           */
          
      72  void _API_extensions_Run_postdriver(   void  )
          {
           Chain_Node *the_node;
           API_extensions_Control *the_extension;
          
           for (   the_node = _API_extensions_List.first ;
           !_Chain_Is_tail(   &_API_extensions_List,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_extension = (  API_extensions_Control * ) the_node;
          
           /*
           * Currently all APIs configure this hook so it is always non-NULL.
           */
          #if defined(  FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API )
           if (   the_extension->postdriver_hook  )
          #endif
           (  *the_extension->postdriver_hook )(   );
           }
          }
          
          /*PAGE
           *
           * _API_extensions_Run_postswitch
           */
          
      98  void _API_extensions_Run_postswitch(   void  )
          {
           Chain_Node *the_node;
           API_extensions_Control *the_extension;
          
           for (   the_node = _API_extensions_List.first ;
           !_Chain_Is_tail(   &_API_extensions_List,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_extension = (  API_extensions_Control * ) the_node;
          
           (  *the_extension->postswitch_hook )(   _Thread_Executing  );
           }
          }
          
          /* end of file */

score/src/apimutex.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: apimutex.c,  v 1.2 2008/12/22 05:52:31 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apimutex.h>
          
      19  void _API_Mutex_Initialization(  
           uint32_t maximum_mutexes
           )
          {
           _Objects_Initialize_information(  
           &_API_Mutex_Information,   /* object information table */
           OBJECTS_INTERNAL_API,   /* object API */
           OBJECTS_INTERNAL_MUTEXES,   /* object class */
           maximum_mutexes,   /* maximum objects of this class */
           sizeof(   API_Mutex_Control  ),   /* size of this object's control block */
           false,   /* true if the name is a string */
           0 /* maximum length of an object name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           true,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          }

score/src/apimutexallocate.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: apimutexallocate.c,  v 1.4 2008/12/22 05:52:31 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apimutex.h>
          
      19  void _API_Mutex_Allocate(  
           API_Mutex_Control **the_mutex
           )
          {
           API_Mutex_Control *mutex;
          
           CORE_mutex_Attributes attr = {
           CORE_MUTEX_NESTING_IS_ERROR,  
           false,  
           CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT,  
           0
           };
          
           mutex = (  API_Mutex_Control * ) _Objects_Allocate(   &_API_Mutex_Information  );
          
           _CORE_mutex_Initialize(   &mutex->Mutex,   &attr,   CORE_MUTEX_UNLOCKED  );
          
           _Objects_Open_u32(   &_API_Mutex_Information,   &mutex->Object,   1  );
          
           *the_mutex = mutex;
          }

score/src/apimutexlock.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: apimutexlock.c,  v 1.4 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apimutex.h>
          
      19  void _API_Mutex_Lock(  
           API_Mutex_Control *the_mutex
           )
          {
           ISR_Level level;
          
           _ISR_Disable(   level  );
          
           _CORE_mutex_Seize(  
           &the_mutex->Mutex,  
           the_mutex->Object.id,  
           true,  
           0,  
           level
            );
          }

score/src/apimutexunlock.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: apimutexunlock.c,  v 1.2 2007/11/09 21:52:09 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apimutex.h>
          
      19  void _API_Mutex_Unlock(  
           API_Mutex_Control *the_mutex
           )
          {
           _Thread_Disable_dispatch(   );
           _CORE_mutex_Surrender(  
           &the_mutex->Mutex,  
           the_mutex->Object.id,  
           NULL
            );
           _Thread_Enable_dispatch(   );
          }

score/src/chain.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: chain.c,  v 1.18 2007/05/09 18:27:26 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          
          /*PAGE
           *
           * _Chain_Initialize
           *
           * This kernel routine initializes a doubly linked chain.
           *
           * Input parameters:
           * the_chain - pointer to chain header
           * starting_address - starting address of first node
           * number_nodes - number of nodes in chain
           * node_size - size of node in bytes
           *
           * Output parameters: NONE
           */
          
      36  void _Chain_Initialize(  
           Chain_Control *the_chain,  
           void *starting_address,  
           size_t number_nodes,  
           size_t node_size
           )
          {
           size_t count;
           Chain_Node *current;
           Chain_Node *next;
          
           count = number_nodes;
           current = _Chain_Head(   the_chain  );
           the_chain->permanent_null = NULL;
           next = starting_address;
           while (   count--  ) {
           current->next = next;
           next->previous = current;
           current = next;
           next = (  Chain_Node * )
           _Addresses_Add_offset(   (  void * ) next,   node_size  );
           }
           current->next = _Chain_Tail(   the_chain  );
           the_chain->last = current;
          }

score/src/chainappend.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: chainappend.c,  v 1.1 2007/05/09 18:27:26 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          
          /*
           * _Chain_Append
           *
           * This kernel routine puts a node on the end of the specified chain.
           *
           * Input parameters:
           * the_chain - pointer to chain header
           * node - address of node to put at rear of chain
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * only case
           */
          
      36  void _Chain_Append(  
           Chain_Control *the_chain,  
           Chain_Node *node
           )
          {
           ISR_Level level;
          
           _ISR_Disable(   level  );
           _Chain_Append_unprotected(   the_chain,   node  );
           _ISR_Enable(   level  );
          }

score/src/chainappendempty.c

       1  /**
           * @file
           *
           * @ingroup ScoreChain
           *
           * @brief _Chain_Append_with_empty_check(   ) implementation.
           */
          
          /*
           * Copyright (  c ) 2010 embedded brains GmbH. All rights reserved.
           *
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * 82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          
      31  bool _Chain_Append_with_empty_check(  
           Chain_Control *chain,  
           Chain_Node *node
           )
          {
           ISR_Level level;
           bool was_empty;
          
           _ISR_Disable(   level  );
           was_empty = _Chain_Append_with_empty_check_unprotected(   chain,   node  );
           _ISR_Enable(   level  );
          
           return was_empty;
          }

score/src/chainextract.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: chainextract.c,  v 1.1 2007/05/09 18:27:26 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          
          /*
           * _Chain_Extract
           *
           * This kernel routine deletes the given node from a chain.
           *
           * Input parameters:
           * node - pointer to node in chain to be deleted
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * only case
           */
          
      35  void _Chain_Extract(  
           Chain_Node *node
           )
          {
           ISR_Level level;
          
           _ISR_Disable(   level  );
           _Chain_Extract_unprotected(   node  );
           _ISR_Enable(   level  );
          }

score/src/chainget.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: chainget.c,  v 1.1 2007/05/09 18:27:26 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          
          /*
           * _Chain_Get
           *
           * This kernel routine returns a pointer to a node taken from the
           * given chain.
           *
           * Input parameters:
           * the_chain - pointer to chain header
           *
           * Output parameters:
           * return_node - pointer to node in chain allocated
           * CHAIN_END - if no nodes available
           *
           * INTERRUPT LATENCY:
           * only case
           */
          
      38  Chain_Node *_Chain_Get(  
           Chain_Control *the_chain
           )
          {
           ISR_Level level;
           Chain_Node *return_node;
          
           return_node = NULL;
           _ISR_Disable(   level  );
           if (   !_Chain_Is_empty(   the_chain  )  )
           return_node = _Chain_Get_first_unprotected(   the_chain  );
           _ISR_Enable(   level  );
           return return_node;
          }

score/src/chaingetempty.c

       1  /**
           * @file
           *
           * @ingroup ScoreChain
           *
           * @brief _Chain_Get_with_empty_check(   ) implementation.
           */
          
          /*
           * Copyright (  c ) 2010 embedded brains GmbH. All rights reserved.
           *
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * 82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          
      31  bool _Chain_Get_with_empty_check(  
           Chain_Control *chain,  
           Chain_Node **node
           )
          {
           ISR_Level level;
           bool is_empty_now;
          
           _ISR_Disable(   level  );
           is_empty_now = _Chain_Get_with_empty_check_unprotected(   chain,   node  );
           _ISR_Enable(   level  );
          
           return is_empty_now;
          }

score/src/chaininsert.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: chaininsert.c,  v 1.1 2007/05/09 18:27:26 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          
          /*
           * _Chain_Insert
           *
           * This kernel routine inserts a given node after a specified node
           * a requested chain.
           *
           * Input parameters:
           * after_node - pointer to node in chain to be inserted after
           * node - pointer to node to be inserted
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * only case
           */
          
      37  void _Chain_Insert(  
           Chain_Node *after_node,  
           Chain_Node *node
           )
          {
           ISR_Level level;
          
           _ISR_Disable(   level  );
           _Chain_Insert_unprotected(   after_node,   node  );
           _ISR_Enable(   level  );
          }

score/src/chainprependempty.c

       1  /**
           * @file
           *
           * @ingroup ScoreChain
           *
           * @brief _Chain_Prepend_with_empty_check(   ) implementation.
           */
          
          /*
           * Copyright (  c ) 2010 embedded brains GmbH. All rights reserved.
           *
           * embedded brains GmbH
           * Obere Lagerstr. 30
           * 82178 Puchheim
           * Germany
           * <rtems@embedded-brains.de>
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          
      31  bool _Chain_Prepend_with_empty_check(  
           Chain_Control *chain,  
           Chain_Node *node
           )
          {
           ISR_Level level;
           bool was_empty;
          
           _ISR_Disable(   level  );
           was_empty = _Chain_Prepend_with_empty_check_unprotected(   chain,   node  );
           _ISR_Enable(   level  );
          
           return was_empty;
          }

score/src/corebarrier.c

       1  /*
           * SuperCore Barrier Handler
           *
           * DESCRIPTION:
           *
           * This package is part of the implementation of the SuperCore Barrier Handler.
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: corebarrier.c,  v 1.2 2008/09/05 21:54:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/corebarrier.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*PAGE
           *
           * _CORE_barrier_Initialize
           *
           * This function initialize a barrier and sets the initial value based
           * on the given count.
           *
           * Input parameters:
           * the_barrier - the barrier control block to initialize
           * the_barrier_attributes - the attributes specified at create time
           *
           * Output parameters: NONE
           */
          
      42  void _CORE_barrier_Initialize(  
           CORE_barrier_Control *the_barrier,  
           CORE_barrier_Attributes *the_barrier_attributes
           )
          {
          
           the_barrier->Attributes = *the_barrier_attributes;
           the_barrier->number_of_waiting_threads = 0;
          
           _Thread_queue_Initialize(  
           &the_barrier->Wait_queue,  
           THREAD_QUEUE_DISCIPLINE_FIFO,  
           STATES_WAITING_FOR_BARRIER,  
           CORE_BARRIER_TIMEOUT
            );
          }

score/src/corebarrierrelease.c

       1  /*
           * SuperCore Barrier Handler
           *
           * DESCRIPTION:
           *
           * This package is part of the implementation of the SuperCore Barrier Handler.
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: corebarrierrelease.c,  v 1.3 2008/12/31 03:21:34 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/corebarrier.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*PAGE
           *
           * _CORE_barrier_Release
           *
           * Input parameters:
           * the_barrier - the barrier to be flushed
           * id - id of the object for a remote unblock
           * api_barrier_mp_support - api dependent MP support actions
           *
           * Output parameters:
           * CORE_BARRIER_STATUS_SUCCESSFUL - if successful
           * core error code - if unsuccessful
           *
           * Output parameters:
           * returns number of threads unblocked
           */
          
      46  uint32_t _CORE_barrier_Release(  
           CORE_barrier_Control *the_barrier,  
          #if defined(  RTEMS_MULTIPROCESSING )
           Objects_Id id,  
           CORE_barrier_API_mp_support_callout api_barrier_mp_support
          #else
           Objects_Id id __attribute__(  (  unused ) ),  
           CORE_barrier_API_mp_support_callout api_barrier_mp_support __attribute__(  (  unused ) )
          #endif
           )
          {
           Thread_Control *the_thread;
           uint32_t count;
          
           count = 0;
           while (   (  the_thread = _Thread_queue_Dequeue(  &the_barrier->Wait_queue ) )  ) {
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   !_Objects_Is_local_id(   the_thread->Object.id  )  )
           (  *api_barrier_mp_support ) (   the_thread,   id  );
          #endif
           count++;
           }
           the_barrier->number_of_waiting_threads = 0;
           return count;
          }

score/src/corebarrierwait.c

       1  /*
           * SuperCore Barrier Handler
           *
           * DESCRIPTION:
           *
           * This package is part of the implementation of the SuperCore Barrier Handler.
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: corebarrierwait.c,  v 1.6 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/corebarrier.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*PAGE
           *
           * _CORE_barrier_Wait
           *
           * Input parameters:
           * the_barrier - pointer to barrier control block
           * id - id of object to wait on
           * wait - true if wait is allowed,   false otherwise
           * timeout - number of ticks to wait (  0 means forever )
           * api_barrier_mp_support - api dependent MP support actions
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * available
           * wait
           */
          
      47  void _CORE_barrier_Wait(  
           CORE_barrier_Control *the_barrier,  
           Objects_Id id,  
           bool wait,  
           Watchdog_Interval timeout,  
           CORE_barrier_API_mp_support_callout api_barrier_mp_support
           )
          {
           Thread_Control *executing;
           ISR_Level level;
          
           executing = _Thread_Executing;
           executing->Wait.return_code = CORE_BARRIER_STATUS_SUCCESSFUL;
           _ISR_Disable(   level  );
           the_barrier->number_of_waiting_threads++;
           if (   _CORE_barrier_Is_automatic(   &the_barrier->Attributes  )  ) {
           if (   the_barrier->number_of_waiting_threads ==
           the_barrier->Attributes.maximum_count ) {
           executing->Wait.return_code = CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED;
           _ISR_Enable(   level  );
           _CORE_barrier_Release(   the_barrier,   id,   api_barrier_mp_support  );
           return;
           }
           }
          
           _Thread_queue_Enter_critical_section(   &the_barrier->Wait_queue  );
           executing->Wait.queue = &the_barrier->Wait_queue;
           executing->Wait.id = id;
           _ISR_Enable(   level  );
          
           _Thread_queue_Enqueue(   &the_barrier->Wait_queue,   timeout  );
          }

score/src/coremsg.c

       1  /*
           * CORE Message Queue Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Message Queue Handler.
           * This core object provides task synchronization and communication functions
           * via messages passed to queue objects.
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremsg.c,  v 1.29 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          
          /*
           * _CORE_message_queue_Initialize
           *
           * This routine initializes a newly created message queue based on the
           * specified data.
           *
           * Input parameters:
           * the_message_queue - the message queue to initialize
           * the_class - the API specific object class
           * the_message_queue_attributes - the message queue's attributes
           * maximum_pending_messages - maximum message and reserved buffer count
           * maximum_message_size - maximum size of each message
           *
           * Output parameters:
           * true - if the message queue is initialized
           * false - if the message queue is NOT initialized
           */
          
      51  bool _CORE_message_queue_Initialize(  
           CORE_message_queue_Control *the_message_queue,  
           CORE_message_queue_Attributes *the_message_queue_attributes,  
           uint32_t maximum_pending_messages,  
           size_t maximum_message_size
           )
          {
           size_t message_buffering_required;
           size_t allocated_message_size;
          
           the_message_queue->maximum_pending_messages = maximum_pending_messages;
           the_message_queue->number_of_pending_messages = 0;
           the_message_queue->maximum_message_size = maximum_message_size;
           _CORE_message_queue_Set_notify(   the_message_queue,   NULL,   NULL  );
          
           /*
           * Round size up to multiple of a pointer for chain init and
           * check for overflow on adding overhead to each message.
           */
           allocated_message_size = maximum_message_size;
           if (  allocated_message_size & (  sizeof(  uint32_t ) - 1 ) ) {
           allocated_message_size += sizeof(  uint32_t );
           allocated_message_size &= ~(  sizeof(  uint32_t ) - 1 );
           }
          
           if (  allocated_message_size < maximum_message_size )
           return false;
          
           /*
           * Calculate how much total memory is required for message buffering and
           * check for overflow on the multiplication.
           */
           message_buffering_required = (  size_t ) maximum_pending_messages *
           (  allocated_message_size + sizeof(  CORE_message_queue_Buffer_control ) );
          
           if (  message_buffering_required < allocated_message_size )
           return false;
          
           /*
           * Attempt to allocate the message memory
           */
           the_message_queue->message_buffers = (  CORE_message_queue_Buffer * )
           _Workspace_Allocate(   message_buffering_required  );
          
           if (  the_message_queue->message_buffers == 0 )
           return false;
          
           /*
           * Initialize the pool of inactive messages,   pending messages,  
           * and set of waiting threads.
           */
           _Chain_Initialize (  
           &the_message_queue->Inactive_messages,  
           the_message_queue->message_buffers,  
           (  size_t ) maximum_pending_messages,  
           allocated_message_size + sizeof(   CORE_message_queue_Buffer_control  )
            );
          
           _Chain_Initialize_empty(   &the_message_queue->Pending_messages  );
          
           _Thread_queue_Initialize(  
           &the_message_queue->Wait_queue,  
           _CORE_message_queue_Is_priority(   the_message_queue_attributes  ) ?
           THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,  
           STATES_WAITING_FOR_MESSAGE,  
           CORE_MESSAGE_QUEUE_STATUS_TIMEOUT
            );
          
           return true;
          }

score/src/coremsgbroadcast.c

       1  /*
           * CORE Message Queue Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Message Queue Handler.
           * This core object provides task synchronization and communication functions
           * via messages passed to queue objects.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremsgbroadcast.c,  v 1.14 2009/09/13 20:12:09 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _CORE_message_queue_Broadcast
           *
           * This function sends a message for every thread waiting on the queue and
           * returns the number of threads made ready by the message.
           *
           * Input parameters:
           * the_message_queue - message is submitted to this message queue
           * buffer - pointer to message buffer
           * size - size in bytes of message to send
           * id - id of message queue
           * api_message_queue_mp_support - api specific mp support callout
           * count - area to store number of threads made ready
           *
           * Output parameters:
           * count - number of threads made ready
           * CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      54  CORE_message_queue_Status _CORE_message_queue_Broadcast(  
           CORE_message_queue_Control *the_message_queue,  
           const void *buffer,  
           size_t size,  
           #if defined(  RTEMS_MULTIPROCESSING )
           Objects_Id id,  
           CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,  
           #else
           Objects_Id id __attribute__(  (  unused ) ),  
           CORE_message_queue_API_mp_support_callout api_message_queue_mp_support __attribute__(  (  unused ) ),  
           #endif
           uint32_t *count
           )
          {
           Thread_Control *the_thread;
           uint32_t number_broadcasted;
           Thread_Wait_information *waitp;
          
           if (   size > the_message_queue->maximum_message_size  ) {
           return CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
           }
          
           /*
           * If there are pending messages,   then there can't be threads
           * waiting for us to send them a message.
           *
           * NOTE: This check is critical because threads can block on
           * send and receive and this ensures that we are broadcasting
           * the message to threads waiting to receive -- not to send.
           */
          
           if (   the_message_queue->number_of_pending_messages != 0  ) {
           *count = 0;
           return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
           }
          
           /*
           * There must be no pending messages if there is a thread waiting to
           * receive a message.
           */
           number_broadcasted = 0;
           while (  (  the_thread =
           _Thread_queue_Dequeue(  &the_message_queue->Wait_queue ) ) ) {
           waitp = &the_thread->Wait;
           number_broadcasted += 1;
          
           _CORE_message_queue_Copy_buffer(  
           buffer,  
           waitp->return_argument_second.mutable_object,  
           size
            );
          
           *(  size_t * ) the_thread->Wait.return_argument = size;
          
           #if defined(  RTEMS_MULTIPROCESSING )
           if (   !_Objects_Is_local_id(   the_thread->Object.id  )  )
           (  *api_message_queue_mp_support ) (   the_thread,   id  );
           #endif
          
           }
           *count = number_broadcasted;
           return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
          }

score/src/coremsgclose.c

       1  /*
           * CORE Message Queue Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Message Queue Handler.
           * This core object provides task synchronization and communication functions
           * via messages passed to queue objects.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremsgclose.c,  v 1.9 2008/09/05 21:54:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _CORE_message_queue_Close
           *
           * This function closes a message by returning all allocated space and
           * flushing the message_queue's task wait queue.
           *
           * Input parameters:
           * the_message_queue - the message_queue to be flushed
           * remote_extract_callout - function to invoke remotely
           * status - status to pass to thread
           *
           * Output parameters: NONE
           */
          
      48  void _CORE_message_queue_Close(  
           CORE_message_queue_Control *the_message_queue,  
           Thread_queue_Flush_callout remote_extract_callout,  
           uint32_t status
           )
          {
          
           /*
           * This will flush blocked threads whether they were blocked on
           * a send or receive.
           */
          
           _Thread_queue_Flush(  
           &the_message_queue->Wait_queue,  
           remote_extract_callout,  
           status
            );
          
           /*
           * This removes all messages from the pending message queue. Since
           * we just flushed all waiting threads,   we don't have to worry about
           * the flush satisfying any blocked senders as a side-effect.
           */
          
           if (   the_message_queue->number_of_pending_messages != 0  )
           (  void ) _CORE_message_queue_Flush_support(   the_message_queue  );
          
           (  void ) _Workspace_Free(   the_message_queue->message_buffers  );
          
          }

score/src/coremsgflush.c

       1  /*
           * CORE Message Queue Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Message Queue Handler.
           * This core object provides task synchronization and communication functions
           * via messages passed to queue objects.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremsgflush.c,  v 1.9 2008/09/05 21:54:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _CORE_message_queue_Flush
           *
           * This function flushes the message_queue's pending message queue. The
           * number of messages flushed from the queue is returned.
           *
           * Input parameters:
           * the_message_queue - the message_queue to be flushed
           *
           * Output parameters:
           * returns - the number of messages flushed from the queue
           */
          
      47  uint32_t _CORE_message_queue_Flush(  
           CORE_message_queue_Control *the_message_queue
           )
          {
           if (   the_message_queue->number_of_pending_messages != 0  )
           return _CORE_message_queue_Flush_support(   the_message_queue  );
           else
           return 0;
          }

score/src/coremsgflushsupp.c

       1  /*
           * CORE Message Queue Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Message Queue Handler.
           * This core object provides task synchronization and communication functions
           * via messages passed to queue objects.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremsgflushsupp.c,  v 1.9 2008/09/05 21:54:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _CORE_message_queue_Flush_support
           *
           * This message handler routine removes all messages from a message queue
           * and returns them to the inactive message pool. The number of messages
           * flushed from the queue is returned
           *
           * Input parameters:
           * the_message_queue - pointer to message queue
           *
           * Output parameters:
           * returns - number of messages placed on inactive chain
           *
           * INTERRUPT LATENCY:
           * only case
           */
          
      51  uint32_t _CORE_message_queue_Flush_support(  
           CORE_message_queue_Control *the_message_queue
           )
          {
           ISR_Level level;
           Chain_Node *inactive_first;
           Chain_Node *message_queue_first;
           Chain_Node *message_queue_last;
           uint32_t count;
          
           /*
           * Currently,   RTEMS supports no API that has both flush and blocking
           * sends. Thus,   this routine assumes that there are no senders
           * blocked waiting to send messages. In the event,   that an API is
           * added that can flush a message queue when threads are blocked
           * waiting to send,   there are two basic behaviors envisioned:
           *
           * (  1 ) The thread queue of pending senders is a logical extension
           * of the pending message queue. In this case,   it should be
           * flushed using the _Thread_queue_Flush(   ) service with a status
           * such as CORE_MESSAGE_QUEUE_SENDER_FLUSHED (  which currently does
           * not exist ). This can be implemented without changing the "big-O"
           * of the message flushing part of the routine.
           *
           * (  2 ) Only the actual messages queued should be purged. In this case,  
           * the blocked sender threads must be allowed to send their messages.
           * In this case,   the implementation will be forced to individually
           * dequeue the senders and queue their messages. This will force
           * this routine to have "big O(  n )" where n is the number of blocked
           * senders. If there are more messages pending than senders blocked,  
           * then the existing flush code can be used to dispose of the remaining
           * pending messages.
           *
           * For now,   though,   we are very happy to have a small routine with
           * fixed execution time that only deals with pending messages.
           */
          
           _ISR_Disable(   level  );
           inactive_first = the_message_queue->Inactive_messages.first;
           message_queue_first = the_message_queue->Pending_messages.first;
           message_queue_last = the_message_queue->Pending_messages.last;
          
           the_message_queue->Inactive_messages.first = message_queue_first;
           message_queue_last->next = inactive_first;
           inactive_first->previous = message_queue_last;
           message_queue_first->previous =
           _Chain_Head(   &the_message_queue->Inactive_messages  );
          
           _Chain_Initialize_empty(   &the_message_queue->Pending_messages  );
          
           count = the_message_queue->number_of_pending_messages;
           the_message_queue->number_of_pending_messages = 0;
           _ISR_Enable(   level  );
           return count;
          }

score/src/coremsgflushwait.c

       1  /*
           * CORE Message Queue Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Message Queue Handler.
           * This core object provides task synchronization and communication functions
           * via messages passed to queue objects.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremsgflushwait.c,  v 1.8 2009/07/02 22:04:42 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          
          #if defined(  FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API )
           /*PAGE
           *
           * _CORE_message_queue_Flush_waiting_threads
           *
           * This function flushes the message_queue's task wait queue. The number
           * of messages flushed from the queue is returned.
           *
           * Input parameters:
           * the_message_queue - the message_queue to be flushed
           *
           * Output parameters:
           * returns - the number of messages flushed from the queue
           */
          
      48   void _CORE_message_queue_Flush_waiting_threads(  
           CORE_message_queue_Control *the_message_queue
            )
           {
           /* XXX this is not supported for global message queues */
          
           /*
           * IF there are no pending messages,  
           * THEN threads may be blocked waiting to RECEIVE a message,  
           *
           * IF the pending message queue is full
           * THEN threads may be blocked waiting to SEND a message
           *
           * But in either case,   we will return "unsatisfied nowait"
           * to indicate that the blocking condition was not satisfied
           * and that the blocking state was canceled.
           */
          
           _Thread_queue_Flush(  
           &the_message_queue->Wait_queue,  
           NULL,  
           CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT
            );
           }
          #endif

score/src/coremsginsert.c

       1  /*
           * CORE Message Queue Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Message Queue Handler.
           * This core object provides task synchronization and communication functions
           * via messages passed to queue objects.
           *
           * COPYRIGHT (  c ) 1989-2005.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremsginsert.c,  v 1.11 2010/08/25 20:48:43 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _CORE_message_queue_Insert_message
           *
           * This kernel routine inserts the specified message into the
           * message queue. It is assumed that the message has been filled
           * in before this routine is called.
           *
           * Input parameters:
           * the_message_queue - pointer to message queue
           * the_message - message to insert
           * priority - insert indication
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * insert
           */
          
      52  void _CORE_message_queue_Insert_message(  
           CORE_message_queue_Control *the_message_queue,  
           CORE_message_queue_Buffer_control *the_message,  
           CORE_message_queue_Submit_types submit_type
           )
          {
           ISR_Level level;
           #if defined(  RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION )
           bool notify = false;
           #define SET_NOTIFY(   ) \
           do { \
           if (   the_message_queue->number_of_pending_messages == 0  ) \
           notify = true; \
           } while (  0 )
           #else
           #define SET_NOTIFY(   )
           #endif
          
           _CORE_message_queue_Set_message_priority(   the_message,   submit_type  );
          
           #if !defined(  RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY )
           _ISR_Disable(   level  );
           SET_NOTIFY(   );
           the_message_queue->number_of_pending_messages++;
           if (   submit_type == CORE_MESSAGE_QUEUE_SEND_REQUEST  )
           _CORE_message_queue_Append_unprotected(  the_message_queue,   the_message );
           else
           _CORE_message_queue_Prepend_unprotected(  the_message_queue,   the_message );
           _ISR_Enable(   level  );
           #else
           if (   submit_type == CORE_MESSAGE_QUEUE_SEND_REQUEST  ) {
           _ISR_Disable(   level  );
           SET_NOTIFY(   );
           the_message_queue->number_of_pending_messages++;
           _CORE_message_queue_Append_unprotected(  the_message_queue,   the_message );
           _ISR_Enable(   level  );
           } else if (   submit_type == CORE_MESSAGE_QUEUE_URGENT_REQUEST  ) {
           _ISR_Disable(   level  );
           SET_NOTIFY(   );
           the_message_queue->number_of_pending_messages++;
           _CORE_message_queue_Prepend_unprotected(  the_message_queue,   the_message );
           _ISR_Enable(   level  );
           } else {
           CORE_message_queue_Buffer_control *this_message;
           Chain_Node *the_node;
           Chain_Control *the_header;
           int the_priority;
          
           the_priority = _CORE_message_queue_Get_message_priority(  the_message );
           the_header = &the_message_queue->Pending_messages;
           the_node = the_header->first;
           while (   !_Chain_Is_tail(   the_header,   the_node  )  ) {
           int this_priority;
          
           this_message = (  CORE_message_queue_Buffer_control * ) the_node;
          
           this_priority = _CORE_message_queue_Get_message_priority(  this_message );
          
           if (   this_priority <= the_priority  ) {
           the_node = the_node->next;
           continue;
           }
           break;
           }
           _ISR_Disable(   level  );
           SET_NOTIFY(   );
           the_message_queue->number_of_pending_messages++;
           _Chain_Insert_unprotected(   the_node->previous,   &the_message->Node  );
           _ISR_Enable(   level  );
           }
           #endif
          
           #if defined(  RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION )
           /*
           * According to POSIX,   does this happen before or after the message
           * is actually enqueued. It is logical to think afterwards,   because
           * the message is actually in the queue at this point.
           */
           if (   notify && the_message_queue->notify_handler  )
           (  *the_message_queue->notify_handler )(  the_message_queue->notify_argument );
           #endif
          }

score/src/coremsgseize.c

       1  /*
           * CORE Message Queue Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Message Queue Handler.
           * This core object provides task synchronization and communication functions
           * via messages passed to queue objects.
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremsgseize.c,  v 1.21 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _CORE_message_queue_Seize
           *
           * This kernel routine dequeues a message,   copies the message buffer to
           * a given destination buffer,   and frees the message buffer to the
           * inactive message pool. The thread will be blocked if wait is true,  
           * otherwise an error will be given to the thread if no messages are available.
           *
           * Input parameters:
           * the_message_queue - pointer to message queue
           * id - id of object we are waitig on
           * buffer - pointer to message buffer to be filled
           * size_p - pointer to the size of buffer to be filled
           * wait - true if wait is allowed,   false otherwise
           * timeout - time to wait for a message
           *
           * Output parameters: NONE
           *
           * NOTE: Dependent on BUFFER_LENGTH
           *
           * INTERRUPT LATENCY:
           * available
           * wait
           */
          
      59  void _CORE_message_queue_Seize(  
           CORE_message_queue_Control *the_message_queue,  
           Objects_Id id,  
           void *buffer,  
           size_t *size_p,  
           bool wait,  
           Watchdog_Interval timeout
           )
          {
           ISR_Level level;
           CORE_message_queue_Buffer_control *the_message;
           Thread_Control *executing;
          
           executing = _Thread_Executing;
           executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
           _ISR_Disable(   level  );
           the_message = _CORE_message_queue_Get_pending_message(   the_message_queue  );
           if (   the_message != NULL  ) {
           the_message_queue->number_of_pending_messages -= 1;
           _ISR_Enable(   level  );
          
           *size_p = the_message->Contents.size;
           _Thread_Executing->Wait.count =
           _CORE_message_queue_Get_message_priority(   the_message  );
           _CORE_message_queue_Copy_buffer(  
           the_message->Contents.buffer,  
           buffer,  
           *size_p
            );
          
           #if !defined(  RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND )
           /*
           * There is not an API with blocking sends enabled.
           * So return immediately.
           */
           _CORE_message_queue_Free_message_buffer(  the_message_queue,   the_message );
           return;
           #else
           {
           Thread_Control *the_thread;
          
           /*
           * There could be a thread waiting to send a message. If there
           * is not,   then we can go ahead and free the buffer.
           *
           * NOTE: If we note that the queue was not full before this receive,  
           * then we can avoid this dequeue.
           */
           the_thread = _Thread_queue_Dequeue(   &the_message_queue->Wait_queue  );
           if (   !the_thread  ) {
           _CORE_message_queue_Free_message_buffer(  
           the_message_queue,  
           the_message
            );
           return;
           }
          
           /*
           * There was a thread waiting to send a message. This code
           * puts the messages in the message queue on behalf of the
           * waiting task.
           */
           _CORE_message_queue_Set_message_priority(  
           the_message,  
           the_thread->Wait.count
            );
           the_message->Contents.size = (  size_t ) the_thread->Wait.option;
           _CORE_message_queue_Copy_buffer(  
           the_thread->Wait.return_argument_second.immutable_object,  
           the_message->Contents.buffer,  
           the_message->Contents.size
            );
          
           _CORE_message_queue_Insert_message(  
           the_message_queue,  
           the_message,  
           _CORE_message_queue_Get_message_priority(   the_message  )
            );
           return;
           }
           #endif
           }
          
           if (   !wait  ) {
           _ISR_Enable(   level  );
           executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT;
           return;
           }
          
           _Thread_queue_Enter_critical_section(   &the_message_queue->Wait_queue  );
           executing->Wait.queue = &the_message_queue->Wait_queue;
           executing->Wait.id = id;
           executing->Wait.return_argument_second.mutable_object = buffer;
           executing->Wait.return_argument = size_p;
           /* Wait.count will be filled in with the message priority */
           _ISR_Enable(   level  );
          
           _Thread_queue_Enqueue(   &the_message_queue->Wait_queue,   timeout  );
          }

score/src/coremsgsubmit.c

       1  /*
           * CORE Message Queue Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Message Queue Handler.
           * This core object provides task synchronization and communication functions
           * via messages passed to queue objects.
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremsgsubmit.c,  v 1.25 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/coremsg.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _CORE_message_queue_Submit
           *
           * This routine implements the send and urgent message functions. It
           * processes a message that is to be submitted to the designated
           * message queue. The message will either be processed as a
           * send message which it will be inserted at the rear of the queue
           * or it will be processed as an urgent message which will be inserted
           * at the front of the queue.
           *
           * Input parameters:
           * the_message_queue - message is submitted to this message queue
           * buffer - pointer to message buffer
           * size - size in bytes of message to send
           * id - id of message queue
           * api_message_queue_mp_support - api specific mp support callout
           * submit_type - send or urgent message
           *
           * Output parameters:
           * CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      57  CORE_message_queue_Status _CORE_message_queue_Submit(  
           CORE_message_queue_Control *the_message_queue,  
           const void *buffer,  
           size_t size,  
           Objects_Id id,  
           #if defined(  RTEMS_MULTIPROCESSING )
           CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,  
           #else
           CORE_message_queue_API_mp_support_callout api_message_queue_mp_support __attribute__(  (  unused ) ),  
           #endif
           CORE_message_queue_Submit_types submit_type,  
           bool wait,  
           Watchdog_Interval timeout
           )
          {
           CORE_message_queue_Buffer_control *the_message;
           Thread_Control *the_thread;
          
           if (   size > the_message_queue->maximum_message_size  ) {
           return CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
           }
          
           /*
           * Is there a thread currently waiting on this message queue?
           */
           if (   the_message_queue->number_of_pending_messages == 0  ) {
           the_thread = _Thread_queue_Dequeue(   &the_message_queue->Wait_queue  );
           if (   the_thread  ) {
           _CORE_message_queue_Copy_buffer(  
           buffer,  
           the_thread->Wait.return_argument_second.mutable_object,  
           size
            );
           *(  size_t * ) the_thread->Wait.return_argument = size;
           the_thread->Wait.count = (  uint32_t ) submit_type;
          
           #if defined(  RTEMS_MULTIPROCESSING )
           if (   !_Objects_Is_local_id(   the_thread->Object.id  )  )
           (  *api_message_queue_mp_support ) (   the_thread,   id  );
           #endif
           return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
           }
           }
          
           /*
           * No one waiting on the message queue at this time,   so attempt to
           * queue the message up for a future receive.
           */
           if (   the_message_queue->number_of_pending_messages <
           the_message_queue->maximum_pending_messages  ) {
          
           the_message =
           _CORE_message_queue_Allocate_message_buffer(   the_message_queue  );
          
           #if defined(  RTEMS_DEBUG )
           /*
           * NOTE: If the system is consistent,   this error should never occur.
           */
          
           if (   !the_message  )
           return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
           #endif
          
           _CORE_message_queue_Copy_buffer(  
           buffer,  
           the_message->Contents.buffer,  
           size
            );
           the_message->Contents.size = size;
           _CORE_message_queue_Set_message_priority(   the_message,   submit_type  );
          
           _CORE_message_queue_Insert_message(  
           the_message_queue,  
           the_message,  
           submit_type
            );
           return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
           }
          
           #if !defined(  RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND )
           return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
           #else
           /*
           * No message buffers were available so we may need to return an
           * overflow error or block the sender until the message is placed
           * on the queue.
           */
           if (   !wait  ) {
           return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
           }
          
           /*
           * Do NOT block on a send if the caller is in an ISR. It is
           * deadly to block in an ISR.
           */
           if (   _ISR_Is_in_progress(   )  ) {
           return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
           }
          
           /*
           * WARNING!! executing should NOT be used prior to this point.
           * Thus the unusual choice to open a new scope and declare
           * it as a variable. Doing this emphasizes how dangerous it
           * would be to use this variable prior to here.
           */
           {
           Thread_Control *executing = _Thread_Executing;
           ISR_Level level;
          
           _ISR_Disable(   level  );
           _Thread_queue_Enter_critical_section(   &the_message_queue->Wait_queue  );
           executing->Wait.queue = &the_message_queue->Wait_queue;
           executing->Wait.id = id;
           executing->Wait.return_argument_second.immutable_object = buffer;
           executing->Wait.option = (  uint32_t ) size;
           executing->Wait.count = submit_type;
           _ISR_Enable(   level  );
          
           _Thread_queue_Enqueue(   &the_message_queue->Wait_queue,   timeout  );
           }
          
           return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT;
           #endif
          }

score/src/coremutex.c

       1  /*
           * Mutex Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Mutex Handler.
           * This handler provides synchronization and mutual exclusion capabilities.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremutex.c,  v 1.34 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*PAGE
           *
           * _CORE_mutex_Initialize
           *
           * This routine initializes a mutex at create time and set the control
           * structure according to the values passed.
           *
           * Input parameters:
           * the_mutex - the mutex control block to initialize
           * the_mutex_attributes - the mutex attributes specified at create time
           * initial_lock - mutex initial lock or unlocked status
           *
           * Output parameters: NONE
           */
          
      45  CORE_mutex_Status _CORE_mutex_Initialize(  
           CORE_mutex_Control *the_mutex,  
           CORE_mutex_Attributes *the_mutex_attributes,  
           uint32_t initial_lock
           )
          {
          
          /* Add this to the RTEMS environment later ?????????
           rtems_assert(   initial_lock == CORE_MUTEX_LOCKED ||
           initial_lock == CORE_MUTEX_UNLOCKED  );
           */
          
           the_mutex->Attributes = *the_mutex_attributes;
           the_mutex->lock = initial_lock;
           the_mutex->blocked_count = 0;
          
           if (   initial_lock == CORE_MUTEX_LOCKED  ) {
           the_mutex->nest_count = 1;
           the_mutex->holder = _Thread_Executing;
           the_mutex->holder_id = _Thread_Executing->Object.id;
           if (   _CORE_mutex_Is_inherit_priority(   &the_mutex->Attributes  ) ||
           _CORE_mutex_Is_priority_ceiling(   &the_mutex->Attributes  )  ) {
          
           if (   _Thread_Executing->current_priority <
           the_mutex->Attributes.priority_ceiling  )
           return CORE_MUTEX_STATUS_CEILING_VIOLATED;
          #ifdef __RTEMS_STRICT_ORDER_MUTEX__
           _Chain_Prepend_unprotected(   &_Thread_Executing->lock_mutex,  
           &the_mutex->queue.lock_queue  );
           the_mutex->queue.priority_before = _Thread_Executing->current_priority;
          #endif
          
           _Thread_Executing->resource_count++;
           }
           } else {
           the_mutex->nest_count = 0;
           the_mutex->holder = NULL;
           the_mutex->holder_id = 0;
           }
          
           _Thread_queue_Initialize(  
           &the_mutex->Wait_queue,  
           _CORE_mutex_Is_fifo(   the_mutex_attributes  ) ?
           THREAD_QUEUE_DISCIPLINE_FIFO : THREAD_QUEUE_DISCIPLINE_PRIORITY,  
           STATES_WAITING_FOR_MUTEX,  
           CORE_MUTEX_TIMEOUT
            );
          
           return CORE_MUTEX_STATUS_SUCCESSFUL;
          }

score/src/coremutexflush.c

       1  /*
           * Mutex Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Mutex Handler.
           * This handler provides synchronization and mutual exclusion capabilities.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremutexflush.c,  v 1.5 2005/01/27 05:57:04 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*PAGE
           *
           * _CORE_mutex_Flush
           *
           * This function a flushes the mutex's task wait queue.
           *
           * Input parameters:
           * the_mutex - the mutex to be flushed
           * remote_extract_callout - function to invoke remotely
           * status - status to pass to thread
           *
           * Output parameters: NONE
           */
          
      44  void _CORE_mutex_Flush(  
           CORE_mutex_Control *the_mutex,  
           Thread_queue_Flush_callout remote_extract_callout,  
           uint32_t status
           )
          {
           _Thread_queue_Flush(  
           &the_mutex->Wait_queue,  
           remote_extract_callout,  
           status
            );
          }

score/src/coremutexseize.c

       1  /*
           * Mutex Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Mutex Handler.
           * This handler provides synchronization and mutual exclusion capabilities.
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremutexseize.c,  v 1.17 2008/12/22 05:52:31 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          #if defined(  __RTEMS_DO_NOT_INLINE_CORE_MUTEX_SEIZE__ )
      31  void _CORE_mutex_Seize(  
           CORE_mutex_Control *_the_mutex,  
           Objects_Id _id,  
           bool _wait,  
           Watchdog_Interval _timeout,  
           ISR_Level _level
           )
          {
           _CORE_mutex_Seize_body(   _the_mutex,   _id,   _wait,   _timeout,   _level  );
          }
          #endif
          
          /*PAGE
           *
           * _CORE_mutex_Seize (  interrupt blocking support )
           *
           * This routine blocks the caller thread after an attempt attempts to obtain
           * the specified mutex has failed.
           *
           * Input parameters:
           * the_mutex - pointer to mutex control block
           * timeout - number of ticks to wait (  0 means forever )
           */
          
      55  void _CORE_mutex_Seize_interrupt_blocking(  
           CORE_mutex_Control *the_mutex,  
           Watchdog_Interval timeout
           )
          {
           Thread_Control *executing;
          
           executing = _Thread_Executing;
           if (   _CORE_mutex_Is_inherit_priority(   &the_mutex->Attributes  )  ) {
           if (   the_mutex->holder->current_priority > executing->current_priority  ) {
           _Thread_Change_priority(  
           the_mutex->holder,  
           executing->current_priority,  
           false
            );
           }
           }
          
           the_mutex->blocked_count++;
           _Thread_queue_Enqueue(   &the_mutex->Wait_queue,   timeout  );
          
           _Thread_Enable_dispatch(   );
          }
          

score/src/coremutexseizeintr.c

       1  /*
           * Mutex Handler -- Seize interrupt disable version
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremutexseizeintr.c,  v 1.2 2008/01/09 21:11:04 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          #if defined(  __RTEMS_DO_NOT_INLINE_CORE_MUTEX_SEIZE__ )
      26  int _CORE_mutex_Seize_interrupt_trylock(  
           CORE_mutex_Control *the_mutex,  
           ISR_Level *level_p
           )
          {
           return _CORE_mutex_Seize_interrupt_trylock_body(   the_mutex,   level_p  );
          }
          #endif

score/src/coremutexsurrender.c

       1  /*
           * Mutex Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the Mutex Handler.
           * This handler provides synchronization and mutual exclusion capabilities.
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coremutexsurrender.c,  v 1.23 2010/07/15 15:44:40 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coremutex.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          #ifdef __RTEMS_STRICT_ORDER_MUTEX__
      31   static inline void _CORE_mutex_Push_priority(  
           CORE_mutex_Control *mutex,  
           Thread_Control *thread
            )
           {
           _Chain_Prepend_unprotected(  
           &thread->lock_mutex,  
           &mutex->queue.lock_queue
            );
           mutex->queue.priority_before = thread->current_priority;
           }
          
      43   static inline CORE_mutex_Status _CORE_mutex_Pop_priority(  
           CORE_mutex_Control *mutex,  
           Thread_Control *holder
            )
           {
           /*
           * Check whether the holder release the mutex in LIFO order if not return
           * error code.
           */
           if (   _Chain_First(   holder->lock_mutex  ) != &mutex->queue.lock_queue  ) {
           mutex->nest_count++;
          
           return CORE_MUTEX_RELEASE_NOT_ORDER;
           }
          
           /*
           * This pops the first node from the list.
           */
           _Chain_Get_first_unprotected(   &holder->lock_mutex  );
          
           if (   mutex->queue.priority_before != holder->current_priority  )
           _Thread_Change_priority(   holder,   mutex->queue.priority_before,   true  );
          
           return CORE_MUTEX_STATUS_SUCCESSFUL;
           }
          #else
           #define _CORE_mutex_Push_priority(   mutex,   thread  ) (  (  void ) 0 )
          
           #define _CORE_mutex_Pop_priority(   mutex,   thread  ) \
           CORE_MUTEX_STATUS_SUCCESSFUL
          #endif
          
          /*
           * _CORE_mutex_Surrender
           *
           * DESCRIPTION:
           *
           * This routine frees a unit to the mutex. If a task was blocked waiting for
           * a unit from this mutex,   then that task will be readied and the unit
           * given to that task. Otherwise,   the unit will be returned to the mutex.
           *
           * Input parameters:
           * the_mutex - the mutex to be flushed
           * id - id of parent mutex
           * api_mutex_mp_support - api dependent MP support actions
           *
           * Output parameters:
           * CORE_MUTEX_STATUS_SUCCESSFUL - if successful
           * core error code - if unsuccessful
           */
      93  
          CORE_mutex_Status _CORE_mutex_Surrender(  
           CORE_mutex_Control *the_mutex,  
          #if defined(  RTEMS_MULTIPROCESSING )
           Objects_Id id,  
           CORE_mutex_API_mp_support_callout api_mutex_mp_support
          #else
           Objects_Id id __attribute__(  (  unused ) ),  
           CORE_mutex_API_mp_support_callout api_mutex_mp_support __attribute__(  (  unused ) )
          #endif
           )
          {
           Thread_Control *the_thread;
           Thread_Control *holder;
          
           holder = the_mutex->holder;
          
           /*
           * The following code allows a thread (  or ISR ) other than the thread
           * which acquired the mutex to release that mutex. This is only
           * allowed when the mutex in quetion is FIFO or simple Priority
           * discipline. But Priority Ceiling or Priority Inheritance mutexes
           * must be released by the thread which acquired them.
           */
          
           if (   the_mutex->Attributes.only_owner_release  ) {
           if (   !_Thread_Is_executing(   holder  )  )
           return CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE;
           }
          
           /* XXX already unlocked -- not right status */
          
           if (   !the_mutex->nest_count  )
           return CORE_MUTEX_STATUS_SUCCESSFUL;
          
           the_mutex->nest_count--;
          
           if (   the_mutex->nest_count != 0  ) {
           /*
           * All error checking is on the locking side,   so if the lock was
           * allowed to acquired multiple times,   then we should just deal with
           * that. The RTEMS_DEBUG is just a validation.
           */
           #if defined(  RTEMS_DEBUG )
           switch (   the_mutex->Attributes.lock_nesting_behavior  ) {
           case CORE_MUTEX_NESTING_ACQUIRES:
           return CORE_MUTEX_STATUS_SUCCESSFUL;
           case CORE_MUTEX_NESTING_IS_ERROR:
           /* should never occur */
           return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
           case CORE_MUTEX_NESTING_BLOCKS:
           /* Currently no API exercises this behavior. */
           break;
           }
           #else
           /* must be CORE_MUTEX_NESTING_ACQUIRES or we wouldn't be here */
           return CORE_MUTEX_STATUS_SUCCESSFUL;
           #endif
           }
          
           /*
           * Formally release the mutex before possibly transferring it to a
           * blocked thread.
           */
           if (   _CORE_mutex_Is_inherit_priority(   &the_mutex->Attributes  ) ||
           _CORE_mutex_Is_priority_ceiling(   &the_mutex->Attributes  )  ) {
           CORE_mutex_Status pop_status =
           _CORE_mutex_Pop_priority(   the_mutex,   holder  );
          
           if (   pop_status != CORE_MUTEX_STATUS_SUCCESSFUL  )
           return pop_status;
          
           holder->resource_count--;
          
           /*
           * Whether or not someone is waiting for the mutex,   an
           * inherited priority must be lowered if this is the last
           * mutex (  i.e. resource ) this task has.
           */
           if (   holder->resource_count == 0 &&
           holder->real_priority != holder->current_priority  ) {
           _Thread_Change_priority(   holder,   holder->real_priority,   true  );
           }
           }
           the_mutex->holder = NULL;
           the_mutex->holder_id = 0;
          
           /*
           * Now we check if another thread was waiting for this mutex. If so,  
           * transfer the mutex to that thread.
           */
           if (   (   the_thread = _Thread_queue_Dequeue(   &the_mutex->Wait_queue  )  )  ) {
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   !_Objects_Is_local_id(   the_thread->Object.id  )  ) {
          
           the_mutex->holder = NULL;
           the_mutex->holder_id = the_thread->Object.id;
           the_mutex->nest_count = 1;
          
           (   *api_mutex_mp_support )(   the_thread,   id  );
          
           } else
          #endif
           {
          
           the_mutex->holder = the_thread;
           the_mutex->holder_id = the_thread->Object.id;
           the_mutex->nest_count = 1;
          
           switch (   the_mutex->Attributes.discipline  ) {
           case CORE_MUTEX_DISCIPLINES_FIFO:
           case CORE_MUTEX_DISCIPLINES_PRIORITY:
           break;
           case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
           _CORE_mutex_Push_priority(   the_mutex,   the_thread  );
           the_thread->resource_count++;
           break;
           case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
           _CORE_mutex_Push_priority(   the_mutex,   the_thread  );
           the_thread->resource_count++;
           if (  the_mutex->Attributes.priority_ceiling <
           the_thread->current_priority ){
           _Thread_Change_priority(  
           the_thread,  
           the_mutex->Attributes.priority_ceiling,  
           false
            );
           }
           break;
           }
           }
           } else
           the_mutex->lock = CORE_MUTEX_UNLOCKED;
          
           return CORE_MUTEX_STATUS_SUCCESSFUL;
          }

score/src/corerwlock.c

       1  /*
           * SuperCore RWLock Handler
           *
           * DESCRIPTION:
           *
           * This package is part of the implementation of the SuperCore RWLock Handler.
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: corerwlock.c,  v 1.3 2008/09/05 21:54:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/corerwlock.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*PAGE
           *
           * _CORE_RWLock_Initialize
           *
           * This function initialize a rwlock and sets the initial value based
           * on the given count.
           *
           * Input parameters:
           * the_rwlock - the rwlock control block to initialize
           * the_rwlock_attributes - the attributes specified at create time
           *
           * Output parameters: NONE
           */
          
      42  void _CORE_RWLock_Initialize(  
           CORE_RWLock_Control *the_rwlock,  
           CORE_RWLock_Attributes *the_rwlock_attributes
           )
          {
          
           the_rwlock->Attributes = *the_rwlock_attributes;
          /*
           the_rwlock->number_of_waiting_threads = 0;
          */
           the_rwlock->number_of_readers = 0;
           the_rwlock->current_state = CORE_RWLOCK_UNLOCKED;
          
           _Thread_queue_Initialize(  
           &the_rwlock->Wait_queue,  
           THREAD_QUEUE_DISCIPLINE_FIFO,  
           STATES_WAITING_FOR_RWLOCK,  
           CORE_RWLOCK_TIMEOUT
            );
          }

score/src/corerwlockobtainread.c

       1  /*
           * SuperCore RWLock Handler -- Obtain RWLock for reading
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: corerwlockobtainread.c,  v 1.6 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/corerwlock.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _CORE_rwlock_Obtain_for_reading
           *
           * This function waits for the rwlock to become available. Optionally,  
           * a limit may be placed on the duration of the spin.
           *
           * Input parameters:
           * the_rwlock - the rwlock control block to initialize
           * timeout_allowed - true if timeout allowed
           * timeout - the maximum number of ticks to spin
           *
           * Output parameters: NONE
           */
          
      39  void _CORE_RWLock_Obtain_for_reading(  
           CORE_RWLock_Control *the_rwlock,  
           Objects_Id id,  
           bool wait,  
           Watchdog_Interval timeout,  
           CORE_RWLock_API_mp_support_callout api_rwlock_mp_support
           )
          {
           ISR_Level level;
           Thread_Control *executing = _Thread_Executing;
          
           /*
           * If unlocked,   then OK to read.
           * If locked for reading and no waiters,   then OK to read.
           * If any thread is waiting,   then we wait.
           */
          
           _ISR_Disable(   level  );
           switch (   the_rwlock->current_state  ) {
           case CORE_RWLOCK_UNLOCKED:
           the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;
           the_rwlock->number_of_readers += 1;
           _ISR_Enable(   level  );
           executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
           return;
          
           case CORE_RWLOCK_LOCKED_FOR_READING: {
           Thread_Control *waiter;
           waiter = _Thread_queue_First(   &the_rwlock->Wait_queue  );
           if (   !waiter  ) {
           the_rwlock->number_of_readers += 1;
           _ISR_Enable(   level  );
           executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
           return;
           }
           break;
           }
           case CORE_RWLOCK_LOCKED_FOR_WRITING:
           break;
           }
          
           /*
           * If the thread is not willing to wait,   then return immediately.
           */
          
           if (   !wait  ) {
           _ISR_Enable(   level  );
           executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
           return;
           }
          
           /*
           * We need to wait to enter this critical section
           */
          
           _Thread_queue_Enter_critical_section(   &the_rwlock->Wait_queue  );
           executing->Wait.queue = &the_rwlock->Wait_queue;
           executing->Wait.id = id;
           executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_READ;
           executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
           _ISR_Enable(   level  );
          
           _Thread_queue_Enqueue_with_handler(  
           &the_rwlock->Wait_queue,  
           timeout,  
           _CORE_RWLock_Timeout
            );
          
           /* return to API level so it can dispatch and we block */
          }

score/src/corerwlockobtainwrite.c

       1  /*
           * SuperCore RWLock Handler -- Obtain RWLock for writing
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: corerwlockobtainwrite.c,  v 1.5 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/corerwlock.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _CORE_rwlock_Obtain_for_writing
           *
           * This function waits for the rwlock to become available. Optionally,  
           * a limit may be placed on the duration of the spin.
           *
           * Input parameters:
           * the_rwlock - the rwlock control block to initialize
           * timeout_allowed - true if timeout allowed
           * timeout - the maximum number of ticks to spin
           *
           * Output parameters: NONE
           */
          
      39  void _CORE_RWLock_Obtain_for_writing(  
           CORE_RWLock_Control *the_rwlock,  
           Objects_Id id,  
           bool wait,  
           Watchdog_Interval timeout,  
           CORE_RWLock_API_mp_support_callout api_rwlock_mp_support
           )
          {
           ISR_Level level;
           Thread_Control *executing = _Thread_Executing;
          
           /*
           * If unlocked,   then OK to read.
           * Otherwise,   we have to block.
           * If locked for reading and no waiters,   then OK to read.
           * If any thread is waiting,   then we wait.
           */
          
           _ISR_Disable(   level  );
           switch (   the_rwlock->current_state  ) {
           case CORE_RWLOCK_UNLOCKED:
           the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
           _ISR_Enable(   level  );
           executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
           return;
          
           case CORE_RWLOCK_LOCKED_FOR_READING:
           case CORE_RWLOCK_LOCKED_FOR_WRITING:
           break;
           }
          
           /*
           * If the thread is not willing to wait,   then return immediately.
           */
          
           if (   !wait  ) {
           _ISR_Enable(   level  );
           executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
           return;
           }
          
           /*
           * We need to wait to enter this critical section
           */
          
           _Thread_queue_Enter_critical_section(   &the_rwlock->Wait_queue  );
           executing->Wait.queue = &the_rwlock->Wait_queue;
           executing->Wait.id = id;
           executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_WRITE;
           executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
           _ISR_Enable(   level  );
          
           _Thread_queue_Enqueue_with_handler(  
           &the_rwlock->Wait_queue,  
           timeout,  
           _CORE_RWLock_Timeout
            );
          
          
           /* return to API level so it can dispatch and we block */
          }

score/src/corerwlockrelease.c

       1  /*
           * SuperCore RWLock Handler -- Release a RWLock
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: corerwlockrelease.c,  v 1.6 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/corerwlock.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _CORE_RWLock_Release
           *
           * This function releases the rwlock.
           *
           * Input parameters:
           * the_rwlock - the rwlock control block to initialize
           *
           * Output parameters: NONE
           */
          
      36  CORE_RWLock_Status _CORE_RWLock_Release(  
           CORE_RWLock_Control *the_rwlock
           )
          {
           ISR_Level level;
           Thread_Control *executing = _Thread_Executing;
           Thread_Control *next;
          
           /*
           * If unlocked,   then OK to read.
           * Otherwise,   we have to block.
           * If locked for reading and no waiters,   then OK to read.
           * If any thread is waiting,   then we wait.
           */
          
           _ISR_Disable(   level  );
           if (   the_rwlock->current_state == CORE_RWLOCK_UNLOCKED ){
           _ISR_Enable(   level  );
           executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
           return CORE_RWLOCK_SUCCESSFUL;
           }
           if (   the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_READING  ) {
           the_rwlock->number_of_readers -= 1;
           if (   the_rwlock->number_of_readers != 0  ) {
           /* must be unlocked again */
           _ISR_Enable(   level  );
           return CORE_RWLOCK_SUCCESSFUL;
           }
           }
          
           /* CORE_RWLOCK_LOCKED_FOR_WRITING or READING with readers */
           executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
          
           /*
           * Implicitly transition to "unlocked" and find another thread interested
           * in obtaining this rwlock.
           */
           the_rwlock->current_state = CORE_RWLOCK_UNLOCKED;
           _ISR_Enable(   level  );
          
           next = _Thread_queue_Dequeue(   &the_rwlock->Wait_queue  );
          
           if (   next  ) {
           if (   next->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE  ) {
           the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
           return CORE_RWLOCK_SUCCESSFUL;
           }
          
           /*
           * Must be CORE_RWLOCK_THREAD_WAITING_FOR_READING
           */
           the_rwlock->number_of_readers += 1;
           the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;
          
           /*
           * Now see if more readers can be let go.
           */
           while (   1  ) {
           next = _Thread_queue_First(   &the_rwlock->Wait_queue  );
           if (   !next ||
           next->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE  )
           return CORE_RWLOCK_SUCCESSFUL;
           the_rwlock->number_of_readers += 1;
           _Thread_queue_Extract(   &the_rwlock->Wait_queue,   next  );
           }
           }
          
           /* indentation is to match _ISR_Disable at top */
          
           return CORE_RWLOCK_SUCCESSFUL;
          }

score/src/corerwlocktimeout.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: corerwlocktimeout.c,  v 1.2 2007/10/26 20:19:02 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/corerwlock.h>
          #include <rtems/score/corerwlock.h>
          
          /*
           * _CORE_RWLock_Timeout
           *
           * This routine processes a thread which timeouts while waiting on
           * a thread queue. It is called by the watchdog handler.
           *
           * Input parameters:
           * id - thread id
           *
           * Output parameters: NONE
           */
          
      35  void _CORE_RWLock_Timeout(  
           Objects_Id id,  
           void *ignored
           )
          {
           Thread_Control *the_thread;
           Objects_Locations location;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
           case OBJECTS_ERROR:
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* impossible */
          #endif
           break;
           case OBJECTS_LOCAL:
           _Thread_queue_Process_timeout(   the_thread  );
           _Thread_Unnest_dispatch(   );
           break;
           }
          }

score/src/coresem.c

       1  /*
           * CORE Semaphore Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Semaphore Handler.
           * This core object utilizes standard Dijkstra counting semaphores to provide
           * synchronization and mutual exclusion capabilities.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coresem.c,  v 1.17 2008/09/05 21:54:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*PAGE
           *
           * CORE_semaphore_Initialize
           *
           * This function initialize a semaphore and sets the initial value based
           * on the given count.
           *
           * Input parameters:
           * the_semaphore - the semaphore control block to initialize
           * the_semaphore_attributes - the attributes specified at create time
           * initial_value - semaphore's initial value
           *
           * Output parameters: NONE
           */
          
      46  void _CORE_semaphore_Initialize(  
           CORE_semaphore_Control *the_semaphore,  
           CORE_semaphore_Attributes *the_semaphore_attributes,  
           uint32_t initial_value
           )
          {
          
           the_semaphore->Attributes = *the_semaphore_attributes;
           the_semaphore->count = initial_value;
          
           _Thread_queue_Initialize(  
           &the_semaphore->Wait_queue,  
           _CORE_semaphore_Is_priority(   the_semaphore_attributes  ) ?
           THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,  
           STATES_WAITING_FOR_SEMAPHORE,  
           CORE_SEMAPHORE_TIMEOUT
            );
          }

score/src/coresemflush.c

       1  /*
           * CORE Semaphore Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Semaphore Handler.
           * This core object utilizes standard Dijkstra counting semaphores to provide
           * synchronization and mutual exclusion capabilities.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coresemflush.c,  v 1.7 2008/09/05 21:54:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*PAGE
           *
           * _CORE_semaphore_Flush
           *
           * This function a flushes the semaphore's task wait queue.
           *
           * Input parameters:
           * the_semaphore - the semaphore to be flushed
           * remote_extract_callout - function to invoke remotely
           * status - status to pass to thread
           *
           * Output parameters: NONE
           */
          
      45  void _CORE_semaphore_Flush(  
           CORE_semaphore_Control *the_semaphore,  
           Thread_queue_Flush_callout remote_extract_callout,  
           uint32_t status
           )
          {
          
           _Thread_queue_Flush(  
           &the_semaphore->Wait_queue,  
           remote_extract_callout,  
           status
            );
          
          }

score/src/coresemseize.c

       1  /*
           * CORE Semaphore Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Semaphore Handler.
           * This core object utilizes standard Dijkstra counting semaphores to provide
           * synchronization and mutual exclusion capabilities.
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coresemseize.c,  v 1.14 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          #if defined(  RTEMS_SCORE_CORESEM_ENABLE_SEIZE_BODY )
          /*
           * This routine attempts to allocate a core semaphore to the calling thread.
           *
           * Input parameters:
           * the_semaphore - pointer to semaphore control block
           * id - id of object to wait on
           * wait - true if wait is allowed,   false otherwise
           * timeout - number of ticks to wait (  0 means forever )
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * available
           * wait
           */
          
      48  void _CORE_semaphore_Seize(  
           CORE_semaphore_Control *the_semaphore,  
           Objects_Id id,  
           bool wait,  
           Watchdog_Interval timeout
           )
          {
           Thread_Control *executing;
           ISR_Level level;
          
           executing = _Thread_Executing;
           executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
           _ISR_Disable(   level  );
           if (   the_semaphore->count != 0  ) {
           the_semaphore->count -= 1;
           _ISR_Enable(   level  );
           return;
           }
          
           /*
           * If the semaphore was not available and the caller was not willing
           * to block,   then return immediately with a status indicating that
           * the semaphore was not available and the caller never blocked.
           */
           if (   !wait  ) {
           _ISR_Enable(   level  );
           executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
           return;
           }
          
           /*
           * If the semaphore is not available and the caller is willing to
           * block,   then we now block the caller with optional timeout.
           */
           _Thread_queue_Enter_critical_section(   &the_semaphore->Wait_queue  );
           executing->Wait.queue = &the_semaphore->Wait_queue;
           executing->Wait.id = id;
           _ISR_Enable(   level  );
           _Thread_queue_Enqueue(   &the_semaphore->Wait_queue,   timeout  );
          }
          #endif

score/src/coresemsurrender.c

       1  /*
           * CORE Semaphore Handler
           *
           * DESCRIPTION:
           *
           * This package is the implementation of the CORE Semaphore Handler.
           * This core object utilizes standard Dijkstra counting semaphores to provide
           * synchronization and mutual exclusion capabilities.
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coresemsurrender.c,  v 1.8 2008/09/05 21:54:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/coresem.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*PAGE
           *
           * _CORE_semaphore_Surrender
           *
           * Input parameters:
           * the_semaphore - the semaphore to be flushed
           * id - id of parent semaphore
           * api_semaphore_mp_support - api dependent MP support actions
           *
           * Output parameters:
           * CORE_SEMAPHORE_STATUS_SUCCESSFUL - if successful
           * core error code - if unsuccessful
           *
           * Output parameters:
           */
          
      47  CORE_semaphore_Status _CORE_semaphore_Surrender(  
           CORE_semaphore_Control *the_semaphore,  
           Objects_Id id,  
           CORE_semaphore_API_mp_support_callout api_semaphore_mp_support
           )
          {
           Thread_Control *the_thread;
           ISR_Level level;
           CORE_semaphore_Status status;
          
           status = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
          
           if (   (  the_thread = _Thread_queue_Dequeue(  &the_semaphore->Wait_queue ) )  ) {
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   !_Objects_Is_local_id(   the_thread->Object.id  )  )
           (  *api_semaphore_mp_support ) (   the_thread,   id  );
          #endif
          
           } else {
           _ISR_Disable(   level  );
           if (   the_semaphore->count < the_semaphore->Attributes.maximum_count  )
           the_semaphore->count += 1;
           else
           status = CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED;
           _ISR_Enable(   level  );
           }
          
           return status;
          }

score/src/corespinlock.c

       1  /*
           * SuperCore Spinlock Handler
           *
           * DESCRIPTION:
           *
           * This package is part of the implementation of the SuperCore Spinlock Handler.
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: corespinlock.c,  v 1.2 2008/09/05 21:54:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/corespinlock.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          /*PAGE
           *
           * _CORE_spinlock_Initialize
           *
           * This function initialize a spinlock and sets the initial value based
           * on the given count.
           *
           * Input parameters:
           * the_spinlock - the spinlock control block to initialize
           * the_spinlock_attributes - the attributes specified at create time
           *
           * Output parameters: NONE
           */
          
      42  void _CORE_spinlock_Initialize(  
           CORE_spinlock_Control *the_spinlock,  
           CORE_spinlock_Attributes *the_spinlock_attributes
           )
          {
          
           the_spinlock->Attributes = *the_spinlock_attributes;
          
           the_spinlock->lock = 0;
           the_spinlock->users = 0;
           the_spinlock->holder = 0;
          }

score/src/corespinlockrelease.c

       1  /*
           * SuperCore Spinlock Handler -- Release a Spinlock
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: corespinlockrelease.c,  v 1.3 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/corespinlock.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _CORE_spinlock_Release
           *
           * This function releases the spinlock.
           *
           * Input parameters:
           * the_spinlock - the spinlock control block to initialize
           *
           * Output parameters:
           * CORE_SPINLOCK_SUCCESSFUL - if successful
           * error code - if unsuccessful
           *
           */
          
      39  CORE_spinlock_Status _CORE_spinlock_Release(  
           CORE_spinlock_Control *the_spinlock
           )
          {
           ISR_Level level;
          
           _ISR_Disable(   level  );
          
           /*
           * It must locked before it can be unlocked.
           */
           if (   the_spinlock->lock == CORE_SPINLOCK_UNLOCKED  ) {
           _ISR_Enable(   level  );
           return CORE_SPINLOCK_NOT_LOCKED;
           }
          
           /*
           * It must locked by the current thread before it can be unlocked.
           */
           if (   the_spinlock->holder != _Thread_Executing->Object.id  ) {
           _ISR_Enable(   level  );
           return CORE_SPINLOCK_NOT_HOLDER;
           }
          
           /*
           * Let it be unlocked.
           */
           the_spinlock->users -= 1;
           the_spinlock->lock = CORE_SPINLOCK_UNLOCKED;
           the_spinlock->holder = 0;
          
           _ISR_Enable(   level  );
           return CORE_SPINLOCK_SUCCESSFUL;
          }

score/src/corespinlockwait.c

       1  /*
           * SuperCore Spinlock Handler -- Wait for Spinlock
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: corespinlockwait.c,  v 1.5 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/corespinlock.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _CORE_spinlock_Wait
           *
           * This function waits for the spinlock to become available. Optionally,  
           * a limit may be placed on the duration of the spin.
           *
           * Input parameters:
           * the_spinlock - the spinlock control block to initialize
           * wait - true if willing to wait
           * timeout - the maximum number of ticks to spin (  0 is forever )
           *
           * Output parameters: NONE
           */
          
      39  CORE_spinlock_Status _CORE_spinlock_Wait(  
           CORE_spinlock_Control *the_spinlock,  
           bool wait,  
           Watchdog_Interval timeout
           )
          {
           ISR_Level level;
           #if defined(  FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API )
           Watchdog_Interval limit = _Watchdog_Ticks_since_boot + timeout;
           #endif
          
           _ISR_Disable(   level  );
           if (   (  the_spinlock->lock == CORE_SPINLOCK_LOCKED ) &&
           (  the_spinlock->holder == _Thread_Executing->Object.id )  ) {
           _ISR_Enable(   level  );
           return CORE_SPINLOCK_HOLDER_RELOCKING;
           }
           the_spinlock->users += 1;
           for (   ;;  ) {
           if (   the_spinlock->lock == CORE_SPINLOCK_UNLOCKED  ) {
           the_spinlock->lock = CORE_SPINLOCK_LOCKED;
           the_spinlock->holder = _Thread_Executing->Object.id;
           _ISR_Enable(   level  );
           return CORE_SPINLOCK_SUCCESSFUL;
           }
          
           /*
           * Spinlock is unavailable. If not willing to wait,   return.
           */
           if (   !wait  ) {
           the_spinlock->users -= 1;
           _ISR_Enable(   level  );
           return CORE_SPINLOCK_UNAVAILABLE;
           }
          
           #if defined(  FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API )
           /*
           * They are willing to wait but there could be a timeout.
           */
           if (   timeout && (  limit <= _Watchdog_Ticks_since_boot )  ) {
           the_spinlock->users -= 1;
           _ISR_Enable(   level  );
           return CORE_SPINLOCK_TIMEOUT;
           }
           #endif
          
           /*
           * The thread is willing to spin so let's set things up so
           * another thread has a chance of running. This spinlock has
           * to be released by either another thread or an ISR. Since
           * POSIX does not say anything about ISRs,   that implies that
           * another thread must be able to run while spinning. We are
           * not blocking so that implies we are at least preemptible
           * and possibly time-sliced.
           *
           * So first,   we will enable interrpts to allow for them to happen.
           * Then we will "flash" the thread dispatching critical section
           * so other threads have a chance to run.
           *
           * A spinlock cannot be deleted while it is being used so we are
           * safe from deletion.
           */
          
           _ISR_Enable(   level  );
           /* An ISR could occur here */
          
           _Thread_Enable_dispatch(   );
           /* Another thread could get dispatched here */
          
           /* Reenter the critical sections so we can attempt the lock again. */
           _Thread_Disable_dispatch(   );
          
           _ISR_Disable(   level  );
           }
          
          }

score/src/coretod.c

       1  /*
           * Time of Day (  TOD ) Handler
           */
          
          /* COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coretod.c,  v 1.24 2008/12/22 05:52:31 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _TOD_Handler_initialization
           *
           * This routine initializes the time of day handler.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      36  void _TOD_Handler_initialization(  void )
          {
           /* POSIX format TOD (  timespec ) */
           _Timestamp_Set(   &_TOD_Now,   TOD_SECONDS_1970_THROUGH_1988,   0  );
          
           /* Uptime (  timespec ) */
           _Timestamp_Set_to_zero(   &_TOD_Uptime  );
          
           /* TOD has not been set */
           _TOD_Is_set = false;
           _TOD_Activate(   );
          }

score/src/coretodget.c

       1  /*
           * Time of Day (  TOD ) Handler - get TOD
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coretodget.c,  v 1.4 2008/12/08 19:41:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/timespec.h>
          #include <rtems/score/timestamp.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*
           * _TOD_Get
           *
           * This routine is used to obtain the current date and time.
           *
           * Input parameters:
           * time - pointer to the time and date structure
           *
           * Output parameters: NONE
           */
          
      36  void _TOD_Get(  
           struct timespec *time
           )
          {
           ISR_Level level;
           Timestamp_Control offset;
           Timestamp_Control now;
           long nanoseconds;
          
           /* assume time checked for NULL by caller */
          
           /* _TOD_Now is the native current time */
           nanoseconds = 0;
           _ISR_Disable(   level  );
           now = _TOD_Now;
           if (   _Watchdog_Nanoseconds_since_tick_handler  )
           nanoseconds = (  *_Watchdog_Nanoseconds_since_tick_handler )(   );
           _ISR_Enable(   level  );
          
           _Timestamp_Set(   &offset,   0,   nanoseconds  );
           _Timestamp_Add_to(   &now,   &offset  );
           _Timestamp_To_timespec(   &now,   time  );
          }

score/src/coretodgetuptime.c

       1  /*
           * Time of Day (  TOD ) Handler - get uptime
           */
          
          /* COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coretodgetuptime.c,  v 1.5 2008/12/10 22:13:28 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/timestamp.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*
           * _TOD_Get_uptime
           *
           * This routine is used to obtain the system uptime
           *
           * Input parameters:
           * time - pointer to the timestamp structure
           *
           * Output parameters: NONE
           */
          
      36  void _TOD_Get_uptime(  
           Timestamp_Control *uptime
           )
          {
           ISR_Level level;
           Timestamp_Control offset;
           Timestamp_Control up;
           long nanoseconds;
          
           /* assume time checked for NULL by caller */
          
           /* _TOD_Uptime is in native timestamp format */
           nanoseconds = 0;
           _ISR_Disable(   level  );
           up = _TOD_Uptime;
           if (   _Watchdog_Nanoseconds_since_tick_handler  )
           nanoseconds = (  *_Watchdog_Nanoseconds_since_tick_handler )(   );
           _ISR_Enable(   level  );
          
           _Timestamp_Set(   &offset,   0,   nanoseconds  );
           _Timestamp_Add_to(   &up,   &offset  );
           *uptime = up;
          }

score/src/coretodgetuptimetimespec.c

       1  /*
           * Time of Day (  TOD ) Handler - get uptime
           */
          
          /* COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coretodgetuptimetimespec.c,  v 1.1 2008/12/08 19:41:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/timestamp.h>
          #include <rtems/score/tod.h>
          
          /*
           * _TOD_Get_uptime_as_timespec
           *
           * This routine is used to obtain the system uptime
           *
           * Input parameters:
           * time - pointer to the timestamp structure
           *
           * Output parameters: NONE
           */
          
      35  void _TOD_Get_uptime_as_timespec(  
           struct timespec *uptime
           )
          {
           Timestamp_Control uptime_ts;
          
           /* assume time checked for NULL by caller */
           _TOD_Get_uptime(   &uptime_ts  );
           _Timestamp_To_timespec(   &uptime_ts,   uptime  );
          }

score/src/coretodmsecstoticks.c

       1  /* COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coretodmsecstoticks.c,  v 1.1 2008/12/16 20:53:33 joel Exp $
           */
          
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/tod.h>
          
      20  uint32_t TOD_MILLISECONDS_TO_TICKS(  
           uint32_t milliseconds
           )
          {
           return (  milliseconds / rtems_configuration_get_milliseconds_per_tick(   ) );
          }

score/src/coretodset.c

       1  /*
           * Time of Day (  TOD ) Handler -- Set Time
           */
          
          /* COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coretodset.c,  v 1.11 2008/12/22 05:52:31 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/timestamp.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _TOD_Set
           *
           * This rountine sets the current date and time with the specified
           * new date and time structure.
           *
           * Input parameters:
           * time - pointer to the time and date structure
           *
           * Output parameters: NONE
           */
          
      39  void _TOD_Set(  
           const struct timespec *time
           )
          {
           long seconds;
          
           _Thread_Disable_dispatch(   );
           _TOD_Deactivate(   );
          
           seconds = _TOD_Seconds_since_epoch(   );
          
           if (   time->tv_sec < seconds  )
           _Watchdog_Adjust_seconds(   WATCHDOG_BACKWARD,   seconds - time->tv_sec  );
           else
           _Watchdog_Adjust_seconds(   WATCHDOG_FORWARD,   time->tv_sec - seconds  );
          
           /* POSIX format TOD (  timespec ) */
           _Timestamp_Set(   &_TOD_Now,   time->tv_sec,   time->tv_nsec  );
           _TOD_Is_set = true;
          
           _TOD_Activate(   );
          
           _Thread_Enable_dispatch(   );
          }

score/src/coretodtickle.c

       1  /*
           * Time of Day (  TOD ) Handler -- Tickle Ticks
           */
          
          /* COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coretodtickle.c,  v 1.10 2008/12/16 20:53:33 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/timestamp.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/config.h>
          
          /*PAGE
           *
           * _TOD_Tickle_ticks
           *
           * This routine processes a clock tick.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      38  void _TOD_Tickle_ticks(   void  )
          {
           Timestamp_Control tick;
           uint32_t seconds;
          
           /* Convert the tick quantum to a timestamp */
           _Timestamp_Set(   &tick,   0,   rtems_configuration_get_nanoseconds_per_tick(   )  );
          
           /* Update the counter of ticks since boot */
           _Watchdog_Ticks_since_boot += 1;
          
           /* Update the timespec format uptime */
           _Timestamp_Add_to(   &_TOD_Uptime,   &tick  );
           /* we do not care how much the uptime changed */
          
           /* Update the timespec format TOD */
           seconds = _Timestamp_Add_to_at_tick(   &_TOD_Now,   &tick  );
           while (   seconds  ) {
           _Watchdog_Tickle_seconds(   );
           seconds--;
           }
          }
          

score/src/coretodtickspersec.c

       1  /* COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coretodtickspersec.c,  v 1.1 2008/12/16 20:53:34 joel Exp $
           */
          
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/tod.h>
          
      20  uint32_t TOD_TICKS_PER_SECOND_method(  void )
          {
           return (  TOD_MICROSECONDS_PER_SECOND /
           rtems_configuration_get_microseconds_per_tick(   ) );
          }

score/src/coretodusectoticks.c

       1  /* COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: coretodusectoticks.c,  v 1.1 2008/12/16 20:53:34 joel Exp $
           */
          
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/tod.h>
          
      20  uint32_t TOD_MICROSECONDS_TO_TICKS(  
           uint32_t microseconds
           )
          {
           return (  microseconds / rtems_configuration_get_microseconds_per_tick(   ) );
          }

score/src/heap.c

       1  /**
           * @file
           *
           * @ingroup ScoreHeap
           *
           * @brief Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2009.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * Copyright (  c ) 2009,   2010 embedded brains GmbH.
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: heap.c,  v 1.39 2010/08/25 12:35:52 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          
          #include <rtems/system.h>
          #include <rtems/score/heap.h>
          #include <rtems/score/interr.h>
          
          #if CPU_ALIGNMENT == 0 || CPU_ALIGNMENT % 2 != 0
           #error "invalid CPU_ALIGNMENT value"
          #endif
          
          static uint32_t instance = 0;
          
          /*PAGE
           *
           * _Heap_Initialize
           *
           * This kernel routine initializes a heap.
           *
           * Input parameters:
           * heap - pointer to heap header
           * area_begin - starting address of heap
           * size - size of heap
           * page_size - allocatable unit of memory
           *
           * Output parameters:
           * returns - maximum memory available if RTEMS_SUCCESSFUL
           * 0 - otherwise
           *
           * This is what a heap looks like in memory immediately after initialization:
           *
           *
           * +--------------------------------+ <- begin = area_begin
           * | unused space due to alignment |
           * | size < page_size |
           * 0 +--------------------------------+ <- first block
           * | prev_size = page_size |
           * 4 +--------------------------------+
           * | size = size0 | 1 |
           * 8 +---------------------+----------+ <- aligned on page_size
           * | next = HEAP_TAIL | |
           * 12 +---------------------+ |
           * | prev = HEAP_HEAD | memory |
           * +---------------------+ |
           * | available |
           * | |
           * | for allocation |
           * | |
           * size0 +--------------------------------+ <- last dummy block
           * | prev_size = size0 |
           * +4 +--------------------------------+
           * | size = page_size | 0 | <- prev block is free
           * +8 +--------------------------------+ <- aligned on page_size
           * | unused space due to alignment |
           * | size < page_size |
           * +--------------------------------+ <- end = begin + size
           *
           * Below is what a heap looks like after first allocation of SIZE bytes using
           * _Heap_allocate(   ). BSIZE stands for SIZE + 4 aligned up on 'page_size'
           * boundary.
           * [NOTE: If allocation were performed by _Heap_Allocate_aligned(   ),   the
           * block size BSIZE is defined differently,   and previously free block will
           * be split so that upper part of it will become used block (  see
           * 'heapallocatealigned.c' for details ).]
           *
           * +--------------------------------+ <- begin = area_begin
           * | unused space due to alignment |
           * | size < page_size |
           * 0 +--------------------------------+ <- used block
           * | prev_size = page_size |
           * 4 +--------------------------------+
           * | size = BSIZE | 1 | <- prev block is used
           * 8 +--------------------------------+ <- aligned on page_size
           * | . | Pointer returned to the user
           * | . | is 8 for _Heap_Allocate(   )
           * | . | and is in range
           * 8 + | user-accessible | [8,  8+page_size ) for
           * page_size +- - - - - -+ _Heap_Allocate_aligned(   )
           * | area |
           * | . |
           * BSIZE +- - - - - . - - - - -+ <- free block
           * | . |
           * BSIZE +4 +--------------------------------+
           * | size = S = size0 - BSIZE | 1 | <- prev block is used
           * BSIZE +8 +-------------------+------------+ <- aligned on page_size
           * | next = HEAP_TAIL | |
           * BSIZE +12 +-------------------+ |
           * | prev = HEAP_HEAD | memory |
           * +-------------------+ |
           * | . available |
           * | . |
           * | . for |
           * | . |
           * BSIZE +S+0 +-------------------+ allocation + <- last dummy block
           * | prev_size = S | |
           * +S+4 +-------------------+------------+
           * | size = page_size | 0 | <- prev block is free
           * +S+8 +--------------------------------+ <- aligned on page_size
           * | unused space due to alignment |
           * | size < page_size |
           * +--------------------------------+ <- end = begin + size
           *
           */
          
          #ifdef HEAP_PROTECTION
     130   static void _Heap_Protection_block_initialize_default(  
           Heap_Control *heap,  
           Heap_Block *block
            )
           {
           block->Protection_begin.protector [0] = HEAP_BEGIN_PROTECTOR_0;
           block->Protection_begin.protector [1] = HEAP_BEGIN_PROTECTOR_1;
           block->Protection_begin.next_delayed_free_block = NULL;
           block->Protection_begin.task = _Thread_Executing;
           block->Protection_begin.tag = NULL;
           block->Protection_end.protector [0] = HEAP_END_PROTECTOR_0;
           block->Protection_end.protector [1] = HEAP_END_PROTECTOR_1;
           }
          
     144   static void _Heap_Protection_block_check_default(  
           Heap_Control *heap,  
           Heap_Block *block
            )
           {
           if (  
           block->Protection_begin.protector [0] != HEAP_BEGIN_PROTECTOR_0
           || block->Protection_begin.protector [1] != HEAP_BEGIN_PROTECTOR_1
           || block->Protection_end.protector [0] != HEAP_END_PROTECTOR_0
           || block->Protection_end.protector [1] != HEAP_END_PROTECTOR_1
            ) {
           _Heap_Protection_block_error(   heap,   block  );
           }
           }
          
     159   static void _Heap_Protection_block_error_default(  
           Heap_Control *heap,  
           Heap_Block *block
            )
           {
           /* FIXME */
           _Internal_error_Occurred(   0xdeadbeef,   false,   0xdeadbeef  );
           }
          #endif
          
     169  bool _Heap_Get_first_and_last_block(  
           uintptr_t heap_area_begin,  
           uintptr_t heap_area_size,  
           uintptr_t page_size,  
           uintptr_t min_block_size,  
           Heap_Block **first_block_ptr,  
           Heap_Block **last_block_ptr
           )
          {
           uintptr_t const heap_area_end = heap_area_begin + heap_area_size;
           uintptr_t const alloc_area_begin =
           _Heap_Align_up(   heap_area_begin + HEAP_BLOCK_HEADER_SIZE,   page_size  );
           uintptr_t const first_block_begin =
           alloc_area_begin - HEAP_BLOCK_HEADER_SIZE;
           uintptr_t const overhead =
           HEAP_BLOCK_HEADER_SIZE + (  first_block_begin - heap_area_begin );
           uintptr_t const first_block_size =
           _Heap_Align_down(   heap_area_size - overhead,   page_size  );
           Heap_Block *const first_block = (  Heap_Block * ) first_block_begin;
           Heap_Block *const last_block =
           _Heap_Block_at(   first_block,   first_block_size  );
          
           if (  
           heap_area_end < heap_area_begin
           || heap_area_size <= overhead
           || first_block_size < min_block_size
            ) {
           /* Invalid area or area too small */
           return false;
           }
          
           *first_block_ptr = first_block;
           *last_block_ptr = last_block;
          
           return true;
          }
          
     206  uintptr_t _Heap_Initialize(  
           Heap_Control *heap,  
           void *heap_area_begin_ptr,  
           uintptr_t heap_area_size,  
           uintptr_t page_size
           )
          {
           Heap_Statistics *const stats = &heap->stats;
           uintptr_t const heap_area_begin = (  uintptr_t ) heap_area_begin_ptr;
           uintptr_t const heap_area_end = heap_area_begin + heap_area_size;
           uintptr_t first_block_begin = 0;
           uintptr_t first_block_size = 0;
           uintptr_t last_block_begin = 0;
           uintptr_t min_block_size = 0;
           bool area_ok = false;
           Heap_Block *first_block = NULL;
           Heap_Block *last_block = NULL;
          
           if (   page_size == 0  ) {
           page_size = CPU_ALIGNMENT;
           } else {
           page_size = _Heap_Align_up(   page_size,   CPU_ALIGNMENT  );
          
           if (   page_size < CPU_ALIGNMENT  ) {
           /* Integer overflow */
           return 0;
           }
           }
           min_block_size = _Heap_Align_up(   sizeof(   Heap_Block  ),   page_size  );
          
           area_ok = _Heap_Get_first_and_last_block(  
           heap_area_begin,  
           heap_area_size,  
           page_size,  
           min_block_size,  
           &first_block,  
           &last_block
            );
           if (   !area_ok  ) {
           return 0;
           }
          
           memset(  heap,   0,   sizeof(  *heap ) );
          
           #ifdef HEAP_PROTECTION
           heap->Protection.block_initialize = _Heap_Protection_block_initialize_default;
           heap->Protection.block_check = _Heap_Protection_block_check_default;
           heap->Protection.block_error = _Heap_Protection_block_error_default;
           #endif
          
           first_block_begin = (  uintptr_t ) first_block;
           last_block_begin = (  uintptr_t ) last_block;
           first_block_size = last_block_begin - first_block_begin;
          
           /* First block */
           first_block->prev_size = heap_area_end;
           first_block->size_and_flag = first_block_size | HEAP_PREV_BLOCK_USED;
           first_block->next = _Heap_Free_list_tail(   heap  );
           first_block->prev = _Heap_Free_list_head(   heap  );
           _Heap_Protection_block_initialize(   heap,   first_block  );
          
           /* Heap control */
           heap->page_size = page_size;
           heap->min_block_size = min_block_size;
           heap->area_begin = heap_area_begin;
           heap->area_end = heap_area_end;
           heap->first_block = first_block;
           heap->last_block = last_block;
           _Heap_Free_list_head(   heap  )->next = first_block;
           _Heap_Free_list_tail(   heap  )->prev = first_block;
          
           /* Last block */
           last_block->prev_size = first_block_size;
           last_block->size_and_flag = 0;
           _Heap_Set_last_block_size(   heap  );
           _Heap_Protection_block_initialize(   heap,   last_block  );
          
           /* Statistics */
           stats->size = first_block_size;
           stats->free_size = first_block_size;
           stats->min_free_size = first_block_size;
           stats->free_blocks = 1;
           stats->max_free_blocks = 1;
           stats->instance = instance++;
          
           _HAssert(   _Heap_Is_aligned(   heap->page_size,   CPU_ALIGNMENT  )  );
           _HAssert(   _Heap_Is_aligned(   heap->min_block_size,   page_size  )  );
           _HAssert(  
           _Heap_Is_aligned(   _Heap_Alloc_area_of_block(   first_block  ),   page_size  )
            );
           _HAssert(  
           _Heap_Is_aligned(   _Heap_Alloc_area_of_block(   last_block  ),   page_size  )
            );
          
           return first_block_size;
          }
          
     303  static void _Heap_Block_split(  
           Heap_Control *heap,  
           Heap_Block *block,  
           Heap_Block *free_list_anchor,  
           uintptr_t alloc_size
           )
          {
           Heap_Statistics *const stats = &heap->stats;
          
           uintptr_t const page_size = heap->page_size;
           uintptr_t const min_block_size = heap->min_block_size;
           uintptr_t const min_alloc_size = min_block_size - HEAP_BLOCK_HEADER_SIZE;
          
           uintptr_t const block_size = _Heap_Block_size(   block  );
          
           uintptr_t const used_size =
           _Heap_Max(   alloc_size,   min_alloc_size  ) + HEAP_BLOCK_HEADER_SIZE;
           uintptr_t const used_block_size = _Heap_Align_up(   used_size,   page_size  );
          
           uintptr_t const free_size = block_size + HEAP_ALLOC_BONUS - used_size;
           uintptr_t const free_size_limit = min_block_size + HEAP_ALLOC_BONUS;
          
           Heap_Block *next_block = _Heap_Block_at(   block,   block_size  );
          
           _HAssert(   used_size <= block_size + HEAP_ALLOC_BONUS  );
           _HAssert(   used_size + free_size == block_size + HEAP_ALLOC_BONUS  );
          
           if (   free_size >= free_size_limit  ) {
           Heap_Block *const free_block = _Heap_Block_at(   block,   used_block_size  );
           uintptr_t free_block_size = block_size - used_block_size;
          
           _HAssert(   used_block_size + free_block_size == block_size  );
          
           _Heap_Block_set_size(   block,   used_block_size  );
          
           /* Statistics */
           stats->free_size += free_block_size;
          
           if (   _Heap_Is_used(   next_block  )  ) {
           _Heap_Free_list_insert_after(   free_list_anchor,   free_block  );
          
           /* Statistics */
           ++stats->free_blocks;
           } else {
           uintptr_t const next_block_size = _Heap_Block_size(   next_block  );
          
           _Heap_Free_list_replace(   next_block,   free_block  );
          
           free_block_size += next_block_size;
          
           next_block = _Heap_Block_at(   free_block,   free_block_size  );
           }
          
           free_block->size_and_flag = free_block_size | HEAP_PREV_BLOCK_USED;
          
           next_block->prev_size = free_block_size;
           next_block->size_and_flag &= ~HEAP_PREV_BLOCK_USED;
          
           _Heap_Protection_block_initialize(   heap,   free_block  );
           } else {
           next_block->size_and_flag |= HEAP_PREV_BLOCK_USED;
           }
          }
          
     367  static Heap_Block *_Heap_Block_allocate_from_begin(  
           Heap_Control *heap,  
           Heap_Block *block,  
           Heap_Block *free_list_anchor,  
           uintptr_t alloc_size
           )
          {
           _Heap_Block_split(   heap,   block,   free_list_anchor,   alloc_size  );
          
           return block;
          }
          
     379  static Heap_Block *_Heap_Block_allocate_from_end(  
           Heap_Control *heap,  
           Heap_Block *block,  
           Heap_Block *free_list_anchor,  
           uintptr_t alloc_begin,  
           uintptr_t alloc_size
           )
          {
           Heap_Statistics *const stats = &heap->stats;
          
           uintptr_t block_begin = (  uintptr_t ) block;
           uintptr_t block_size = _Heap_Block_size(   block  );
           uintptr_t block_end = block_begin + block_size;
          
           Heap_Block *const new_block =
           _Heap_Block_of_alloc_area(   alloc_begin,   heap->page_size  );
           uintptr_t const new_block_begin = (  uintptr_t ) new_block;
           uintptr_t const new_block_size = block_end - new_block_begin;
          
           block_end = new_block_begin;
           block_size = block_end - block_begin;
          
           _HAssert(   block_size >= heap->min_block_size  );
           _HAssert(   new_block_size >= heap->min_block_size  );
          
           /* Statistics */
           stats->free_size += block_size;
          
           if (   _Heap_Is_prev_used(   block  )  ) {
           _Heap_Free_list_insert_after(   free_list_anchor,   block  );
          
           free_list_anchor = block;
          
           /* Statistics */
           ++stats->free_blocks;
           } else {
           Heap_Block *const prev_block = _Heap_Prev_block(   block  );
           uintptr_t const prev_block_size = _Heap_Block_size(   prev_block  );
          
           block = prev_block;
           block_begin = (  uintptr_t ) block;
           block_size += prev_block_size;
           }
          
           block->size_and_flag = block_size | HEAP_PREV_BLOCK_USED;
          
           new_block->prev_size = block_size;
           new_block->size_and_flag = new_block_size;
          
           _Heap_Block_split(   heap,   new_block,   free_list_anchor,   alloc_size  );
          
           return new_block;
          }
          
     433  Heap_Block *_Heap_Block_allocate(  
           Heap_Control *heap,  
           Heap_Block *block,  
           uintptr_t alloc_begin,  
           uintptr_t alloc_size
           )
          {
           Heap_Statistics *const stats = &heap->stats;
          
           uintptr_t const alloc_area_begin = _Heap_Alloc_area_of_block(   block  );
           uintptr_t const alloc_area_offset = alloc_begin - alloc_area_begin;
          
           Heap_Block *free_list_anchor = NULL;
          
           _HAssert(   alloc_area_begin <= alloc_begin  );
          
           if (   _Heap_Is_free(   block  )  ) {
           free_list_anchor = block->prev;
          
           _Heap_Free_list_remove(   block  );
          
           /* Statistics */
           --stats->free_blocks;
           ++stats->used_blocks;
           stats->free_size -= _Heap_Block_size(   block  );
           } else {
           free_list_anchor = _Heap_Free_list_head(   heap  );
           }
          
           if (   alloc_area_offset < heap->page_size  ) {
           alloc_size += alloc_area_offset;
          
           block = _Heap_Block_allocate_from_begin(  
           heap,  
           block,  
           free_list_anchor,  
           alloc_size
            );
           } else {
           block = _Heap_Block_allocate_from_end(  
           heap,  
           block,  
           free_list_anchor,  
           alloc_begin,  
           alloc_size
            );
           }
          
           /* Statistics */
           if (   stats->min_free_size > stats->free_size  ) {
           stats->min_free_size = stats->free_size;
           }
          
           _Heap_Protection_block_initialize(   heap,   block  );
          
           return block;
          }

score/src/heapallocate.c

       1  /**
           * @file
           *
           * @ingroup ScoreHeap
           *
           * @brief Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * Copyright (  c ) 2009 embedded brains GmbH.
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: heapallocate.c,  v 1.18 2010/08/25 12:35:52 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/heap.h>
          
          #ifndef HEAP_PROTECTION
           #define _Heap_Protection_free_delayed_blocks(   heap,   alloc_begin  ) false
          #else
      33   static bool _Heap_Protection_free_delayed_blocks(  
           Heap_Control *heap,  
           uintptr_t alloc_begin
            )
           {
           bool search_again = false;
           uintptr_t const blocks_to_free_count =
           (  heap->Protection.delayed_free_block_count + 1 ) / 2;
          
           if (   alloc_begin == 0 && blocks_to_free_count > 0  ) {
           Heap_Block *block_to_free = heap->Protection.first_delayed_free_block;
           uintptr_t count = 0;
          
           for (   count = 0; count < blocks_to_free_count; ++count  ) {
           Heap_Block *next_block_to_free =
           block_to_free->Protection_begin.next_delayed_free_block;
          
           block_to_free->Protection_begin.next_delayed_free_block =
           HEAP_PROTECTION_OBOLUS;
          
           _Heap_Free(  
           heap,  
           (  void * ) _Heap_Alloc_area_of_block(   block_to_free  )
            );
          
           block_to_free = next_block_to_free;
           }
          
           heap->Protection.delayed_free_block_count -= blocks_to_free_count;
           heap->Protection.first_delayed_free_block = block_to_free;
          
           search_again = true;
           }
          
           return search_again;
           }
          #endif
          
          #ifdef RTEMS_HEAP_DEBUG
      72   static void _Heap_Check_allocation(  
           const Heap_Control *heap,  
           const Heap_Block *block,  
           uintptr_t alloc_begin,  
           uintptr_t alloc_size,  
           uintptr_t alignment,  
           uintptr_t boundary
            )
           {
           uintptr_t const min_block_size = heap->min_block_size;
           uintptr_t const page_size = heap->page_size;
          
           uintptr_t const block_begin = (  uintptr_t ) block;
           uintptr_t const block_size = _Heap_Block_size(   block  );
           uintptr_t const block_end = block_begin + block_size;
          
           uintptr_t const alloc_end = alloc_begin + alloc_size;
          
           uintptr_t const alloc_area_begin = _Heap_Alloc_area_of_block(   block  );
           uintptr_t const alloc_area_offset = alloc_begin - alloc_area_begin;
          
           _HAssert(   block_size >= min_block_size  );
           _HAssert(   block_begin < block_end  );
           _HAssert(  
           _Heap_Is_aligned(   block_begin + HEAP_BLOCK_HEADER_SIZE,   page_size  )
            );
           _HAssert(  
           _Heap_Is_aligned(   block_size,   page_size  )
            );
          
           _HAssert(   alloc_end <= block_end + HEAP_ALLOC_BONUS  );
           _HAssert(   alloc_area_begin == block_begin + HEAP_BLOCK_HEADER_SIZE );
           _HAssert(   alloc_area_offset < page_size  );
          
           _HAssert(   _Heap_Is_aligned(   alloc_area_begin,   page_size  )  );
           if (   alignment == 0  ) {
           _HAssert(   alloc_begin == alloc_area_begin  );
           } else {
           _HAssert(   _Heap_Is_aligned(   alloc_begin,   alignment  )  );
           }
          
           if (   boundary != 0  ) {
           uintptr_t boundary_line = _Heap_Align_down(   alloc_end,   boundary  );
          
           _HAssert(   alloc_size <= boundary  );
           _HAssert(   boundary_line <= alloc_begin || alloc_end <= boundary_line  );
           }
           }
          #else
           #define _Heap_Check_allocation(   h,   b,   ab,   as,   ag,   bd  ) (  (  void ) 0 )
          #endif
          
     124  static uintptr_t _Heap_Check_block(  
           const Heap_Control *heap,  
           const Heap_Block *block,  
           uintptr_t alloc_size,  
           uintptr_t alignment,  
           uintptr_t boundary
           )
          {
           uintptr_t const page_size = heap->page_size;
           uintptr_t const min_block_size = heap->min_block_size;
          
           uintptr_t const block_begin = (  uintptr_t ) block;
           uintptr_t const block_size = _Heap_Block_size(   block  );
           uintptr_t const block_end = block_begin + block_size;
          
           uintptr_t const alloc_begin_floor = _Heap_Alloc_area_of_block(   block  );
           uintptr_t const alloc_begin_ceiling = block_end - min_block_size
           + HEAP_BLOCK_HEADER_SIZE + page_size - 1;
          
           uintptr_t alloc_end = block_end + HEAP_ALLOC_BONUS;
           uintptr_t alloc_begin = alloc_end - alloc_size;
          
           alloc_begin = _Heap_Align_down(   alloc_begin,   alignment  );
          
           /* Ensure that the we have a valid new block at the end */
           if (   alloc_begin > alloc_begin_ceiling  ) {
           alloc_begin = _Heap_Align_down(   alloc_begin_ceiling,   alignment  );
           }
          
           alloc_end = alloc_begin + alloc_size;
          
           /* Ensure boundary constaint */
           if (   boundary != 0  ) {
           uintptr_t const boundary_floor = alloc_begin_floor + alloc_size;
           uintptr_t boundary_line = _Heap_Align_down(   alloc_end,   boundary  );
          
           while (   alloc_begin < boundary_line && boundary_line < alloc_end  ) {
           if (   boundary_line < boundary_floor  ) {
           return 0;
           }
           alloc_begin = boundary_line - alloc_size;
           alloc_begin = _Heap_Align_down(   alloc_begin,   alignment  );
           alloc_end = alloc_begin + alloc_size;
           boundary_line = _Heap_Align_down(   alloc_end,   boundary  );
           }
           }
          
           /* Ensure that the we have a valid new block at the beginning */
           if (   alloc_begin >= alloc_begin_floor  ) {
           uintptr_t const alloc_block_begin =
           (  uintptr_t ) _Heap_Block_of_alloc_area(   alloc_begin,   page_size  );
           uintptr_t const free_size = alloc_block_begin - block_begin;
          
           if (   free_size >= min_block_size || free_size == 0  ) {
           return alloc_begin;
           }
           }
          
           return 0;
          }
          
     185  void *_Heap_Allocate_aligned_with_boundary(  
           Heap_Control *heap,  
           uintptr_t alloc_size,  
           uintptr_t alignment,  
           uintptr_t boundary
           )
          {
           Heap_Statistics *const stats = &heap->stats;
           uintptr_t const block_size_floor = alloc_size + HEAP_BLOCK_HEADER_SIZE
           - HEAP_ALLOC_BONUS;
           uintptr_t const page_size = heap->page_size;
           Heap_Block *block = NULL;
           uintptr_t alloc_begin = 0;
           uint32_t search_count = 0;
           bool search_again = false;
          
           if (   block_size_floor < alloc_size  ) {
           /* Integer overflow occured */
           return NULL;
           }
          
           if (   boundary != 0  ) {
           if (   boundary < alloc_size  ) {
           return NULL;
           }
          
           if (   alignment == 0  ) {
           alignment = page_size;
           }
           }
          
           do {
           Heap_Block *const free_list_tail = _Heap_Free_list_tail(   heap  );
          
           block = _Heap_Free_list_first(   heap  );
           while (   block != free_list_tail  ) {
           _HAssert(   _Heap_Is_prev_used(   block  )  );
          
           _Heap_Protection_block_check(   heap,   block  );
          
           /*
           * The HEAP_PREV_BLOCK_USED flag is always set in the block size_and_flag
           * field. Thus the value is about one unit larger than the real block
           * size. The greater than operator takes this into account.
           */
           if (   block->size_and_flag > block_size_floor  ) {
           if (   alignment == 0  ) {
           alloc_begin = _Heap_Alloc_area_of_block(   block  );
           } else {
           alloc_begin = _Heap_Check_block(  
           heap,  
           block,  
           alloc_size,  
           alignment,  
           boundary
            );
           }
           }
          
           /* Statistics */
           ++search_count;
          
           if (   alloc_begin != 0  ) {
           break;
           }
          
           block = block->next;
           }
          
           search_again = _Heap_Protection_free_delayed_blocks(   heap,   alloc_begin  );
           } while (   search_again  );
          
           if (   alloc_begin != 0  ) {
           /* Statistics */
           ++stats->allocs;
           stats->searches += search_count;
          
           block = _Heap_Block_allocate(   heap,   block,   alloc_begin,   alloc_size  );
          
           _Heap_Check_allocation(  
           heap,  
           block,  
           alloc_begin,  
           alloc_size,  
           alignment,  
           boundary
            );
           }
          
           /* Statistics */
           if (   stats->max_search < search_count  ) {
           stats->max_search = search_count;
           }
          
           return (  void * ) alloc_begin;
          }

score/src/heapextend.c

       1  /**
           * @file
           *
           * @ingroup ScoreHeap
           *
           * @brief Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * Copyright (  c ) 2010 embedded brains GmbH.
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: heapextend.c,  v 1.18 2010/08/25 12:35:52 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/heap.h>
          
      30  static void _Heap_Free_block(   Heap_Control *heap,   Heap_Block *block  )
          {
           Heap_Statistics *const stats = &heap->stats;
          
           /* Statistics */
           ++stats->used_blocks;
           --stats->frees;
          
           _Heap_Free(   heap,   (  void * ) _Heap_Alloc_area_of_block(   block  ) );
          }
          
      41  static void _Heap_Merge_below(  
           Heap_Control *heap,  
           uintptr_t extend_area_begin,  
           Heap_Block *first_block
           )
          {
           uintptr_t const page_size = heap->page_size;
           uintptr_t const new_first_block_alloc_begin =
           _Heap_Align_up(   extend_area_begin + HEAP_BLOCK_HEADER_SIZE,   page_size  );
           uintptr_t const new_first_block_begin =
           new_first_block_alloc_begin - HEAP_BLOCK_HEADER_SIZE;
           uintptr_t const first_block_begin = (  uintptr_t ) first_block;
           uintptr_t const new_first_block_size =
           first_block_begin - new_first_block_begin;
           Heap_Block *const new_first_block = (  Heap_Block * ) new_first_block_begin;
          
           new_first_block->prev_size = first_block->prev_size;
           new_first_block->size_and_flag = new_first_block_size | HEAP_PREV_BLOCK_USED;
          
           _Heap_Free_block(   heap,   new_first_block  );
          }
          
      63  static void _Heap_Merge_above(  
           Heap_Control *heap,  
           Heap_Block *last_block,  
           uintptr_t extend_area_end
           )
          {
           uintptr_t const page_size = heap->page_size;
           uintptr_t const last_block_begin = (  uintptr_t ) last_block;
           uintptr_t const last_block_new_size = _Heap_Align_down(  
           extend_area_end - last_block_begin - HEAP_BLOCK_HEADER_SIZE,  
           page_size
            );
           Heap_Block *const new_last_block =
           _Heap_Block_at(   last_block,   last_block_new_size  );
          
           new_last_block->size_and_flag =
           (  last_block->size_and_flag - last_block_new_size )
           | HEAP_PREV_BLOCK_USED;
          
           _Heap_Block_set_size(   last_block,   last_block_new_size  );
          
           _Heap_Free_block(   heap,   last_block  );
          }
          
      87  static void _Heap_Link_below(  
           Heap_Block *link,  
           Heap_Block *last_block
           )
          {
           uintptr_t const last_block_begin = (  uintptr_t ) last_block;
           uintptr_t const link_begin = (  uintptr_t ) link;
          
           last_block->size_and_flag =
           (  link_begin - last_block_begin ) | HEAP_PREV_BLOCK_USED;
          }
          
      99  static void _Heap_Link_above(  
           Heap_Block *link,  
           Heap_Block *first_block,  
           Heap_Block *last_block
           )
          {
           uintptr_t const link_begin = (  uintptr_t ) link;
           uintptr_t const first_block_begin = (  uintptr_t ) first_block;
          
           _Heap_Block_set_size(   link,   first_block_begin - link_begin  );
          
           last_block->size_and_flag |= HEAP_PREV_BLOCK_USED;
          }
          
     113  bool _Heap_Extend(  
           Heap_Control *heap,  
           void *extend_area_begin_ptr,  
           uintptr_t extend_area_size,  
           uintptr_t *extended_size_ptr
           )
          {
           Heap_Statistics *const stats = &heap->stats;
           Heap_Block *const first_block = heap->first_block;
           Heap_Block *start_block = first_block;
           Heap_Block *merge_below_block = NULL;
           Heap_Block *merge_above_block = NULL;
           Heap_Block *link_below_block = NULL;
           Heap_Block *link_above_block = NULL;
           Heap_Block *extend_first_block = NULL;
           Heap_Block *extend_last_block = NULL;
           uintptr_t const page_size = heap->page_size;
           uintptr_t const min_block_size = heap->min_block_size;
           uintptr_t const extend_area_begin = (  uintptr_t ) extend_area_begin_ptr;
           uintptr_t const extend_area_end = extend_area_begin + extend_area_size;
           uintptr_t const free_size = stats->free_size;
           uintptr_t extend_first_block_size = 0;
           uintptr_t extended_size = 0;
           bool extend_area_ok = false;
          
           if (   extend_area_end < extend_area_begin  ) {
           return false;
           }
          
           extend_area_ok = _Heap_Get_first_and_last_block(  
           extend_area_begin,  
           extend_area_size,  
           page_size,  
           min_block_size,  
           &extend_first_block,  
           &extend_last_block
            );
           if (  !extend_area_ok  ) {
           /* For simplicity we reject extend areas that are too small */
           return false;
           }
          
           do {
           uintptr_t const sub_area_begin = (  start_block != first_block ) ?
           (  uintptr_t ) start_block : heap->area_begin;
           uintptr_t const sub_area_end = start_block->prev_size;
           Heap_Block *const end_block =
           _Heap_Block_of_alloc_area(   sub_area_end,   page_size  );
          
           if (  
           sub_area_end > extend_area_begin && extend_area_end > sub_area_begin
            ) {
           return false;
           }
          
           if (   extend_area_end == sub_area_begin  ) {
           merge_below_block = start_block;
           } else if (   extend_area_end < sub_area_end  ) {
           link_below_block = start_block;
           }
          
           if (   sub_area_end == extend_area_begin  ) {
           start_block->prev_size = extend_area_end;
          
           merge_above_block = end_block;
           } else if (   sub_area_end < extend_area_begin  ) {
           link_above_block = end_block;
           }
          
           start_block = _Heap_Block_at(   end_block,   _Heap_Block_size(   end_block  )  );
           } while (   start_block != first_block  );
          
           if (   extend_area_begin < heap->area_begin  ) {
           heap->area_begin = extend_area_begin;
           } else if (   heap->area_end < extend_area_end  ) {
           heap->area_end = extend_area_end;
           }
          
           extend_first_block_size =
           (  uintptr_t ) extend_last_block - (  uintptr_t ) extend_first_block;
          
           extend_first_block->prev_size = extend_area_end;
           extend_first_block->size_and_flag =
           extend_first_block_size | HEAP_PREV_BLOCK_USED;
           _Heap_Protection_block_initialize(   heap,   extend_first_block  );
          
           extend_last_block->prev_size = extend_first_block_size;
           extend_last_block->size_and_flag = 0;
           _Heap_Protection_block_initialize(   heap,   extend_last_block  );
          
           if (   (  uintptr_t ) extend_first_block < (  uintptr_t ) heap->first_block  ) {
           heap->first_block = extend_first_block;
           } else if (   (  uintptr_t ) extend_last_block > (  uintptr_t ) heap->last_block  ) {
           heap->last_block = extend_last_block;
           }
          
           if (   merge_below_block != NULL  ) {
           _Heap_Merge_below(   heap,   extend_area_begin,   merge_below_block  );
           } else if (   link_below_block != NULL  ) {
           _Heap_Link_below(  
           link_below_block,  
           extend_last_block
            );
           }
          
           if (   merge_above_block != NULL  ) {
           _Heap_Merge_above(   heap,   merge_above_block,   extend_area_end  );
           } else if (   link_above_block != NULL  ) {
           _Heap_Link_above(  
           link_above_block,  
           extend_first_block,  
           extend_last_block
            );
           }
          
           if (   merge_below_block == NULL && merge_above_block == NULL  ) {
           _Heap_Free_block(   heap,   extend_first_block  );
           }
          
           _Heap_Set_last_block_size(   heap  );
          
           extended_size = stats->free_size - free_size;
          
           /* Statistics */
           stats->size += extended_size;
          
           if (   extended_size_ptr != NULL  )
           *extended_size_ptr = extended_size;
          
           return true;
          }

score/src/heapfree.c

       1  /**
           * @file
           *
           * @ingroup ScoreHeap
           *
           * @brief Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: heapfree.c,  v 1.14 2010/08/25 12:35:52 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/heap.h>
          
          #ifndef HEAP_PROTECTION
           #define _Heap_Protection_determine_block_free(   heap,   block  ) true
          #else
      30   static void _Heap_Protection_delay_block_free(  
           Heap_Control *heap,  
           Heap_Block *block
            )
           {
           uintptr_t *const pattern_begin = (  uintptr_t * )
           _Heap_Alloc_area_of_block(   block  );
           uintptr_t *const pattern_end = (  uintptr_t * )
           (  (  uintptr_t ) block + _Heap_Block_size(   block  ) + HEAP_ALLOC_BONUS );
           uintptr_t const delayed_free_block_count =
           heap->Protection.delayed_free_block_count;
           uintptr_t *current = NULL;
          
           block->Protection_begin.next_delayed_free_block = block;
           block->Protection_begin.task = _Thread_Executing;
          
           if (   delayed_free_block_count > 0  ) {
           Heap_Block *const last = heap->Protection.last_delayed_free_block;
          
           last->Protection_begin.next_delayed_free_block = block;
           } else {
           heap->Protection.first_delayed_free_block = block;
           }
           heap->Protection.last_delayed_free_block = block;
           heap->Protection.delayed_free_block_count = delayed_free_block_count + 1;
          
           for (   current = pattern_begin; current != pattern_end; ++current  ) {
           *current = HEAP_FREE_PATTERN;
           }
           }
          
      61   static void _Heap_Protection_check_free_block(  
           Heap_Control *heap,  
           Heap_Block *block
            )
           {
           uintptr_t *const pattern_begin = (  uintptr_t * )
           _Heap_Alloc_area_of_block(   block  );
           uintptr_t *const pattern_end = (  uintptr_t * )
           (  (  uintptr_t ) block + _Heap_Block_size(   block  ) + HEAP_ALLOC_BONUS );
           uintptr_t *current = NULL;
          
           for (   current = pattern_begin; current != pattern_end; ++current  ) {
           if (   *current != HEAP_FREE_PATTERN  ) {
           _Heap_Protection_block_error(   heap,   block  );
           break;
           }
           }
           }
          
      80   static bool _Heap_Protection_determine_block_free(  
           Heap_Control *heap,  
           Heap_Block *block
            )
           {
           bool do_free = true;
          
           /*
           * Sometimes after a free the allocated area is still in use. An example
           * is the task stack of a thread that deletes itself. The thread dispatch
           * disable level is a way to detect this use case.
           */
           if (   _Thread_Dispatch_disable_level == 0  ) {
           Heap_Block *const next = block->Protection_begin.next_delayed_free_block;
           if (   next == NULL  ) {
           _Heap_Protection_delay_block_free(   heap,   block  );
           do_free = false;
           } else if (   next == HEAP_PROTECTION_OBOLUS  ) {
           _Heap_Protection_check_free_block(   heap,   block  );
           } else {
           _Heap_Protection_block_error(   heap,   block  );
           }
           }
          
           return do_free;
           }
          #endif
          
     108  bool _Heap_Free(   Heap_Control *heap,   void *alloc_begin_ptr  )
          {
           Heap_Statistics *const stats = &heap->stats;
           uintptr_t alloc_begin = (  uintptr_t ) alloc_begin_ptr;
           Heap_Block *block =
           _Heap_Block_of_alloc_area(   alloc_begin,   heap->page_size  );
           Heap_Block *next_block = NULL;
           uintptr_t block_size = 0;
           uintptr_t next_block_size = 0;
           bool next_is_free = false;
          
           _Heap_Protection_block_check(   heap,   block  );
          
           if (   !_Heap_Is_block_in_heap(   heap,   block  )  ) {
           return false;
           }
          
           block_size = _Heap_Block_size(   block  );
           next_block = _Heap_Block_at(   block,   block_size  );
          
           _Heap_Protection_block_check(   heap,   next_block  );
          
           if (   !_Heap_Is_block_in_heap(   heap,   next_block  )  ) {
           _HAssert(   false  );
           return false;
           }
          
           if (   !_Heap_Is_prev_used(   next_block  )  ) {
           _Heap_Protection_block_error(   heap,   block  );
          
           return false;
           }
          
           if (   !_Heap_Protection_determine_block_free(   heap,   block  )  ) {
           return true;
           }
          
           next_block_size = _Heap_Block_size(   next_block  );
           next_is_free = next_block != heap->last_block
           && !_Heap_Is_prev_used(   _Heap_Block_at(   next_block,   next_block_size  ) );
          
           if (   !_Heap_Is_prev_used(   block  )  ) {
           uintptr_t const prev_size = block->prev_size;
           Heap_Block * const prev_block = _Heap_Block_at(   block,   -prev_size  );
          
           if (   !_Heap_Is_block_in_heap(   heap,   prev_block  )  ) {
           _HAssert(   false  );
           return(   false  );
           }
          
           /* As we always coalesce free blocks,   the block that preceedes prev_block
           must have been used. */
           if (   !_Heap_Is_prev_used (   prev_block )  ) {
           _HAssert(   false  );
           return(   false  );
           }
          
           if (   next_is_free  ) { /* coalesce both */
           uintptr_t const size = block_size + prev_size + next_block_size;
           _Heap_Free_list_remove(   next_block  );
           stats->free_blocks -= 1;
           prev_block->size_and_flag = size | HEAP_PREV_BLOCK_USED;
           next_block = _Heap_Block_at(   prev_block,   size  );
           _HAssert(  !_Heap_Is_prev_used(   next_block ) );
           next_block->prev_size = size;
           } else { /* coalesce prev */
           uintptr_t const size = block_size + prev_size;
           prev_block->size_and_flag = size | HEAP_PREV_BLOCK_USED;
           next_block->size_and_flag &= ~HEAP_PREV_BLOCK_USED;
           next_block->prev_size = size;
           }
           } else if (   next_is_free  ) { /* coalesce next */
           uintptr_t const size = block_size + next_block_size;
           _Heap_Free_list_replace(   next_block,   block  );
           block->size_and_flag = size | HEAP_PREV_BLOCK_USED;
           next_block = _Heap_Block_at(   block,   size  );
           next_block->prev_size = size;
           } else { /* no coalesce */
           /* Add 'block' to the head of the free blocks list as it tends to
           produce less fragmentation than adding to the tail. */
           _Heap_Free_list_insert_after(   _Heap_Free_list_head(   heap ),   block  );
           block->size_and_flag = block_size | HEAP_PREV_BLOCK_USED;
           next_block->size_and_flag &= ~HEAP_PREV_BLOCK_USED;
           next_block->prev_size = block_size;
          
           /* Statistics */
           ++stats->free_blocks;
           if (   stats->max_free_blocks < stats->free_blocks  ) {
           stats->max_free_blocks = stats->free_blocks;
           }
           }
          
           /* Statistics */
           --stats->used_blocks;
           ++stats->frees;
           stats->free_size += block_size;
          
           return(   true  );
          }

score/src/heapgetfreeinfo.c

       1  /**
           * @file
           *
           * @ingroup ScoreHeap
           *
           * @brief Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2004.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: heapgetfreeinfo.c,  v 1.6 2009/09/06 15:24:07 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/heap.h>
          
      28  void _Heap_Get_free_information(  
           Heap_Control *the_heap,  
           Heap_Information *info
           )
          {
           Heap_Block *the_block;
           Heap_Block *const tail = _Heap_Free_list_tail(  the_heap );
          
           info->number = 0;
           info->largest = 0;
           info->total = 0;
          
           for(  the_block = _Heap_Free_list_first(  the_heap );
           the_block != tail;
           the_block = the_block->next )
           {
           uint32_t const the_size = _Heap_Block_size(  the_block );
          
           /* As we always coalesce free blocks,   prev block must have been used. */
           _HAssert(  _Heap_Is_prev_used(  the_block ) );
          
           info->number++;
           info->total += the_size;
           if (   info->largest < the_size  )
           info->largest = the_size;
           }
          }

score/src/heapgetinfo.c

       1  /**
           * @file
           *
           * @ingroup ScoreHeap
           *
           * @brief Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: heapgetinfo.c,  v 1.12 2010/06/07 09:35:01 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/heap.h>
          
      30  void _Heap_Get_information(  
           Heap_Control *the_heap,  
           Heap_Information_block *the_info
           )
          {
           Heap_Block *the_block = the_heap->first_block;
           Heap_Block *const end = the_heap->last_block;
          
           memset(  the_info,   0,   sizeof(  *the_info ) );
          
           while (   the_block != end  ) {
           uintptr_t const the_size = _Heap_Block_size(  the_block );
           Heap_Block *const next_block = _Heap_Block_at(  the_block,   the_size );
           Heap_Information *info;
          
           if (   _Heap_Is_prev_used(  next_block )  )
           info = &the_info->Used;
           else
           info = &the_info->Free;
          
           info->number++;
           info->total += the_size;
           if (   info->largest < the_size  )
           info->largest = the_size;
          
           the_block = next_block;
           }
          }

score/src/heapresizeblock.c

       1  /**
           * @file
           *
           * @ingroup ScoreHeap
           *
           * @brief Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * Copyright (  c ) 2009 embedded brains GmbH.
           *
           * The license and distribution terms for this file may be
           * found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: heapresizeblock.c,  v 1.13 2010/08/25 12:35:52 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/heap.h>
          
      30  static Heap_Resize_status _Heap_Resize_block_checked(  
           Heap_Control *heap,  
           Heap_Block *block,  
           uintptr_t alloc_begin,  
           uintptr_t new_alloc_size,  
           uintptr_t *old_size,  
           uintptr_t *new_size
           )
          {
           Heap_Statistics *const stats = &heap->stats;
          
           uintptr_t const block_begin = (  uintptr_t ) block;
           uintptr_t block_size = _Heap_Block_size(   block  );
           uintptr_t block_end = block_begin + block_size;
          
           uintptr_t alloc_size = block_end - alloc_begin + HEAP_ALLOC_BONUS;
          
           Heap_Block *next_block = _Heap_Block_at(   block,   block_size  );
           uintptr_t next_block_size = _Heap_Block_size(   next_block  );
           bool next_block_is_free = _Heap_Is_free(   next_block  );;
          
           _HAssert(   _Heap_Is_block_in_heap(   heap,   next_block  )  );
           _HAssert(   _Heap_Is_prev_used(   next_block  )  );
          
           *old_size = alloc_size;
          
           if (   next_block_is_free  ) {
           block_size += next_block_size;
           alloc_size += next_block_size;
           }
          
           if (   new_alloc_size > alloc_size  ) {
           return HEAP_RESIZE_UNSATISFIED;
           }
          
           if (   next_block_is_free  ) {
           _Heap_Block_set_size(   block,   block_size  );
          
           _Heap_Free_list_remove(   next_block  );
          
           next_block = _Heap_Block_at(   block,   block_size  );
           next_block->size_and_flag |= HEAP_PREV_BLOCK_USED;
          
           /* Statistics */
           --stats->free_blocks;
           stats->free_size -= next_block_size;
           }
          
           block = _Heap_Block_allocate(   heap,   block,   alloc_begin,   new_alloc_size  );
          
           block_size = _Heap_Block_size(   block  );
           next_block = _Heap_Block_at(   block,   block_size  );
           *new_size = (  uintptr_t ) next_block - alloc_begin + HEAP_ALLOC_BONUS;
          
           /* Statistics */
           ++stats->resizes;
          
           return HEAP_RESIZE_SUCCESSFUL;
          }
          
      90  Heap_Resize_status _Heap_Resize_block(  
           Heap_Control *heap,  
           void *alloc_begin_ptr,  
           uintptr_t new_alloc_size,  
           uintptr_t *old_size,  
           uintptr_t *new_size
           )
          {
           uintptr_t const page_size = heap->page_size;
          
           uintptr_t const alloc_begin = (  uintptr_t ) alloc_begin_ptr;
          
           Heap_Block *const block = _Heap_Block_of_alloc_area(   alloc_begin,   page_size  );
          
           *old_size = 0;
           *new_size = 0;
          
           _Heap_Protection_block_check(   heap,   block  );
          
           if (   _Heap_Is_block_in_heap(   heap,   block  )  ) {
           return _Heap_Resize_block_checked(  
           heap,  
           block,  
           alloc_begin,  
           new_alloc_size,  
           old_size,  
           new_size
            );
           } else {
           return HEAP_RESIZE_FATAL_ERROR;
           }
          }

score/src/heapsizeofuserarea.c

       1  /**
           * @file
           *
           * @ingroup ScoreHeap
           *
           * @brief Heap Handler implementation.
           */
          
          /*
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: heapsizeofuserarea.c,  v 1.18 2010/08/25 12:35:52 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/heap.h>
          
      28  bool _Heap_Size_of_alloc_area(  
           Heap_Control *heap,  
           void *alloc_begin_ptr,  
           uintptr_t *alloc_size
           )
          {
           uintptr_t const page_size = heap->page_size;
           uintptr_t const alloc_begin = (  uintptr_t ) alloc_begin_ptr;
           Heap_Block *block = _Heap_Block_of_alloc_area(   alloc_begin,   page_size  );
           Heap_Block *next_block = NULL;
           uintptr_t block_size = 0;
          
           if (   !_Heap_Is_block_in_heap(   heap,   block  )  ) {
           return false;
           }
          
           block_size = _Heap_Block_size(   block  );
           next_block = _Heap_Block_at(   block,   block_size  );
          
           if (  
           !_Heap_Is_block_in_heap(   heap,   next_block  )
           || !_Heap_Is_prev_used(   next_block  )
            ) {
           return false;
           }
          
           *alloc_size = (  uintptr_t ) next_block + HEAP_ALLOC_BONUS - alloc_begin;
          
           return true;
          }
          

score/src/heapwalk.c

       1  /**
           * @file
           *
           * @ingroup ScoreHeap
           *
           * @brief Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (   c  ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: heapwalk.c,  v 1.27 2010/06/07 09:35:01 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/heap.h>
          #include <rtems/score/interr.h>
          #include <rtems/bspIo.h>
          
          typedef void (  *Heap_Walk_printer )(  int,   bool,   const char*,   ... );
          
      33  static void _Heap_Walk_print_nothing(  
           int source,  
           bool error,  
           const char *fmt,  
           ...
           )
          {
           /* Do nothing */
          }
          
      43  static void _Heap_Walk_print(   int source,   bool error,   const char *fmt,   ...  )
          {
           va_list ap;
          
           if (   error  ) {
           printk(   "FAIL[%d]: ",   source  );
           } else {
           printk(   "PASS[%d]: ",   source  );
           }
          
           va_start(   ap,   fmt  );
           vprintk(   fmt,   ap  );
           va_end(   ap  );
          }
          
      58  static bool _Heap_Walk_check_free_list(  
           int source,  
           Heap_Walk_printer printer,  
           Heap_Control *heap
           )
          {
           uintptr_t const page_size = heap->page_size;
           const Heap_Block *const free_list_tail = _Heap_Free_list_tail(   heap  );
           const Heap_Block *const first_free_block = _Heap_Free_list_first(   heap  );
           const Heap_Block *prev_block = free_list_tail;
           const Heap_Block *free_block = first_free_block;
          
           while (   free_block != free_list_tail  ) {
           if (   !_Heap_Is_block_in_heap(   heap,   free_block  )  ) {
           (  *printer )(  
           source,  
           true,  
           "free block 0x%08x: not in heap\n",  
           free_block
            );
          
           return false;
           }
          
           if (  
           !_Heap_Is_aligned(   _Heap_Alloc_area_of_block(   free_block  ),   page_size  )
            ) {
           (  *printer )(  
           source,  
           true,  
           "free block 0x%08x: alloc area not page aligned\n",  
           free_block
            );
          
           return false;
           }
          
           if (   _Heap_Is_used(   free_block  )  ) {
           (  *printer )(  
           source,  
           true,  
           "free block 0x%08x: is used\n",  
           free_block
            );
          
           return false;
           }
          
           if (   free_block->prev != prev_block  ) {
           (  *printer )(  
           source,  
           true,  
           "free block 0x%08x: invalid previous block 0x%08x\n",  
           free_block,  
           free_block->prev
            );
          
           return false;
           }
          
           prev_block = free_block;
           free_block = free_block->next;
           }
          
           return true;
          }
          
     125  static bool _Heap_Walk_is_in_free_list(  
           Heap_Control *heap,  
           Heap_Block *block
           )
          {
           const Heap_Block *const free_list_tail = _Heap_Free_list_tail(   heap  );
           const Heap_Block *free_block = _Heap_Free_list_first(   heap  );
          
           while (   free_block != free_list_tail  ) {
           if (   free_block == block  ) {
           return true;
           }
           free_block = free_block->next;
           }
          
           return false;
          }
          
     143  static bool _Heap_Walk_check_control(  
           int source,  
           Heap_Walk_printer printer,  
           Heap_Control *heap
           )
          {
           uintptr_t const page_size = heap->page_size;
           uintptr_t const min_block_size = heap->min_block_size;
           Heap_Block *const first_free_block = _Heap_Free_list_first(   heap  );
           Heap_Block *const last_free_block = _Heap_Free_list_last(   heap  );
           Heap_Block *const first_block = heap->first_block;
           Heap_Block *const last_block = heap->last_block;
          
           (  *printer )(  
           source,  
           false,  
           "page size %u,   min block size %u\n"
           "\tarea begin 0x%08x,   area end 0x%08x\n"
           "\tfirst block 0x%08x,   last block 0x%08x\n"
           "\tfirst free 0x%08x,   last free 0x%08x\n",  
           page_size,   min_block_size,  
           heap->area_begin,   heap->area_end,  
           first_block,   last_block,  
           first_free_block,   last_free_block
            );
          
           if (   page_size == 0  ) {
           (  *printer )(   source,   true,   "page size is zero\n"  );
          
           return false;
           }
          
           if (   !_Addresses_Is_aligned(   (  void * ) page_size  )  ) {
           (  *printer )(  
           source,  
           true,  
           "page size %u not CPU aligned\n",  
           page_size
            );
          
           return false;
           }
          
           if (   !_Heap_Is_aligned(   min_block_size,   page_size  )  ) {
           (  *printer )(  
           source,  
           true,  
           "min block size %u not page aligned\n",  
           min_block_size
            );
          
           return false;
           }
          
           if (  
           !_Heap_Is_aligned(   _Heap_Alloc_area_of_block(   first_block  ),   page_size  )
            ) {
           (  *printer )(  
           source,  
           true,  
           "first block 0x%08x: alloc area not page aligned\n",  
           first_block
            );
          
           return false;
           }
          
           if (   !_Heap_Is_prev_used(   first_block  )  ) {
           (  *printer )(  
           source,  
           true,  
           "first block: HEAP_PREV_BLOCK_USED is cleared\n"
            );
          
           return false;
           }
          
           if (   _Heap_Is_free(   last_block  )  ) {
           (  *printer )(  
           source,  
           true,  
           "last block: is free\n"
            );
          
           return false;
           }
          
           if (  
           _Heap_Block_at(   last_block,   _Heap_Block_size(   last_block  )  ) != first_block
            ) {
           (  *printer )(  
           source,  
           true,  
           "last block: next block is not the first block\n"
            );
          
           return false;
           }
          
           return _Heap_Walk_check_free_list(   source,   printer,   heap  );
          }
          
     245  static bool _Heap_Walk_check_free_block(  
           int source,  
           Heap_Walk_printer printer,  
           Heap_Control *heap,  
           Heap_Block *block
           )
          {
           Heap_Block *const free_list_tail = _Heap_Free_list_tail(   heap  );
           Heap_Block *const free_list_head = _Heap_Free_list_head(   heap  );
           Heap_Block *const first_free_block = _Heap_Free_list_first(   heap  );
           Heap_Block *const last_free_block = _Heap_Free_list_last(   heap  );
           bool const prev_used = _Heap_Is_prev_used(   block  );
           uintptr_t const block_size = _Heap_Block_size(   block  );
           Heap_Block *const next_block = _Heap_Block_at(   block,   block_size  );
          
           (  *printer )(  
           source,  
           false,  
           "block 0x%08x: size %u,   prev 0x%08x%s,   next 0x%08x%s\n",  
           block,  
           block_size,  
           block->prev,  
           block->prev == first_free_block ?
           " (  = first free )"
           : (  block->prev == free_list_head ? " (  = head )" : "" ),  
           block->next,  
           block->next == last_free_block ?
           " (  = last free )"
           : (  block->next == free_list_tail ? " (  = tail )" : "" )
            );
          
           if (   block_size != next_block->prev_size  ) {
           (  *printer )(  
           source,  
           true,  
           "block 0x%08x: size %u != size %u (  in next block 0x%08x )\n",  
           block,  
           block_size,  
           next_block->prev_size,  
           next_block
            );
          
           return false;
           }
          
           if (   !prev_used  ) {
           (  *printer )(  
           source,  
           true,  
           "block 0x%08x: two consecutive blocks are free\n",  
           block
            );
          
           return false;
           }
          
           if (   !_Heap_Walk_is_in_free_list(   heap,   block  )  ) {
           (  *printer )(  
           source,  
           true,  
           "block 0x%08x: free block not in free list\n",  
           block
            );
          
           return false;
           }
          
           return true;
          }
          
     315  bool _Heap_Walk(  
           Heap_Control *heap,  
           int source,  
           bool dump
           )
          {
           uintptr_t const page_size = heap->page_size;
           uintptr_t const min_block_size = heap->min_block_size;
           Heap_Block *const first_block = heap->first_block;
           Heap_Block *const last_block = heap->last_block;
           Heap_Block *block = first_block;
           Heap_Walk_printer printer = dump ?
           _Heap_Walk_print : _Heap_Walk_print_nothing;
          
           if (   !_System_state_Is_up(   _System_state_Get(   )  )  ) {
           return true;
           }
          
           if (   !_Heap_Walk_check_control(   source,   printer,   heap  )  ) {
           return false;
           }
          
           do {
           uintptr_t const block_begin = (  uintptr_t ) block;
           uintptr_t const block_size = _Heap_Block_size(   block  );
           bool const prev_used = _Heap_Is_prev_used(   block  );
           Heap_Block *const next_block = _Heap_Block_at(   block,   block_size  );
           uintptr_t const next_block_begin = (  uintptr_t ) next_block;
           bool const is_not_last_block = block != last_block;
          
           if (   !_Heap_Is_block_in_heap(   heap,   next_block  )  ) {
           (  *printer )(  
           source,  
           true,  
           "block 0x%08x: next block 0x%08x not in heap\n",  
           block,  
           next_block
            );
          
           return false;
           }
          
           if (   !_Heap_Is_aligned(   block_size,   page_size  ) && is_not_last_block  ) {
           (  *printer )(  
           source,  
           true,  
           "block 0x%08x: block size %u not page aligned\n",  
           block,  
           block_size
            );
          
           return false;
           }
          
           if (   block_size < min_block_size && is_not_last_block  ) {
           (  *printer )(  
           source,  
           true,  
           "block 0x%08x: size %u < min block size %u\n",  
           block,  
           block_size,  
           min_block_size
            );
          
           return false;
           }
          
           if (   next_block_begin <= block_begin && is_not_last_block  ) {
           (  *printer )(  
           source,  
           true,  
           "block 0x%08x: next block 0x%08x is not a successor\n",  
           block,  
           next_block
            );
          
           return false;
           }
          
           if (   !_Heap_Is_prev_used(   next_block  )  ) {
           if (   !_Heap_Walk_check_free_block(   source,   printer,   heap,   block  )  ) {
           return false;
           }
           } else if (  prev_used ) {
           (  *printer )(  
           source,  
           false,  
           "block 0x%08x: size %u\n",  
           block,  
           block_size
            );
           } else {
           (  *printer )(  
           source,  
           false,  
           "block 0x%08x: size %u,   prev_size %u\n",  
           block,  
           block_size,  
           block->prev_size
            );
           }
          
           block = next_block;
           } while (   block != first_block  );
          
           return true;
          }

score/src/interr.c

       1  /*
           * Internal Error Handler
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: interr.c,  v 1.17 2009/10/12 12:16:22 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/userext.h>
          
          /*PAGE
           *
           * _Internal_error_Occurred
           *
           * This routine will invoke the fatal error handler supplied by the user
           * followed by the the default one provided by the executive. The default
           * error handler assumes no hardware is present to help inform the user
           * of the problem. Halt stores the error code in a known register,  
           * disables interrupts,   and halts the CPU. If the CPU does not have a
           * halt instruction,   it will loop to itself.
           *
           * Input parameters:
           * the_source - what subsystem the error originated in
           * is_internal - if the error was internally generated
           * the_error - fatal error status code
           *
           * Output parameters:
           * As much information as possible is stored in a CPU dependent fashion.
           * See the CPU dependent code for more information.
           *
           * NOTE: The the_error is not necessarily a directive status code.
           */
          
      46  void _Internal_error_Occurred(  
           Internal_errors_Source the_source,  
           bool is_internal,  
           Internal_errors_t the_error
           )
          {
          
           _Internal_errors_What_happened.the_source = the_source;
           _Internal_errors_What_happened.is_internal = is_internal;
           _Internal_errors_What_happened.the_error = the_error;
          
           _User_extensions_Fatal(   the_source,   is_internal,   the_error  );
          
           _System_state_Set(   SYSTEM_STATE_FAILED  );
          
           _CPU_Fatal_halt(   the_error  );
          
           /* will not return from this routine */
           while (  true );
          }

score/src/isr.c

       1  /*
           * ISR Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: isr.c,  v 1.20 2010/08/19 12:13:56 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/stack.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/config.h>
          
          /* _ISR_Handler_initialization
           *
           * This routine initializes the ISR handler.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      35  void _ISR_Handler_initialization(   void  )
          {
           _ISR_Nest_level = 0;
          
          #if (  CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE )
           _ISR_Vector_table = _Workspace_Allocate_or_fatal_error(  
           sizeof(  ISR_Handler_entry ) * ISR_NUMBER_OF_VECTORS
            );
          #endif
          
           _CPU_Initialize_vectors(   );
          
          #if (   CPU_ALLOCATE_INTERRUPT_STACK == TRUE  )
          
           if (   !_Stack_Is_enough(  Configuration.interrupt_stack_size )  )
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL
            );
          
           _CPU_Interrupt_stack_low = _Workspace_Allocate_or_fatal_error(  
           Configuration.interrupt_stack_size
            );
          
           _CPU_Interrupt_stack_high = _Addresses_Add_offset(  
           _CPU_Interrupt_stack_low,  
           Configuration.interrupt_stack_size
            );
          
           _CPU_Interrupt_stack_high = (  void * )
           (  (  uintptr_t ) _CPU_Interrupt_stack_high & ~(  CPU_STACK_ALIGNMENT - 1 ) );
          
           /* Interrupt stack might have to be aligned and/or setup
           * in a specific way.
           */
          #if defined(  _CPU_Interrupt_stack_setup )
           _CPU_Interrupt_stack_setup(  _CPU_Interrupt_stack_low,   _CPU_Interrupt_stack_high );
          #endif
          
          #endif
          
          #if (   CPU_HAS_HARDWARE_INTERRUPT_STACK == TRUE  )
           _CPU_Install_interrupt_stack(   );
          #endif
          
          }

score/src/iterateoverthreads.c

       1  /*
           * rtems_iterate_over_all_threads
           *
           * This function operates by as follows:
           * for all threads
           * invoke specified function
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: iterateoverthreads.c,  v 1.8 2010/07/26 22:03:18 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          
      25  void rtems_iterate_over_all_threads(  rtems_per_thread_routine routine )
          {
           uint32_t i;
           uint32_t api_index;
           Thread_Control *the_thread;
           Objects_Information *information;
          
           if (   !routine  )
           return;
          
           for (   api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++  ) {
           /*
           * Since the removal of ITRON,   this cannot occur.
           */
           #if defined(  RTEMS_DEBUG )
           if (   !_Objects_Information_table[ api_index ]  )
           continue;
           #endif
          
           information = _Objects_Information_table[ api_index ][ 1 ];
           if (   !information  )
           continue;
          
           for (   i=1 ; i <= information->maximum ; i++  ) {
           the_thread = (  Thread_Control * )information->local_table[ i ];
          
           if (   !the_thread  )
           continue;
          
           (  *routine )(  the_thread );
           }
           }
          
          }

score/src/mpci.c

       1  /*
           * Multiprocessing Communications Interface (  MPCI ) Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: mpci.c,  v 1.36 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/mpci.h>
          #include <rtems/score/mppkt.h>
          #endif
          #include <rtems/config.h>
          #include <rtems/score/cpu.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/score/sysstate.h>
          
          #include <rtems/score/coresem.h>
          #include <rtems/config.h>
          
          /**
           * This is the core semaphore which the MPCI Receive Server blocks on.
           */
          CORE_semaphore_Control _MPCI_Semaphore;
          
          /*PAGE
           *
           * _MPCI_Handler_initialization
           *
           * This subprogram performs the initialization necessary for this handler.
           */
          
      49  void _MPCI_Handler_initialization(  
           uint32_t timeout_status
           )
          {
           CORE_semaphore_Attributes attributes;
           MPCI_Control *users_mpci_table;
          
           users_mpci_table = _Configuration_MP_table->User_mpci_table;
          
           if (   _System_state_Is_multiprocessing && !users_mpci_table  )
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_NO_MPCI
            );
          
           _MPCI_table = users_mpci_table;
          
           if (   !_System_state_Is_multiprocessing  )
           return;
          
           /*
           * Register the MP Process Packet routine.
           */
          
           _MPCI_Register_packet_processor(  
           MP_PACKET_MPCI_INTERNAL,  
           _MPCI_Internal_packets_Process_packet
            );
          
           /*
           * Create the counting semaphore used by the MPCI Receive Server.
           */
          
           attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
          
           _CORE_semaphore_Initialize(  
           &_MPCI_Semaphore,  
           &attributes,   /* the_semaphore_attributes */
           0 /* initial_value */
            );
          
           _Thread_queue_Initialize(  
           &_MPCI_Remote_blocked_threads,  
           THREAD_QUEUE_DISCIPLINE_FIFO,  
           STATES_WAITING_FOR_RPC_REPLY,  
           timeout_status
            );
          }
          
          /*PAGE
           *
           * _MPCI_Create_server
           *
           * This subprogram creates the MPCI receive server.
           */
          
     106  void _MPCI_Create_server(   void  )
          {
           Objects_Name name;
          
          
           if (   !_System_state_Is_multiprocessing  )
           return;
          
           /*
           * Initialize the MPCI Receive Server
           */
          
           _MPCI_Receive_server_tcb = _Thread_Internal_allocate(   );
          
           name.name_u32 = _Objects_Build_name(   'M',   'P',   'C',   'I'  );
           _Thread_Initialize(  
           &_Thread_Internal_information,  
           _MPCI_Receive_server_tcb,  
           NULL,   /* allocate the stack */
           _Stack_Minimum(   ) +
           CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK +
           _Configuration_MP_table->extra_mpci_receive_server_stack,  
           CPU_ALL_TASKS_ARE_FP,  
           PRIORITY_MINIMUM,  
           false,   /* no preempt */
           THREAD_CPU_BUDGET_ALGORITHM_NONE,  
           NULL,   /* no budget algorithm callout */
           0,   /* all interrupts enabled */
           name
            );
          
           _Thread_Start(  
           _MPCI_Receive_server_tcb,  
           THREAD_START_NUMERIC,  
           (  void * ) _MPCI_Receive_server,  
           NULL,  
           0
            );
          }
          
          /*PAGE
           *
           * _MPCI_Initialization
           *
           * This subprogram initializes the MPCI driver by
           * invoking the user provided MPCI initialization callout.
           */
          
     154  void _MPCI_Initialization (   void  )
          {
           (  *_MPCI_table->initialization )(   );
          }
          
          /*PAGE
           *
           * _MPCI_Register_packet_processor
           *
           * This routine registers the MPCI packet processor for the
           * designated object class.
           */
          
     167  void _MPCI_Register_packet_processor(  
           MP_packet_Classes the_class,  
           MPCI_Packet_processor the_packet_processor
          
           )
          {
           _MPCI_Packet_processors[ the_class ] = the_packet_processor;
          }
          
          /*PAGE
           *
           * _MPCI_Get_packet
           *
           * This subprogram obtains a packet by invoking the user provided
           * MPCI get packet callout.
           */
          
     184  MP_packet_Prefix *_MPCI_Get_packet (   void  )
          {
           MP_packet_Prefix *the_packet;
          
           (  *_MPCI_table->get_packet )(   &the_packet  );
          
           if (   the_packet == NULL  )
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_OUT_OF_PACKETS
            );
          
           /*
           * Put in a default timeout that will be used for
           * all packets that do not otherwise have a timeout.
           */
          
           the_packet->timeout = MPCI_DEFAULT_TIMEOUT;
          
           return the_packet;
          }
          
          /*PAGE
           *
           * _MPCI_Return_packet
           *
           * This subprogram returns a packet by invoking the user provided
           * MPCI return packet callout.
           */
          
     215  void _MPCI_Return_packet (  
           MP_packet_Prefix *the_packet
           )
          {
           (  *_MPCI_table->return_packet )(   the_packet  );
          }
          
          /*PAGE
           *
           * _MPCI_Send_process_packet
           *
           * This subprogram sends a process packet by invoking the user provided
           * MPCI send callout.
           */
          
     230  void _MPCI_Send_process_packet (  
           uint32_t destination,  
           MP_packet_Prefix *the_packet
           )
          {
           the_packet->source_tid = _Thread_Executing->Object.id;
           the_packet->to_convert =
           (   the_packet->to_convert - sizeof(  MP_packet_Prefix )  ) / sizeof(  uint32_t );
          
           (  *_MPCI_table->send_packet )(   destination,   the_packet  );
          }
          
          /*PAGE
           *
           * _MPCI_Send_request_packet
           *
           * This subprogram sends a request packet by invoking the user provided
           * MPCI send callout.
           */
          
     250  uint32_t _MPCI_Send_request_packet (  
           uint32_t destination,  
           MP_packet_Prefix *the_packet,  
           States_Control extra_state
           )
          {
           the_packet->source_tid = _Thread_Executing->Object.id;
           the_packet->source_priority = _Thread_Executing->current_priority;
           the_packet->to_convert =
           (   the_packet->to_convert - sizeof(  MP_packet_Prefix )  ) / sizeof(  uint32_t );
          
           _Thread_Executing->Wait.id = the_packet->id;
          
           _Thread_Executing->Wait.queue = &_MPCI_Remote_blocked_threads;
          
           _Thread_Disable_dispatch(   );
          
           (  *_MPCI_table->send_packet )(   destination,   the_packet  );
          
           _Thread_queue_Enter_critical_section(   &_MPCI_Remote_blocked_threads  );
          
           /*
           * See if we need a default timeout
           */
          
           if (  the_packet->timeout == MPCI_DEFAULT_TIMEOUT )
           the_packet->timeout = _MPCI_table->default_timeout;
          
           _Thread_queue_Enqueue(   &_MPCI_Remote_blocked_threads,   the_packet->timeout  );
          
           _Thread_Executing->current_state =
           _States_Set(   extra_state,   _Thread_Executing->current_state  );
          
           _Thread_Enable_dispatch(   );
          
           return _Thread_Executing->Wait.return_code;
          }
          
          /*PAGE
           *
           * _MPCI_Send_response_packet
           *
           * This subprogram sends a response packet by invoking the user provided
           * MPCI send callout.
           */
          
     296  void _MPCI_Send_response_packet (  
           uint32_t destination,  
           MP_packet_Prefix *the_packet
           )
          {
           the_packet->source_tid = _Thread_Executing->Object.id;
          
           (  *_MPCI_table->send_packet )(   destination,   the_packet  );
          }
          
          /*PAGE
           *
           * _MPCI_Receive_packet
           *
           * This subprogram receives a packet by invoking the user provided
           * MPCI receive callout.
           */
          
     314  MP_packet_Prefix *_MPCI_Receive_packet (   void  )
          {
           MP_packet_Prefix *the_packet;
          
           (  *_MPCI_table->receive_packet )(   &the_packet  );
          
           return the_packet;
          }
          
          /*PAGE
           *
           * _MPCI_Process_response
           *
           * This subprogram obtains a packet by invoking the user provided
           * MPCI get packet callout.
           */
          
     331  Thread_Control *_MPCI_Process_response (  
           MP_packet_Prefix *the_packet
           )
          {
           Thread_Control *the_thread;
           Objects_Locations location;
          
           the_thread = _Thread_Get(   the_packet->id,   &location  );
           switch (   location  ) {
           case OBJECTS_ERROR:
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
          #endif
           the_thread = NULL; /* IMPOSSIBLE */
           break;
           case OBJECTS_LOCAL:
           _Thread_queue_Extract(   &_MPCI_Remote_blocked_threads,   the_thread  );
           the_thread->Wait.return_code = the_packet->return_code;
           _Thread_Unnest_dispatch(   );
           break;
           }
          
           return the_thread;
          }
          
          /*PAGE
           *
           * _MPCI_Receive_server
           *
           */
          
     362  Thread _MPCI_Receive_server(  
           uint32_t ignored
           )
          {
          
           MP_packet_Prefix *the_packet;
           MPCI_Packet_processor the_function;
           Thread_Control *executing;
          
           executing = _Thread_Executing;
          
           for (   ; ;  ) {
          
           executing->receive_packet = NULL;
          
           _Thread_Disable_dispatch(   );
           _CORE_semaphore_Seize(   &_MPCI_Semaphore,   0,   true,   WATCHDOG_NO_TIMEOUT  );
           _Thread_Enable_dispatch(   );
          
           for (   ; ;  ) {
           the_packet = _MPCI_Receive_packet(   );
          
           if (   !the_packet  )
           break;
          
           executing->receive_packet = the_packet;
          
           if (   !_Mp_packet_Is_valid_packet_class (   the_packet->the_class  )  )
           break;
          
           the_function = _MPCI_Packet_processors[ the_packet->the_class ];
          
           if (   !the_function  )
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_BAD_PACKET
            );
          
           (  *the_function )(   the_packet  );
           }
           }
          
           return 0; /* unreached - only to remove warnings */
          }
          
          /*PAGE
           *
           * _MPCI_Announce
           *
           */
          
     414  void _MPCI_Announce (   void  )
          {
           _Thread_Disable_dispatch(   );
           (  void ) _CORE_semaphore_Surrender(   &_MPCI_Semaphore,   0,   0  );
           _Thread_Enable_dispatch(   );
          }
          
          /*PAGE
           *
           * _MPCI_Internal_packets_Send_process_packet
           *
           */
          
     427  void _MPCI_Internal_packets_Send_process_packet (  
           MPCI_Internal_Remote_operations operation
           )
          {
           MPCI_Internal_packet *the_packet;
          
           switch (   operation  ) {
          
           case MPCI_PACKETS_SYSTEM_VERIFY:
          
           the_packet = _MPCI_Internal_packets_Get_packet(   );
           the_packet->Prefix.the_class = MP_PACKET_MPCI_INTERNAL;
           the_packet->Prefix.length = sizeof (   MPCI_Internal_packet  );
           the_packet->Prefix.to_convert = sizeof (   MPCI_Internal_packet  );
           the_packet->operation = operation;
          
           the_packet->maximum_nodes = _Objects_Maximum_nodes;
          
           the_packet->maximum_global_objects = _Objects_MP_Maximum_global_objects;
          
           _MPCI_Send_process_packet(   MPCI_ALL_NODES,   &the_packet->Prefix  );
           break;
           }
          }
          
          /*PAGE
           *
           * _MPCI_Internal_packets_Send_request_packet
           *
           * This subprogram is not needed since there are no request
           * packets to be sent by this manager.
           *
           */
          
          /*PAGE
           *
           * _MPCI_Internal_packets_Send_response_packet
           *
           * This subprogram is not needed since there are no response
           * packets to be sent by this manager.
           *
           */
          
          /*PAGE
           *
           *
           * _MPCI_Internal_packets_Process_packet
           *
           */
          
     477  void _MPCI_Internal_packets_Process_packet (  
           MP_packet_Prefix *the_packet_prefix
           )
          {
           MPCI_Internal_packet *the_packet;
           uint32_t maximum_nodes;
           uint32_t maximum_global_objects;
          
           the_packet = (  MPCI_Internal_packet * ) the_packet_prefix;
          
           switch (   the_packet->operation  ) {
          
           case MPCI_PACKETS_SYSTEM_VERIFY:
          
           maximum_nodes = the_packet->maximum_nodes;
           maximum_global_objects = the_packet->maximum_global_objects;
           if (   maximum_nodes != _Objects_Maximum_nodes ||
           maximum_global_objects != _Objects_MP_Maximum_global_objects  ) {
          
           _MPCI_Return_packet(   the_packet_prefix  );
          
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION
            );
           }
          
           _MPCI_Return_packet(   the_packet_prefix  );
          
           break;
           }
          }
          
          /*PAGE
           *
           * _MPCI_Internal_packets_Send_object_was_deleted
           *
           * This subprogram is not needed since there are no objects
           * deleted by this manager.
           *
           */
          
          /*PAGE
           *
           * _MPCI_Internal_packets_Send_extract_proxy
           *
           * This subprogram is not needed since there are no objects
           * deleted by this manager.
           *
           */
          
          /*PAGE
           *
           * _MPCI_Internal_packets_Get_packet
           *
           */
          
     535  MPCI_Internal_packet *_MPCI_Internal_packets_Get_packet (   void  )
          {
           return (   (  MPCI_Internal_packet * ) _MPCI_Get_packet(   )  );
          }
          
          /* end of file */

score/src/objectallocate.c

       1  /*
           * Object Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectallocate.c,  v 1.10 2010/06/16 17:35:25 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/object.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/objectmp.h>
          #endif
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/isr.h>
          
          /* #define RTEMS_DEBUG_OBJECT_ALLOCATION */
          
          #if defined(  RTEMS_DEBUG_OBJECT_ALLOCATION )
          #include <rtems/bspIo.h>
          #endif
          
          /*PAGE
           *
           * _Objects_Allocate
           *
           * DESCRIPTION:
           *
           * This function allocates a object control block from
           * the inactive chain of free object control blocks.
           */
          
      47  Objects_Control *_Objects_Allocate(  
           Objects_Information *information
           )
          {
           Objects_Control *the_object;
          
           /*
           * If the application is using the optional manager stubs and
           * still attempts to create the object,   the information block
           * should be all zeroed out because it is in the BSS. So let's
           * check that code for this manager is even present.
           */
           if (   information->size == 0  )
           return NULL;
          
           /*
           * OK. The manager should be initialized and configured to have objects.
           * With any luck,   it is safe to attempt to allocate an object.
           */
           the_object = (  Objects_Control * ) _Chain_Get(   &information->Inactive  );
          
           if (   information->auto_extend  ) {
           /*
           * If the list is empty then we are out of objects and need to
           * extend information base.
           */
          
           if (   !the_object  ) {
           _Objects_Extend_information(   information  );
           the_object = (  Objects_Control * ) _Chain_Get(   &information->Inactive  );
           }
          
           if (   the_object  ) {
           uint32_t block;
          
           block = (  uint32_t ) _Objects_Get_index(   the_object->id  ) -
           _Objects_Get_index(   information->minimum_id  );
           block /= information->allocation_size;
          
           information->inactive_per_block[ block ]--;
           information->inactive--;
           }
           }
          
          #if defined(  RTEMS_DEBUG_OBJECT_ALLOCATION )
           if (   !the_object  ) {
           printk(  
           "OBJECT ALLOCATION FAILURE! API/Class %d/%d\n",  
           information->the_api,  
           information->the_class
            );
           }
          #endif
          
           return the_object;
          }

score/src/objectapimaximumclass.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectapimaximumclass.c,  v 1.3 2010/06/18 04:03:04 ralf Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          
      19  unsigned int _Objects_API_maximum_class(  
           uint32_t api
           )
          {
           switch (  api ) {
           case OBJECTS_INTERNAL_API:
           return OBJECTS_INTERNAL_CLASSES_LAST;
           case OBJECTS_CLASSIC_API:
           return OBJECTS_RTEMS_CLASSES_LAST;
           case OBJECTS_POSIX_API:
           return OBJECTS_POSIX_CLASSES_LAST;
           case OBJECTS_NO_API:
           default:
           break;
           }
           return 0;
          }
          

score/src/objectclose.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectclose.c,  v 1.2 2008/05/22 20:38:03 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/wkspace.h>
          
      20  void _Objects_Close(  
           Objects_Information *information,  
           Objects_Control *the_object
           )
          {
           _Objects_Invalidate_Id(   information,   the_object  );
          
           _Objects_Namespace_remove(   information,   the_object  );
          }

score/src/objectextendinformation.c

       1  /*
           * Object Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectextendinformation.c,  v 1.22 2010/06/21 16:27:37 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/object.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/objectmp.h>
          #endif
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/isr.h>
          
          #include <string.h> /* for memcpy(   ) */
          
          /*PAGE
           *
           * _Objects_Extend_information
           *
           * This routine extends all object information related data structures.
           *
           * Input parameters:
           * information - object information table
           *
           * Output parameters: NONE
           */
          
      45  void _Objects_Extend_information(  
           Objects_Information *information
           )
          {
           Objects_Control *the_object;
           Chain_Control Inactive;
           uint32_t block_count;
           uint32_t block;
           uint32_t index_base;
           uint32_t minimum_index;
           uint32_t index;
           uint32_t maximum;
           size_t block_size;
           void *new_object_block;
           bool do_extend;
          
           /*
           * Search for a free block of indexes. If we do NOT need to allocate or
           * extend the block table,   then we will change do_extend.
           */
           do_extend = true;
           minimum_index = _Objects_Get_index(   information->minimum_id  );
           index_base = minimum_index;
           block = 0;
          
           /* if (   information->maximum < minimum_index  ) */
           if (   information->object_blocks == NULL  )
           block_count = 0;
           else {
           block_count = information->maximum / information->allocation_size;
          
           for (   ; block < block_count; block++  ) {
           if (   information->object_blocks[ block ] == NULL  ) {
           do_extend = false;
           break;
           } else
           index_base += information->allocation_size;
           }
           }
          
           maximum = (  uint32_t ) information->maximum + information->allocation_size;
          
           /*
           * We need to limit the number of objects to the maximum number
           * representable in the index portion of the object Id. In the
           * case of 16-bit Ids,   this is only 256 object instances.
           */
           if (   maximum > OBJECTS_ID_FINAL_INDEX  ) {
           return;
           }
          
           /*
           * Allocate the name table,   and the objects and if it fails either return or
           * generate a fatal error depending on auto-extending being active.
           */
           block_size = information->allocation_size * information->size;
           if (   information->auto_extend  ) {
           new_object_block = _Workspace_Allocate(   block_size  );
           if (   !new_object_block  )
           return;
           } else {
           new_object_block = _Workspace_Allocate_or_fatal_error(   block_size  );
           }
          
           /*
           * Do we need to grow the tables?
           */
           if (   do_extend  ) {
           ISR_Level level;
           void **object_blocks;
           uint32_t *inactive_per_block;
           Objects_Control **local_table;
           void *old_tables;
           size_t block_size;
          
           /*
           * Growing the tables means allocating a new area,   doing a copy and
           * updating the information table.
           *
           * If the maximum is minimum we do not have a table to copy. First
           * time through.
           *
           * The allocation has :
           *
           * void *objects[block_count];
           * uint32_t inactive_count[block_count];
           * Objects_Control *local_table[maximum];
           *
           * This is the order in memory. Watch changing the order. See the memcpy
           * below.
           */
          
           /*
           * Up the block count and maximum
           */
           block_count++;
          
           /*
           * Allocate the tables and break it up.
           */
           block_size = block_count *
           (  sizeof(  void * ) + sizeof(  uint32_t ) + sizeof(  Objects_Name * ) ) +
           (  (  maximum + minimum_index ) * sizeof(  Objects_Control * ) );
           object_blocks = (  void** ) _Workspace_Allocate(   block_size  );
          
           if (   !object_blocks  ) {
           _Workspace_Free(   new_object_block  );
           return;
           }
          
           /*
           * Break the block into the various sections.
           */
           inactive_per_block = (  uint32_t * ) _Addresses_Add_offset(  
           object_blocks,   block_count * sizeof(  void* )  );
           local_table = (  Objects_Control ** ) _Addresses_Add_offset(  
           inactive_per_block,   block_count * sizeof(  uint32_t )  );
          
           /*
           * Take the block count down. Saves all the (  block_count - 1 )
           * in the copies.
           */
           block_count--;
          
           if (   information->maximum > minimum_index  ) {
          
           /*
           * Copy each section of the table over. This has to be performed as
           * separate parts as size of each block has changed.
           */
          
           memcpy(   object_blocks,  
           information->object_blocks,  
           block_count * sizeof(  void* )  );
           memcpy(   inactive_per_block,  
           information->inactive_per_block,  
           block_count * sizeof(  uint32_t )  );
           memcpy(   local_table,  
           information->local_table,  
           (  information->maximum + minimum_index ) * sizeof(  Objects_Control * )  );
           } else {
          
           /*
           * Deal with the special case of the 0 to minimum_index
           */
           for (   index = 0; index < minimum_index; index++  ) {
           local_table[ index ] = NULL;
           }
           }
          
           /*
           * Initialise the new entries in the table.
           */
           object_blocks[block_count] = NULL;
           inactive_per_block[block_count] = 0;
          
           for (   index=index_base ;
           index < (   information->allocation_size + index_base  );
           index++  ) {
           local_table[ index ] = NULL;
           }
          
           _ISR_Disable(   level  );
          
           old_tables = information->object_blocks;
          
           information->object_blocks = object_blocks;
           information->inactive_per_block = inactive_per_block;
           information->local_table = local_table;
           information->maximum = (  Objects_Maximum ) maximum;
           information->maximum_id = _Objects_Build_id(  
           information->the_api,  
           information->the_class,  
           _Objects_Local_node,  
           information->maximum
            );
          
           _ISR_Enable(   level  );
          
           if (   old_tables  )
           _Workspace_Free(   old_tables  );
          
           block_count++;
           }
          
           /*
           * Assign the new object block to the object block table.
           */
           information->object_blocks[ block ] = new_object_block;
          
           /*
           * Initialize objects .. add to a local chain first.
           */
           _Chain_Initialize(  
           &Inactive,  
           information->object_blocks[ block ],  
           information->allocation_size,  
           information->size
            );
          
           /*
           * Move from the local chain,   initialise,   then append to the inactive chain
           */
           index = index_base;
          
           while (  (  the_object = (  Objects_Control * ) _Chain_Get(   &Inactive  ) ) != NULL  ) {
          
           the_object->id = _Objects_Build_id(  
           information->the_api,  
           information->the_class,  
           _Objects_Local_node,  
           index
            );
          
           _Chain_Append(   &information->Inactive,   &the_object->Node  );
          
           index++;
           }
          
           information->inactive_per_block[ block ] = information->allocation_size;
           information->inactive =
           (  Objects_Maximum )(  information->inactive + information->allocation_size );
          }

score/src/objectfree.c

       1  /*
           * Object Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectfree.c,  v 1.8 2009/10/08 07:07:36 ccj Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/object.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/objectmp.h>
          #endif
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/isr.h>
          
          /*PAGE
           *
           * _Objects_Free
           *
           * DESCRIPTION:
           *
           * This function frees a object control block to the
           * inactive chain of free object control blocks.
           */
          
      41  void _Objects_Free(  
           Objects_Information *information,  
           Objects_Control *the_object
           )
          {
           uint32_t allocation_size = information->allocation_size;
          
           _Chain_Append(   &information->Inactive,   &the_object->Node  );
          
           if (   information->auto_extend  ) {
           uint32_t block;
          
           block = (  uint32_t ) (  _Objects_Get_index(   the_object->id  ) -
           _Objects_Get_index(   information->minimum_id  ) );
           block /= information->allocation_size;
          
           information->inactive_per_block[ block ]++;
           information->inactive++;
          
           /*
           * Check if the threshold level has been met of
           * 1.5 x allocation_size are free.
           */
          
           if (   information->inactive > (   allocation_size + (   allocation_size >> 1  )  )  ) {
           _Objects_Shrink_information(   information  );
           }
           }
          }

score/src/objectget.c

       1  /*
           * Object Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectget.c,  v 1.14 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/object.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/objectmp.h>
          #endif
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/isr.h>
          
          /*PAGE
           *
           * _Objects_Get
           *
           * This routine sets the object pointer for the given
           * object id based on the given object information structure.
           *
           * Input parameters:
           * information - pointer to entry in table for this class
           * id - object id to search for
           * location - address of where to store the location
           *
           * Output parameters:
           * returns - address of object if local
           * location - one of the following:
           * OBJECTS_ERROR - invalid object ID
           * OBJECTS_REMOTE - remote object
           * OBJECTS_LOCAL - local object
           */
          
      51  Objects_Control *_Objects_Get(  
           Objects_Information *information,  
           Objects_Id id,  
           Objects_Locations *location
           )
          {
           Objects_Control *the_object;
           uint32_t index;
          
           /*
           * Extract the index portion of an Id in a way that produces a valid
           * index for objects within this class and an invalid value for objects
           * outside this class.
           *
           * If the Id matches the api,   class,   and node but index portion is 0,  
           * then the subtraction will underflow and the addition of 1 will
           * result in a 0 index. The zeroth element in the local_table is
           * always NULL.
           *
           * If the Id is valid but the object has not been created yet,   then
           * the local_table entry will be NULL.
           */
           index = id - information->minimum_id + 1;
          
           /*
           * If the index is less than maximum,   then it is OK to use it to
           * index into the local_table array.
           */
           if (   index <= information->maximum  ) {
           _Thread_Disable_dispatch(   );
           if (   (  the_object = information->local_table[ index ] ) != NULL  ) {
           *location = OBJECTS_LOCAL;
           return the_object;
           }
          
           /*
           * Valid Id for this API,   Class and Node but the object has not
           * been allocated yet.
           */
           _Thread_Enable_dispatch(   );
           *location = OBJECTS_ERROR;
           return NULL;
           }
          
           /*
           * Object Id is not within this API and Class on this node. So
           * it may be global in a multiprocessing system. But it is clearly
           * invalid on a single processor system.
           */
           *location = OBJECTS_ERROR;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           _Objects_MP_Is_remote(   information,   id,   location,   &the_object  );
           return the_object;
          #else
           return NULL;
          #endif
          }

score/src/objectgetinfo.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectgetinfo.c,  v 1.8 2010/08/10 17:41:32 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          
      21  Objects_Information *_Objects_Get_information(  
           Objects_APIs the_api,  
           uint16_t the_class
           )
          {
           Objects_Information *info;
           int the_class_api_maximum;
          
           if (   !the_class  )
           return NULL;
          
           /*
           * This call implicitly validates the_api so we do not call
           * _Objects_Is_api_valid above here.
           */
           the_class_api_maximum = _Objects_API_maximum_class(   the_api  );
           if (   the_class_api_maximum == 0  )
           return NULL;
          
           if (   the_class > (  uint32_t ) the_class_api_maximum  )
           return NULL;
          
           if (   !_Objects_Information_table[ the_api ]  )
           return NULL;
          
           info = _Objects_Information_table[ the_api ][ the_class ];
           if (   !info  )
           return NULL;
          
           /*
           * In a multprocessing configuration,   we may access remote objects.
           * Thus we may have 0 local instances and still have a valid object
           * pointer.
           */
           #if !defined(  RTEMS_MULTIPROCESSING )
           if (   info->maximum == 0  )
           return NULL;
           #endif
          
           return info;
          }
          

score/src/objectgetinfoid.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectgetinfoid.c,  v 1.2 2008/02/04 17:16:37 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          
      20  Objects_Information *_Objects_Get_information_id(  
           Objects_Id id
           )
          {
           return _Objects_Get_information(  
           _Objects_Get_API(   id  ),  
           _Objects_Get_class(   id  )
            );
          }

score/src/objectgetisr.c

       1  /*
           * Object Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectgetisr.c,  v 1.7 2009/01/05 20:09:02 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/object.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/objectmp.h>
          #endif
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/isr.h>
          
          /*PAGE
           *
           * _Objects_Get_isr_disable
           *
           * This routine sets the object pointer for the given
           * object id based on the given object information structure.
           *
           * Input parameters:
           * information - pointer to entry in table for this class
           * id - object id to search for
           * location - address of where to store the location
           * level - pointer to previous interrupt level
           *
           * Output parameters:
           * returns - address of object if local
           * location - one of the following:
           * OBJECTS_ERROR - invalid object ID
           * OBJECTS_REMOTE - remote object
           * OBJECTS_LOCAL - local object
           * *level - previous interrupt level
           */
          
      53  Objects_Control *_Objects_Get_isr_disable(  
           Objects_Information *information,  
           Objects_Id id,  
           Objects_Locations *location,  
           ISR_Level *level_p
           )
          {
           Objects_Control *the_object;
           uint32_t index;
           ISR_Level level;
          
           index = id - information->minimum_id + 1;
          
           _ISR_Disable(   level  );
           if (   information->maximum >= index  ) {
           if (   (  the_object = information->local_table[ index ] ) != NULL  ) {
           *location = OBJECTS_LOCAL;
           *level_p = level;
           return the_object;
           }
           _ISR_Enable(   level  );
           *location = OBJECTS_ERROR;
           return NULL;
           }
           _ISR_Enable(   level  );
           *location = OBJECTS_ERROR;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           _Objects_MP_Is_remote(   information,   id,   location,   &the_object  );
           return the_object;
          #else
           return NULL;
          #endif
          }

score/src/objectgetnameasstring.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectgetnameasstring.c,  v 1.12 2010/03/12 16:26:16 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <stdlib.h>
          #include <ctype.h>
          #include <inttypes.h>
          
          /*
           * This method objects the name of an object and returns its name
           * in the form of a C string. It attempts to be careful about
           * overflowing the user's string and about returning unprintable characters.
           */
          
      29  char *_Objects_Get_name_as_string(  
           Objects_Id id,  
           size_t length,  
           char *name
           )
          {
           Objects_Information *information;
           const char *s;
           char *d;
           uint32_t i;
           char lname[5];
           Objects_Control *the_object;
           Objects_Locations location;
           Objects_Id tmpId;
          
           if (   length == 0  )
           return NULL;
          
           if (   name == NULL  )
           return NULL;
          
           tmpId = (  id == OBJECTS_ID_OF_SELF ) ? _Thread_Executing->Object.id : id;
          
           information = _Objects_Get_information_id(   tmpId  );
           if (   !information  )
           return NULL;
          
           the_object = _Objects_Get(   information,   tmpId,   &location  );
           switch (   location  ) {
          
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE:
           /* not supported */
          #endif
           case OBJECTS_ERROR:
           return NULL;
          
           case OBJECTS_LOCAL:
          
           #if defined(  RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES )
           if (   information->is_string  ) {
           s = the_object->name.name_p;
           } else
           #endif
           {
           uint32_t u32_name = (  uint32_t ) the_object->name.name_u32;
          
           lname[ 0 ] = (  u32_name >> 24 ) & 0xff;
           lname[ 1 ] = (  u32_name >> 16 ) & 0xff;
           lname[ 2 ] = (  u32_name >> 8 ) & 0xff;
           lname[ 3 ] = (  u32_name >> 0 ) & 0xff;
           lname[ 4 ] = '\0';
           s = lname;
           }
          
           d = name;
           if (   s  ) {
           for (   i=0 ; i<(  length-1 ) && *s ; i++,   s++,   d++  ) {
           *d = (  isprint(  (  unsigned char )*s ) ) ? *s : '*';
           }
           }
           *d = '\0';
          
           _Thread_Enable_dispatch(   );
           return name;
           }
           return NULL; /* unreachable path */
          }

score/src/objectgetnext.c

       1  /*
           * Object Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectgetnext.c,  v 1.6 2009/05/08 02:13:24 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/object.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/objectmp.h>
          #endif
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/isr.h>
          
          /*PAGE
           *
           * _Objects_Get_next
           *
           * Like _Objects_Get,   but considers the 'id' as a "hint" and
           * finds next valid one after that point.
           * Mostly used for monitor and debug traversal of an object.
           *
           * Input parameters:
           * information - pointer to entry in table for this class
           * id - object id to search for
           * location - address of where to store the location
           * next_id - address to store next id to try
           *
           * Output parameters:
           * returns - address of object if local
           * location - one of the following:
           * OBJECTS_ERROR - invalid object ID
           * OBJECTS_REMOTE - remote object
           * OBJECTS_LOCAL - local object
           * next_id - will contain a reasonable "next" id to continue traversal
           *
           * NOTE:
           * assumes can add '1' to an id to get to next index.
           */
          
          Objects_Control *
      58  _Objects_Get_next(  
           Objects_Information *information,  
           Objects_Id id,  
           Objects_Locations *location_p,  
           Objects_Id *next_id_p
           )
          {
           Objects_Control *object;
           Objects_Id next_id;
          
           if (   !information  )
           return NULL;
          
           if (   !location_p  )
           return NULL;
          
           if (   !next_id_p  )
           return NULL;
          
           if (  _Objects_Get_index(  id ) == OBJECTS_ID_INITIAL_INDEX )
           next_id = information->minimum_id;
           else
           next_id = id;
          
           do {
           /* walked off end of list? */
           if (  _Objects_Get_index(  next_id ) > information->maximum )
           {
           *location_p = OBJECTS_ERROR;
           goto final;
           }
          
           /* try to grab one */
           object = _Objects_Get(  information,   next_id,   location_p );
          
           next_id++;
          
           } while (  *location_p != OBJECTS_LOCAL );
          
           *next_id_p = next_id;
           return object;
          
          final:
           *next_id_p = OBJECTS_ID_FINAL;
           return 0;
          }

score/src/objectgetnoprotection.c

       1  /*
           * Object Handler -- Object Get
           *
           *
           * COPYRIGHT (  c ) 1989-2002.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectgetnoprotection.c,  v 1.7 2008/01/09 20:49:44 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/object.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/objectmp.h>
          #endif
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/isr.h>
          
          /*PAGE
           *
           * _Objects_Get_no_protection
           *
           * This routine sets the object pointer for the given
           * object id based on the given object information structure.
           *
           * Input parameters:
           * information - pointer to entry in table for this class
           * id - object id to search for
           * location - address of where to store the location
           *
           * Output parameters:
           * returns - address of object if local
           * location - one of the following:
           * OBJECTS_ERROR - invalid object ID
           * OBJECTS_REMOTE - remote object
           * OBJECTS_LOCAL - local object
           */
          
      51  Objects_Control *_Objects_Get_no_protection(  
           Objects_Information *information,  
           Objects_Id id,  
           Objects_Locations *location
           )
          {
           Objects_Control *the_object;
           uint32_t index;
          
           /*
           * You can't just extract the index portion or you can get tricked
           * by a value between 1 and maximum.
           */
           index = id - information->minimum_id + 1;
          
           if (   information->maximum >= index  ) {
           if (   (  the_object = information->local_table[ index ] ) != NULL  ) {
           *location = OBJECTS_LOCAL;
           return the_object;
           }
           }
          
           /*
           * This isn't supported or required yet for Global objects so
           * if it isn't local,   we don't find it.
           */
           *location = OBJECTS_ERROR;
           return NULL;
          }

score/src/objectidtoname.c

       1  /*
           * Obtain Object Name Given ID
           *
           *
           * COPYRIGHT (  c ) 1989-2003.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: objectidtoname.c,  v 1.15 2009/09/28 23:00:20 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          
          /*
           * _Objects_Id_to_name
           *
           * DESCRIPTION:
           *
           * This routine returns the name associated with the given ID.
           *
           * INPUT:
           *
           * id - id of object to lookup name
           * name - pointer to location in which to store name
           *
           */
      36  Objects_Name_or_id_lookup_errors _Objects_Id_to_name (  
           Objects_Id id,  
           Objects_Name *name
           )
          {
           uint32_t the_api;
           uint32_t the_class;
           Objects_Id tmpId;
           Objects_Information *information;
           Objects_Control *the_object = (  Objects_Control * ) 0;
           Objects_Locations ignored_location;
          
           /*
           * Caller is trusted for name != NULL.
           */
          
           tmpId = (  id == OBJECTS_ID_OF_SELF ) ? _Thread_Executing->Object.id : id;
          
           the_api = _Objects_Get_API(   tmpId  );
           if (   !_Objects_Is_api_valid(   the_api  )  )
           return OBJECTS_INVALID_ID;
          
           if (   !_Objects_Information_table[ the_api ]  )
           return OBJECTS_INVALID_ID;
          
           the_class = _Objects_Get_class(   tmpId  );
          
           information = _Objects_Information_table[ the_api ][ the_class ];
           if (   !information  )
           return OBJECTS_INVALID_ID;
          
           #if defined(  RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES )
           if (   information->is_string  )
           return OBJECTS_INVALID_ID;
           #endif
          
           the_object = _Objects_Get(   information,   tmpId,   &ignored_location  );
           if (   !the_object  )
           return OBJECTS_INVALID_ID;
          
           *name = the_object->name;
           _Thread_Enable_dispatch(   );
           return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
          }

score/src/objectinitializeinformation.c

       1  /*
           * Object Handler Initialization per Object Class
           *
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectinitializeinformation.c,  v 1.19 2010/08/10 17:41:32 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/object.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/objectmp.h>
          #endif
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/isr.h>
          
          /*PAGE
           *
           * _Objects_Initialize_information
           *
           * This routine initializes all object information related data structures.
           *
           * Input parameters:
           * information - object information table
           * maximum - maximum objects of this class
           * size - size of this object's control block
           * is_string - true if names for this object are strings
           * maximum_name_length - maximum length of each object's name
           * When multiprocessing is configured,  
           * supports_global - true if this is a global object class
           * extract_callout - pointer to threadq extract callout
           *
           * Output parameters: NONE
           */
          
      49  void _Objects_Initialize_information(  
           Objects_Information *information,  
           Objects_APIs the_api,  
           uint16_t the_class,  
           uint32_t maximum,  
           uint16_t size,  
           bool is_string,  
           uint32_t maximum_name_length
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           bool supports_global,  
           Objects_Thread_queue_Extract_callout extract
          #endif
           )
          {
           static Objects_Control *null_local_table = NULL;
           uint32_t minimum_index;
           uint32_t name_length;
           uint32_t maximum_per_allocation;
           #if defined(  RTEMS_MULTIPROCESSING )
           uint32_t index;
           #endif
          
           information->the_api = the_api;
           information->the_class = the_class;
           information->size = size;
           information->local_table = 0;
           information->inactive_per_block = 0;
           information->object_blocks = 0;
           information->inactive = 0;
           #if defined(  RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES )
           information->is_string = is_string;
           #endif
          
           /*
           * Set the maximum value to 0. It will be updated when objects are
           * added to the inactive set from _Objects_Extend_information(   )
           */
           information->maximum = 0;
          
           /*
           * Register this Object Class in the Object Information Table.
           */
           _Objects_Information_table[ the_api ][ the_class ] = information;
          
           /*
           * Are we operating in limited or unlimited (  e.g. auto-extend ) mode.
           */
           information->auto_extend =
           (  maximum & OBJECTS_UNLIMITED_OBJECTS ) ? true : false;
           maximum_per_allocation = maximum & ~OBJECTS_UNLIMITED_OBJECTS;
          
           /*
           * Unlimited and maximum of zero is illogical.
           */
           if (   information->auto_extend && maximum_per_allocation == 0 ) {
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0
            );
           }
          
           /*
           * The allocation unit is the maximum value
           */
           information->allocation_size = maximum_per_allocation;
          
           /*
           * Provide a null local table entry for the case of any empty table.
           */
           information->local_table = &null_local_table;
          
           /*
           * Calculate minimum and maximum Id's
           */
           minimum_index = (  maximum_per_allocation == 0 ) ? 0 : 1;
           information->minimum_id =
           _Objects_Build_id(   the_api,   the_class,   _Objects_Local_node,   minimum_index  );
          
           /*
           * Calculate the maximum name length
           */
           name_length = maximum_name_length;
          
           if (   name_length & (  OBJECTS_NAME_ALIGNMENT-1 )  )
           name_length = (  name_length + OBJECTS_NAME_ALIGNMENT ) &
           ~(  OBJECTS_NAME_ALIGNMENT-1 );
          
           information->name_length = name_length;
          
           _Chain_Initialize_empty(   &information->Inactive  );
          
           /*
           * Initialize objects .. if there are any
           */
           if (   maximum_per_allocation  ) {
           /*
           * Always have the maximum size available so the current performance
           * figures are create are met. If the user moves past the maximum
           * number then a performance hit is taken.
           */
           _Objects_Extend_information(   information  );
           }
          
           /*
           * Take care of multiprocessing
           */
           #if defined(  RTEMS_MULTIPROCESSING )
           information->extract = extract;
          
           if (   (  supports_global == true ) && _System_state_Is_multiprocessing  ) {
          
           information->global_table =
           (  Chain_Control * ) _Workspace_Allocate_or_fatal_error(  
           (  _Objects_Maximum_nodes + 1 ) * sizeof(  Chain_Control )
            );
          
           for (   index=1; index <= _Objects_Maximum_nodes ; index++  )
           _Chain_Initialize_empty(   &information->global_table[ index ]  );
           }
           else
           information->global_table = NULL;
           #endif
          }

score/src/objectmp.c

       1  /*
           * Multiprocessing Support for the Object Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectmp.c,  v 1.27 2009/07/03 15:13:47 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/thread.h>
          
          /*PAGE
           *
           * _Objects_MP_Handler_early_initialization
           *
           */
      31  void _Objects_MP_Handler_early_initialization(  void )
          {
           uint32_t node;
           uint32_t maximum_nodes;
          
           node = _Configuration_MP_table->node;
           maximum_nodes = _Configuration_MP_table->maximum_nodes;
          
           if (   node < 1 || node > maximum_nodes  )
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_INVALID_NODE
            );
          
           _Objects_Local_node = node;
           _Objects_Maximum_nodes = maximum_nodes;
          }
          
          /*PAGE
           *
           * _Objects_MP_Handler_initialization
           *
           */
          
      56  void _Objects_MP_Handler_initialization(  void )
          {
          
           uint32_t maximum_global_objects;
          
           maximum_global_objects = _Configuration_MP_table->maximum_global_objects;
          
           _Objects_MP_Maximum_global_objects = maximum_global_objects;
          
           if (   maximum_global_objects == 0  ) {
           _Chain_Initialize_empty(   &_Objects_MP_Inactive_global_objects  );
           return;
           }
          
           _Chain_Initialize(  
           &_Objects_MP_Inactive_global_objects,  
           _Workspace_Allocate_or_fatal_error(  
           maximum_global_objects * sizeof(   Objects_MP_Control  )
            ),  
           maximum_global_objects,  
           sizeof(   Objects_MP_Control  )
            );
          
          }
          
          /*PAGE
           *
           * _Objects_MP_Open
           *
           */
          
      87  void _Objects_MP_Open (  
           Objects_Information *information,  
           Objects_MP_Control *the_global_object,  
           uint32_t the_name,   /* XXX -- wrong for variable */
           Objects_Id the_id
           )
          {
           the_global_object->Object.id = the_id;
           the_global_object->name = the_name;
          
           _Chain_Prepend(  
           &information->global_table[ _Objects_Get_node(   the_id  ) ],  
           &the_global_object->Object.Node
            );
          
          }
          
          /*PAGE
           *
           * _Objects_MP_Allocate_and_open
           *
           */
          
     110  bool _Objects_MP_Allocate_and_open (  
           Objects_Information *information,  
           uint32_t the_name,   /* XXX -- wrong for variable */
           Objects_Id the_id,  
           bool is_fatal_error
           )
          {
           Objects_MP_Control *the_global_object;
          
           the_global_object = _Objects_MP_Allocate_global_object(   );
           if (   _Objects_MP_Is_null_global_object(   the_global_object  )  ) {
          
           if (   is_fatal_error == false  )
           return false;
          
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS
            );
          
           }
          
           _Objects_MP_Open(   information,   the_global_object,   the_name,   the_id  );
          
           return true;
          }
          
          /*PAGE
           *
           * _Objects_MP_Close
           *
           */
          
     144  void _Objects_MP_Close (  
           Objects_Information *information,  
           Objects_Id the_id
           )
          {
           Chain_Control *the_chain;
           Chain_Node *the_node;
           Objects_MP_Control *the_object;
          
           the_chain = &information->global_table[ _Objects_Get_node(   the_id  ) ];
          
           for (   the_node = the_chain->first ;
           !_Chain_Is_tail(   the_chain,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_object = (  Objects_MP_Control * ) the_node;
          
           if (   _Objects_Are_ids_equal(   the_object->Object.id,   the_id  )  ) {
          
           _Chain_Extract(   the_node  );
           _Objects_MP_Free_global_object(   the_object  );
           return;
           }
          
           }
          
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_INVALID_GLOBAL_ID
            );
          }
          
          /*PAGE
           *
           * _Objects_MP_Global_name_search
           *
           */
          
     183  Objects_Name_or_id_lookup_errors _Objects_MP_Global_name_search (  
           Objects_Information *information,  
           Objects_Name the_name,  
           uint32_t nodes_to_search,  
           Objects_Id *the_id
           )
          {
           uint32_t low_node;
           uint32_t high_node;
           uint32_t node_index;
           Chain_Control *the_chain;
           Chain_Node *the_node;
           Objects_MP_Control *the_object;
           uint32_t name_to_use;
          
           name_to_use = the_name.name_u32; /* XXX only fixed length names */
          
           if (   nodes_to_search > _Objects_Maximum_nodes  )
           return OBJECTS_INVALID_NODE;
          
           if (   information->global_table == NULL  )
           return OBJECTS_INVALID_NAME;
          
           if (   nodes_to_search == OBJECTS_SEARCH_ALL_NODES ||
           nodes_to_search == OBJECTS_SEARCH_OTHER_NODES  ) {
           low_node = 1;
           high_node = _Objects_Maximum_nodes;
           } else {
           low_node =
           high_node = nodes_to_search;
           }
          
           _Thread_Disable_dispatch(   );
          
           for (   node_index = low_node ; node_index <= high_node ; node_index++  ) {
          
           /*
           * NOTE: The local node was search (  if necessary ) by
           * _Objects_Name_to_id_XXX before this was invoked.
           */
          
           if (   !_Objects_Is_local_node(   node_index  )  ) {
           the_chain = &information->global_table[ node_index ];
          
           for (   the_node = the_chain->first ;
           !_Chain_Is_tail(   the_chain,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_object = (  Objects_MP_Control * ) the_node;
          
           if (   the_object->name == name_to_use  ) {
           *the_id = the_object->Object.id;
           _Thread_Enable_dispatch(   );
           return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
           }
           }
           }
           }
          
           _Thread_Enable_dispatch(   );
           return OBJECTS_INVALID_NAME;
          }
          
          /*PAGE
           *
           * _Objects_MP_Is_remote
           *
           */
          
     252  void _Objects_MP_Is_remote (  
           Objects_Information *information,  
           Objects_Id the_id,  
           Objects_Locations *location,  
           Objects_Control **the_object
           )
          {
           uint32_t node;
           Chain_Control *the_chain;
           Chain_Node *the_node;
           Objects_MP_Control *the_global_object;
          
           node = _Objects_Get_node(   the_id  );
          
           /*
           * NOTE: The local node was search (  if necessary ) by
           * _Objects_Name_to_id_XXX before this was invoked.
           *
           * The NODE field of an object id cannot be 0
           * because 0 is an invalid node number.
           */
          
           if (   node == 0 ||
           _Objects_Is_local_node(   node  ) ||
           node > _Objects_Maximum_nodes ||
           information->global_table == NULL  ) {
          
           *location = OBJECTS_ERROR;
           *the_object = NULL;
           return;
           }
          
           _Thread_Disable_dispatch(   );
          
           the_chain = &information->global_table[ node ];
          
           for (   the_node = the_chain->first ;
           !_Chain_Is_tail(   the_chain,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_global_object = (  Objects_MP_Control * ) the_node;
          
           if (   _Objects_Are_ids_equal(   the_global_object->Object.id,   the_id  )  ) {
           _Thread_Unnest_dispatch(   );
           *location = OBJECTS_REMOTE;
           *the_object = (  Objects_Control * ) the_global_object;
           return;
           }
           }
          
           _Thread_Enable_dispatch(   );
           *location = OBJECTS_ERROR;
           *the_object = NULL;
          
          }
          

score/src/objectnamespaceremove.c

       1  /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectnamespaceremove.c,  v 1.2 2009/09/11 14:54:29 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/wkspace.h>
          
      20  void _Objects_Namespace_remove(  
           Objects_Information *information,  
           Objects_Control *the_object
           )
          {
           #if defined(  RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES )
           /*
           * If this is a string format name,   then free the memory.
           */
           if (   information->is_string && the_object->name.name_p  )
           _Workspace_Free(   (  void * )the_object->name.name_p  );
           #endif
          
           /*
           * Clear out either format.
           */
           #if defined(  RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES )
           the_object->name.name_p = NULL;
           #endif
           the_object->name.name_u32 = 0;
          }

score/src/objectnametoid.c

       1  /*
           * Object Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectnametoid.c,  v 1.14 2008/12/22 05:52:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/object.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/objectmp.h>
          #endif
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/isr.h>
          
          /*PAGE
           *
           * _Objects_Name_to_id_u32
           *
           * These kernel routines search the object table(  s ) for the given
           * object name and returns the associated object id.
           *
           * Input parameters:
           * information - object information
           * name - user defined object name
           * node - node indentifier (  0 indicates any node )
           * id - address of return ID
           *
           * Output parameters:
           * id - object id
           * OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      50  Objects_Name_or_id_lookup_errors _Objects_Name_to_id_u32(  
           Objects_Information *information,  
           uint32_t name,  
           uint32_t node,  
           Objects_Id *id
           )
          {
           bool search_local_node;
           Objects_Control *the_object;
           uint32_t index;
           uint32_t name_length;
          #if defined(  RTEMS_MULTIPROCESSING )
           Objects_Name name_for_mp;
          #endif
          
           /* ASSERT: information->is_string == false */
          
           if (   !id  )
           return OBJECTS_INVALID_ADDRESS;
          
           if (   name == 0  )
           return OBJECTS_INVALID_NAME;
          
           search_local_node = false;
          
           if (   information->maximum != 0 &&
           (  node == OBJECTS_SEARCH_ALL_NODES ||
           node == OBJECTS_SEARCH_LOCAL_NODE ||
           _Objects_Is_local_node(   node  )
            ) )
           search_local_node = true;
          
           if (   search_local_node  ) {
           name_length = information->name_length;
          
           for (   index = 1; index <= information->maximum; index++  ) {
           the_object = information->local_table[ index ];
           if (   !the_object  )
           continue;
          
           if (   name == the_object->name.name_u32  ) {
           *id = the_object->id;
           return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
           }
           }
           }
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Objects_Is_local_node(   node  ) || node == OBJECTS_SEARCH_LOCAL_NODE  )
           return OBJECTS_INVALID_NAME;
          
           name_for_mp.name_u32 = name;
           return _Objects_MP_Global_name_search(   information,   name_for_mp,   node,   id  );
          #else
           return OBJECTS_INVALID_NAME;
          #endif
          }

score/src/objectnametoidstring.c

       1  /*
           * Object Handler - Object ID to Name (  String )
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectnametoidstring.c,  v 1.7 2009/09/11 20:00:30 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <string.h>
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/object.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/objectmp.h>
          #endif
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/isr.h>
          
          #if defined(  RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES )
          /*PAGE
           *
           * _Objects_Name_to_id_string
           *
           * These kernel routines search the object table(  s ) for the given
           * object name and returns the associated object id.
           *
           * Input parameters:
           * information - object information
           * name - user defined object name
           * id - address of return ID
           *
           * Output parameters:
           * id - object id
           * OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL - if successful
           * error code - if unsuccessful
           */
          
      52  Objects_Name_or_id_lookup_errors _Objects_Name_to_id_string(  
           Objects_Information *information,  
           const char *name,  
           Objects_Id *id
           )
          {
           Objects_Control *the_object;
           uint32_t index;
           uint32_t name_length;
          
           /* ASSERT: information->is_string == true */
          
           if (   !id  )
           return OBJECTS_INVALID_ADDRESS;
          
           if (   !name  )
           return OBJECTS_INVALID_NAME;
          
           if (   information->maximum != 0  ) {
           name_length = information->name_length;
          
           for (   index = 1; index <= information->maximum; index++  ) {
           the_object = information->local_table[ index ];
           if (   !the_object  )
           continue;
          
           if (   !the_object->name.name_p  )
           continue;
          
           if (  !strncmp(   name,   the_object->name.name_p,   information->name_length ) ) {
           *id = the_object->id;
           return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
           }
           }
           }
          
           return OBJECTS_INVALID_NAME;
          }
          #endif

score/src/objectsetname.c

       1  /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectsetname.c,  v 1.8 2009/12/07 17:27:46 joel Exp $
           */
          
          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/object.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <stdlib.h>
          #include <ctype.h>
          #include <inttypes.h>
          #include <string.h>
          
          
          /*
           * This method sets the name of an object based upon a C string.
           */
          
      30  bool _Objects_Set_name(  
           Objects_Information *information,  
           Objects_Control *the_object,  
           const char *name
           )
          {
           size_t length;
           const char *s;
          
           s = name;
           length = strnlen(   name,   information->name_length  );
          
          #if defined(  RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES )
           if (   information->is_string  ) {
           char *d;
          
           d = _Workspace_Allocate(   length + 1  );
           if (   !d  )
           return false;
          
           if (   the_object->name.name_p  ) {
           _Workspace_Free(   (  void * )the_object->name.name_p  );
           the_object->name.name_p = NULL;
           }
          
           strncpy(   d,   name,   length  );
           d[length] = '\0';
           the_object->name.name_p = d;
           } else
          #endif
           {
           the_object->name.name_u32 = _Objects_Build_name(  
           (  (  0 <= length ) ? s[ 0 ] : ' ' ),  
           (  (  1 < length ) ? s[ 1 ] : ' ' ),  
           (  (  2 < length ) ? s[ 2 ] : ' ' ),  
           (  (  3 < length ) ? s[ 3 ] : ' ' )
            );
          
           }
          
           return true;
          }

score/src/objectshrinkinformation.c

       1  /*
           * Object Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: objectshrinkinformation.c,  v 1.9 2009/07/07 22:47:03 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/address.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/object.h>
          #if defined(  RTEMS_MULTIPROCESSING )
          #include <rtems/score/objectmp.h>
          #endif
          #include <rtems/score/thread.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/isr.h>
          
          /*PAGE
           *
           * _Objects_Shrink_information
           *
           * This routine shrinks object information related data structures.
           * The object's name and object space are released. The local_table
           * etc block does not shrink. The InActive list needs to be scanned
           * to find the objects are remove them.
           * Input parameters:
           * information - object information table
           * the_block - the block to remove
           *
           * Output parameters: NONE
           */
          
      46  void _Objects_Shrink_information(  
           Objects_Information *information
           )
          {
           Objects_Control *the_object;
           Objects_Control *extract_me;
           uint32_t block_count;
           uint32_t block;
           uint32_t index_base;
           uint32_t index;
          
           /*
           * Search the list to find block or chunk with all objects inactive.
           */
          
           index_base = _Objects_Get_index(   information->minimum_id  );
           block_count = (  information->maximum - index_base ) /
           information->allocation_size;
          
           for (   block = 0; block < block_count; block++  ) {
           if (   information->inactive_per_block[ block ] ==
           information->allocation_size  ) {
          
           /*
           * Assume the Inactive chain is never empty at this point
           */
           the_object = (  Objects_Control * ) information->Inactive.first;
          
           do {
           index = _Objects_Get_index(   the_object->id  );
           /*
           * Get the next node before the node is extracted
           */
           extract_me = the_object;
           the_object = (  Objects_Control * ) the_object->Node.next;
           if (  (  index >= index_base ) &&
           (  index < (  index_base + information->allocation_size ) ) ) {
           _Chain_Extract(   &extract_me->Node  );
           }
           }
           while (   the_object  );
           /*
           * Free the memory and reset the structures in the object' information
           */
          
           _Workspace_Free(   information->object_blocks[ block ]  );
           information->object_blocks[ block ] = NULL;
           information->inactive_per_block[ block ] = 0;
          
           information->inactive -= information->allocation_size;
          
           return;
           }
          
           index_base += information->allocation_size;
           }
          }

score/src/percpu.c

       1  /*
           * COPYRIGHT (  c ) 1989-2010.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: percpu.c,  v 1.1 2010/06/29 00:34:11 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/percpu.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/config.h>
          #include <string.h>
          
          /*
           * On single core systems,   we can efficiently directly access a single
           * statically allocated per cpu structure. And the fields are initialized
           * as individual elements just like it has always been done.
           */
          Per_CPU_Control _Per_CPU_Information;

score/src/pheapallocate.c

       1  /**
           * @file
           *
           * @ingroup ScoreProtHeap
           *
           * @brief Protected Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pheapallocate.c,  v 1.4 2009/11/30 13:05:29 thomas Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/protectedheap.h>
          
      27  void *_Protected_heap_Allocate_aligned_with_boundary(  
           Heap_Control *heap,  
           uintptr_t size,  
           uintptr_t alignment,  
           uintptr_t boundary
           )
          {
           void *p;
          
           _RTEMS_Lock_allocator(   );
           p = _Heap_Allocate_aligned_with_boundary(  
           heap,  
           size,  
           alignment,  
           boundary
            );
           _RTEMS_Unlock_allocator(   );
          
           return p;
          }

score/src/pheapextend.c

       1  /**
           * @file
           *
           * @ingroup ScoreProtHeap
           *
           * @brief Protected Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pheapextend.c,  v 1.5 2010/06/07 09:35:01 sh Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/protectedheap.h>
          
      27  bool _Protected_heap_Extend(  
           Heap_Control *the_heap,  
           void *starting_address,  
           uintptr_t size
           )
          {
           bool extend_ok;
           uintptr_t amount_extended;
          
           _RTEMS_Lock_allocator(   );
           extend_ok = _Heap_Extend(  the_heap,   starting_address,   size,   &amount_extended );
           _RTEMS_Unlock_allocator(   );
           return extend_ok;
          }
          

score/src/pheapfree.c

       1  /**
           * @file
           *
           * @ingroup ScoreProtHeap
           *
           * @brief Protected Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pheapfree.c,  v 1.3 2009/09/06 15:24:07 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/protectedheap.h>
          
      27  bool _Protected_heap_Free(  
           Heap_Control *the_heap,  
           void *start_address
           )
          {
           bool status;
          
           _RTEMS_Lock_allocator(   );
           status = _Heap_Free(   the_heap,   start_address  );
           _RTEMS_Unlock_allocator(   );
           return status;
          }

score/src/pheapgetblocksize.c

       1  /**
           * @file
           *
           * @ingroup ScoreProtHeap
           *
           * @brief Protected Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pheapgetblocksize.c,  v 1.8 2009/09/06 15:24:07 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/protectedheap.h>
          
      27  bool _Protected_heap_Get_block_size(  
           Heap_Control *the_heap,  
           void *starting_address,  
           uintptr_t *size
           )
          {
           bool status;
          
           _RTEMS_Lock_allocator(   );
           status = _Heap_Size_of_alloc_area(   the_heap,   starting_address,   size  );
           _RTEMS_Unlock_allocator(   );
           return status;
          }

score/src/pheapgetfreeinfo.c

       1  /**
           * @file
           *
           * @ingroup ScoreProtHeap
           *
           * @brief Protected Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pheapgetfreeinfo.c,  v 1.3 2009/09/06 15:24:07 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/protectedheap.h>
          
      27  bool _Protected_heap_Get_free_information(  
           Heap_Control *the_heap,  
           Heap_Information *info
           )
          {
           /*
           * TBD: _Heap_Get_free_information does not error check or return status.
           */
          
           _RTEMS_Lock_allocator(   );
           _Heap_Get_free_information(   the_heap,   info  );
           _RTEMS_Unlock_allocator(   );
          
           return true;
          }
          

score/src/pheapgetinfo.c

       1  /**
           * @file
           *
           * @ingroup ScoreProtHeap
           *
           * @brief Protected Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pheapgetinfo.c,  v 1.3 2009/09/06 15:24:07 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/protectedheap.h>
          
      27  bool _Protected_heap_Get_information(  
           Heap_Control *the_heap,  
           Heap_Information_block *the_info
           )
          {
           if (   !the_heap  )
           return false;
          
           if (   !the_info  )
           return false;
          
           _RTEMS_Lock_allocator(   );
           _Heap_Get_information(   the_heap,   the_info  );
           _RTEMS_Unlock_allocator(   );
          
           return true;
          }

score/src/pheapgetsize.c

       1  /**
           * @file
           *
           * @ingroup ScoreProtHeap
           *
           * @brief Protected Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pheapgetsize.c,  v 1.2 2009/09/06 15:24:08 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/protectedheap.h>
          
      27  uintptr_t _Protected_heap_Get_size(  
           Heap_Control *the_heap
           )
          {
           return _Heap_Get_size(   the_heap  );
          }

score/src/pheapinit.c

       1  /**
           * @file
           *
           * @ingroup ScoreProtHeap
           *
           * @brief Protected Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pheapinit.c,  v 1.2 2009/09/06 15:24:08 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/protectedheap.h>
          
          

score/src/pheapresizeblock.c

       1  /**
           * @file
           *
           * @ingroup ScoreProtHeap
           *
           * @brief Protected Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pheapresizeblock.c,  v 1.5 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/protectedheap.h>
          
      27  bool _Protected_heap_Resize_block(  
           Heap_Control *the_heap,  
           void *starting_address,  
           uintptr_t size
           )
          {
           Heap_Resize_status status;
           uintptr_t old_mem_size;
           uintptr_t avail_mem_size;
          
           _RTEMS_Lock_allocator(   );
           status = _Heap_Resize_block(  
           the_heap,   starting_address,   size,   &old_mem_size,   &avail_mem_size  );
           _RTEMS_Unlock_allocator(   );
           return (  status == HEAP_RESIZE_SUCCESSFUL );
          }
          

score/src/pheapwalk.c

       1  /**
           * @file
           *
           * @ingroup ScoreProtHeap
           *
           * @brief Protected Heap Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: pheapwalk.c,  v 1.5 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/protectedheap.h>
          
      27  bool _Protected_heap_Walk(  
           Heap_Control *the_heap,  
           int source,  
           bool do_dump
           )
          {
           bool status;
          
           /*
           * If we are called from within a dispatching critical section,  
           * then it is forbidden to lock a mutex. But since we are inside
           * a critical section,   it should be safe to walk it unlocked.
           *
           * NOTE: Dispatching is also disabled during initialization.
           */
           if (   !_Thread_Dispatch_disable_level  ) {
           _RTEMS_Lock_allocator(   );
           status = _Heap_Walk(   the_heap,   source,   do_dump  );
           _RTEMS_Unlock_allocator(   );
           } else {
           status = _Heap_Walk(   the_heap,   source,   do_dump  );
           }
           return status;
          }

score/src/thread.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: thread.c,  v 1.64 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/config.h>
          
          /*PAGE
           *
           * _Thread_Handler_initialization
           *
           * This routine initializes all thread manager related data structures.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      46  void _Thread_Handler_initialization(  void )
          {
           uint32_t index;
           uint32_t ticks_per_timeslice;
           uint32_t maximum_extensions;
           #if defined(  RTEMS_MULTIPROCESSING )
           uint32_t maximum_proxies;
           #endif
          
           ticks_per_timeslice = Configuration.ticks_per_timeslice;
           maximum_extensions = Configuration.maximum_extensions;
           #if defined(  RTEMS_MULTIPROCESSING )
           maximum_proxies = _Configuration_MP_table->maximum_proxies;
           #endif
           /*
           * BOTH stacks hooks must be set or both must be NULL.
           * Do not allow mixture.
           */
           if (   !(   (  !Configuration.stack_allocate_hook )
           == (  !Configuration.stack_free_hook )  )  )
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_BAD_STACK_HOOK
            );
          
           _Thread_Dispatch_necessary = false;
           _Thread_Executing = NULL;
           _Thread_Heir = NULL;
          #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
           _Thread_Allocated_fp = NULL;
          #endif
          
           _Thread_Maximum_extensions = maximum_extensions;
          
           _Thread_Ticks_per_timeslice = ticks_per_timeslice;
          
           _Thread_Ready_chain = (  Chain_Control * ) _Workspace_Allocate_or_fatal_error(  
           (  PRIORITY_MAXIMUM + 1 ) * sizeof(  Chain_Control )
            );
          
           for (   index=0; index <= PRIORITY_MAXIMUM ; index++  )
           _Chain_Initialize_empty(   &_Thread_Ready_chain[ index ]  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           _Thread_MP_Handler_initialization(   maximum_proxies  );
          #endif
          
           /*
           * Initialize this class of objects.
           */
          
           _Objects_Initialize_information(  
           &_Thread_Internal_information,  
           OBJECTS_INTERNAL_API,  
           OBJECTS_INTERNAL_THREADS,  
          #if defined(  RTEMS_MULTIPROCESSING )
           (   _System_state_Is_multiprocessing  ) ? 2 : 1,  
          #else
           1,  
          #endif
           sizeof(   Thread_Control  ),  
           /* size of this object's control block */
           false,   /* true if names for this object are strings */
           8 /* maximum length of each object's name */
          #if defined(  RTEMS_MULTIPROCESSING )
           ,  
           false,   /* true if this is a global object class */
           NULL /* Proxy extraction support callout */
          #endif
            );
          
          }

score/src/threadblockingoperationcancel.c

       1  /*
           * Cancel Thread Blocking Operation
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadblockingoperationcancel.c,  v 1.6 2008/12/31 03:33:08 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/thread.h>
          #if defined(  RTEMS_DEBUG )
          #include <rtems/score/interr.h>
          #endif
          
      25  void _Thread_blocking_operation_Cancel(  
          #if defined(  RTEMS_DEBUG )
           Thread_blocking_operation_States sync_state,  
          #else
           Thread_blocking_operation_States sync_state __attribute__(  (  unused ) ),  
          #endif
           Thread_Control *the_thread,  
           ISR_Level level
           )
          {
           /*
           * Cases that should not happen and why.
           *
           * THREAD_BLOCKING_OPERATION_SYNCHRONIZED:
           *
           * This indicates that someone did not enter a blocking
           * operation critical section.
           *
           * THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED:
           *
           * This indicates that there was nothing to cancel so
           * we should not have been called.
           */
          
           #if defined(  RTEMS_DEBUG )
           if (   (  sync_state == THREAD_BLOCKING_OPERATION_SYNCHRONIZED ) ||
           (  sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )  ) {
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL
            );
           }
           #endif
          
           /*
           * The thread is not waiting on anything after this completes.
           */
           the_thread->Wait.queue = NULL;
          
           /*
           * If the sync state is timed out,   this is very likely not needed.
           * But better safe than sorry when it comes to critical sections.
           */
           if (   _Watchdog_Is_active(   &the_thread->Timer  )  ) {
           _Watchdog_Deactivate(   &the_thread->Timer  );
           _ISR_Enable(   level  );
           (  void ) _Watchdog_Remove(   &the_thread->Timer  );
           } else
           _ISR_Enable(   level  );
          
           /*
           * Global objects with thread queue's should not be operated on from an
           * ISR. But the sync code still must allow short timeouts to be processed
           * correctly.
           */
          
           _Thread_Unblock(   the_thread  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   !_Objects_Is_local_id(   the_thread->Object.id  )  )
           _Thread_MP_Free_proxy(   the_thread  );
          #endif
          
          }

score/src/threadchangepriority.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2006.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadchangepriority.c,  v 1.14 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Change_priority
           *
           * This kernel routine changes the priority of the thread. The
           * thread chain is adjusted if necessary.
           *
           * Input parameters:
           * the_thread - pointer to thread control block
           * new_priority - ultimate priority
           * prepend_it - true if the thread should be prepended to the chain
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * ready chain
           * select heir
           */
          
      52  void _Thread_Change_priority(  
           Thread_Control *the_thread,  
           Priority_Control new_priority,  
           bool prepend_it
           )
          {
           ISR_Level level;
           States_Control state,   original_state;
          
           /*
           * If this is a case where prepending the task to its priority is
           * potentially desired,   then we need to consider whether to do it.
           * This usually occurs when a task lowers its priority implcitly as
           * the result of losing inherited priority. Normal explicit priority
           * change calls (  e.g. rtems_task_set_priority ) should always do an
           * append not a prepend.
           */
          /*
           if (   prepend_it &&
           _Thread_Is_executing(   the_thread  ) &&
           new_priority >= the_thread->current_priority  )
           prepend_it = true;
          */
          
           /*
           * Save original state
           */
           original_state = the_thread->current_state;
          
           /*
           * Set a transient state for the thread so it is pulled off the Ready chains.
           * This will prevent it from being scheduled no matter what happens in an
           * ISR.
           */
           _Thread_Set_transient(   the_thread  );
          
           /*
           * Do not bother recomputing all the priority related information if
           * we are not REALLY changing priority.
           */
           if (   the_thread->current_priority != new_priority  )
           _Thread_Set_priority(   the_thread,   new_priority  );
          
           _ISR_Disable(   level  );
          
           /*
           * If the thread has more than STATES_TRANSIENT set,   then it is blocked,  
           * If it is blocked on a thread queue,   then we need to requeue it.
           */
           state = the_thread->current_state;
           if (   state != STATES_TRANSIENT  ) {
           /* Only clear the transient state if it wasn't set already */
           if (   ! _States_Is_transient(   original_state  )  )
           the_thread->current_state = _States_Clear(   STATES_TRANSIENT,   state  );
           _ISR_Enable(   level  );
           if (   _States_Is_waiting_on_thread_queue(   state  )  ) {
           _Thread_queue_Requeue(   the_thread->Wait.queue,   the_thread  );
           }
           return;
           }
          
           /* Only clear the transient state if it wasn't set already */
           if (   ! _States_Is_transient(   original_state  )  ) {
           /*
           * Interrupts are STILL disabled.
           * We now know the thread will be in the READY state when we remove
           * the TRANSIENT state. So we have to place it on the appropriate
           * Ready Queue with interrupts off.
           */
           the_thread->current_state = _States_Clear(   STATES_TRANSIENT,   state  );
          
           _Priority_bit_map_Add(   &the_thread->Priority_map  );
           if (   prepend_it  )
           _Chain_Prepend_unprotected(   the_thread->ready,   &the_thread->Object.Node  );
           else
           _Chain_Append_unprotected(   the_thread->ready,   &the_thread->Object.Node  );
           }
          
           _ISR_Flash(   level  );
          
           /*
           * We altered the set of thread priorities. So let's figure out
           * who is the heir and if we need to switch to them.
           */
           _Thread_Calculate_heir(   );
          
           if (   !_Thread_Is_executing_also_the_heir(   ) &&
           _Thread_Executing->is_preemptible  )
           _Thread_Dispatch_necessary = true;
           _ISR_Enable(   level  );
          }

score/src/threadclearstate.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadclearstate.c,  v 1.12 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Clear_state
           *
           * This kernel routine clears the appropriate states in the
           * requested thread. The thread ready chain is adjusted if
           * necessary and the Heir thread is set accordingly.
           *
           * Input parameters:
           * the_thread - pointer to thread control block
           * state - state set to clear
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * priority map
           * select heir
           */
          
          
      53  void _Thread_Clear_state(  
           Thread_Control *the_thread,  
           States_Control state
           )
          {
           ISR_Level level;
           States_Control current_state;
          
           _ISR_Disable(   level  );
           current_state = the_thread->current_state;
          
           if (   current_state & state  ) {
           current_state =
           the_thread->current_state = _States_Clear(   state,   current_state  );
          
           if (   _States_Is_ready(   current_state  )  ) {
          
           _Priority_bit_map_Add(   &the_thread->Priority_map  );
          
           _Chain_Append_unprotected(  the_thread->ready,   &the_thread->Object.Node );
          
           _ISR_Flash(   level  );
          
           /*
           * If the thread that was unblocked is more important than the heir,  
           * then we have a new heir. This may or may not result in a
           * context switch.
           *
           * Normal case:
           * If the current thread is preemptible,   then we need to do
           * a context switch.
           * Pseudo-ISR case:
           * Even if the thread isn't preemptible,   if the new heir is
           * a pseudo-ISR system task,   we need to do a context switch.
           */
           if (   the_thread->current_priority < _Thread_Heir->current_priority  ) {
           _Thread_Heir = the_thread;
           if (   _Thread_Executing->is_preemptible ||
           the_thread->current_priority == 0  )
           _Thread_Dispatch_necessary = true;
           }
           }
           }
           _ISR_Enable(   level  );
          }

score/src/threadclose.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadclose.c,  v 1.12 2008/05/22 20:38:03 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*
           * _Thread_Close
           *
           * DESCRIPTION:
           *
           * This routine frees all memory associated with the specified
           * thread and removes it from the local object table so no further
           * operations on this thread are allowed.
           */
          
      43  void _Thread_Close(  
           Objects_Information *information,  
           Thread_Control *the_thread
           )
          {
          
           /*
           * Now we are in a dispatching critical section again and we
           * can take the thread OUT of the published set. It is invalid
           * to use this thread's Id after this call. This will prevent
           * any other task from attempting to initiate a call on this task.
           */
           _Objects_Invalidate_Id(   information,   &the_thread->Object  );
          
           /*
           * We assume the Allocator Mutex is locked when we get here.
           * This provides sufficient protection to let the user extensions
           * run but as soon as we get back,   we will make the thread
           * disappear and set a transient state on it. So we temporarily
           * unnest dispatching.
           */
           _Thread_Unnest_dispatch(   );
          
           _User_extensions_Thread_delete(   the_thread  );
          
           _Thread_Disable_dispatch(   );
          
           /*
           * Now we are in a dispatching critical section again and we
           * can take the thread OUT of the published set. It is invalid
           * to use this thread's Id OR name after this call.
           */
           _Objects_Close(   information,   &the_thread->Object  );
          
           /*
           * By setting the dormant state,   the thread will not be considered
           * for scheduling when we remove any blocking states.
           */
           _Thread_Set_state(   the_thread,   STATES_DORMANT  );
          
           if (   !_Thread_queue_Extract_with_proxy(   the_thread  )  ) {
           if (   _Watchdog_Is_active(   &the_thread->Timer  )  )
           (  void ) _Watchdog_Remove(   &the_thread->Timer  );
           }
          
           /*
           * The thread might have been FP. So deal with that.
           */
          #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
          #if (   CPU_USE_DEFERRED_FP_SWITCH == TRUE  )
           if (   _Thread_Is_allocated_fp(   the_thread  )  )
           _Thread_Deallocate_fp(   );
          #endif
           the_thread->fp_context = NULL;
          
           if (   the_thread->Start.fp_context  )
           (  void ) _Workspace_Free(   the_thread->Start.fp_context  );
          #endif
          
           /*
           * Free the rest of the memory associated with this task
           * and set the associated pointers to NULL for safety.
           */
           _Thread_Stack_Free(   the_thread  );
           the_thread->Start.stack = NULL;
          
           if (   the_thread->extensions  )
           (  void ) _Workspace_Free(   the_thread->extensions  );
           the_thread->extensions = NULL;
          }

score/src/threadcreateidle.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadcreateidle.c,  v 1.15 2009/09/11 14:54:29 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/config.h>
          
          /*PAGE
           *
           * _Thread_Create_idle
           */
          
      39  void _Thread_Create_idle(   void  )
          {
           Objects_Name name;
          
           name.name_u32 = _Objects_Build_name(   'I',   'D',   'L',   'E'  );
          
           /*
           * The entire workspace is zeroed during its initialization. Thus,   all
           * fields not explicitly assigned were explicitly zeroed by
           * _Workspace_Initialization.
           */
           _Thread_Idle = _Thread_Internal_allocate(   );
          
           /*
           * This is only called during initialization and we better be sure
           * that when _Thread_Initialize unnests dispatch that we do not
           * do anything stupid.
           */
           _Thread_Disable_dispatch(   );
          
           _Thread_Initialize(  
           &_Thread_Internal_information,  
           _Thread_Idle,  
           NULL,   /* allocate the stack */
           _Stack_Ensure_minimum(   Configuration.idle_task_stack_size  ),  
           CPU_IDLE_TASK_IS_FP,  
           PRIORITY_MAXIMUM,  
           true,   /* preemptable */
           THREAD_CPU_BUDGET_ALGORITHM_NONE,  
           NULL,   /* no budget algorithm callout */
           0,   /* all interrupts enabled */
           name
            );
          
           _Thread_Unnest_dispatch(   );
          
           /*
           * WARNING!!! This is necessary to "kick" start the system and
           * MUST be done before _Thread_Start is invoked.
           */
           _Thread_Heir =
           _Thread_Executing = _Thread_Idle;
          
           _Thread_Start(  
           _Thread_Idle,  
           THREAD_START_NUMERIC,  
           Configuration.idle_task,  
           NULL,  
           0
            );
          
          }

score/src/threaddelayended.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2007.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threaddelayended.c,  v 1.7 2009/11/30 19:44:57 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Delay_ended
           *
           * This routine processes a thread whose delay period has ended.
           * It is called by the watchdog handler.
           *
           * Input parameters:
           * id - thread id
           *
           * Output parameters: NONE
           */
          
      46  void _Thread_Delay_ended(  
           Objects_Id id,  
           void *ignored __attribute__(  (  unused ) )
           )
          {
           Thread_Control *the_thread;
           Objects_Locations location;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
           case OBJECTS_ERROR:
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* impossible */
          #endif
           break;
           case OBJECTS_LOCAL:
           _Thread_Clear_state(  
           the_thread,  
           STATES_DELAYING
           | STATES_WAITING_FOR_TIME
           | STATES_INTERRUPTIBLE_BY_SIGNAL
            );
           _Thread_Unnest_dispatch(   );
           break;
           }
          }

score/src/threaddispatch.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2009.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threaddispatch.c,  v 1.22 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           #include <rtems/score/timestamp.h>
          #endif
          
          /*PAGE
           *
           * _Thread_Enable_dispatch
           *
           * This kernel routine exits a context switch disable critical section.
           * This is the NOT INLINED version.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * dispatch thread
           * no dispatch thread
           */
          
          #if (   (  defined(  CPU_INLINE_ENABLE_DISPATCH ) && \
      54   (  CPU_INLINE_ENABLE_DISPATCH == FALSE ) ) || \
           (  __RTEMS_DO_NOT_INLINE_THREAD_ENABLE_DISPATCH__ == 1 )  )
          void _Thread_Enable_dispatch(   void  )
          {
           if (   --_Thread_Dispatch_disable_level  )
           return;
           _Thread_Dispatch(   );
          }
          #endif
          
          /*PAGE
           *
           * _Thread_Dispatch
           *
           * This kernel routine determines if a dispatch is needed,   and if so
           * dispatches to the heir thread. Once the heir is running an attempt
           * is made to dispatch any ASRs.
           *
           * ALTERNATE ENTRY POINTS:
           * void _Thread_Enable_dispatch(   );
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * dispatch thread
           * no dispatch thread
      82   */
          
          void _Thread_Dispatch(   void  )
          {
           Thread_Control *executing;
           Thread_Control *heir;
           ISR_Level level;
          
           executing = _Thread_Executing;
           _ISR_Disable(   level  );
           while (   _Thread_Dispatch_necessary == true  ) {
           heir = _Thread_Heir;
           _Thread_Dispatch_disable_level = 1;
           _Thread_Dispatch_necessary = false;
           _Thread_Executing = heir;
          
           /*
           * When the heir and executing are the same,   then we are being
           * requested to do the post switch dispatching. This is normally
           * done to dispatch signals.
           */
           if (   heir == executing  )
           goto post_switch;
          
           /*
           * Since heir and executing are not the same,   we need to do a real
           * context switch.
           */
          #if __RTEMS_ADA__
           executing->rtems_ada_self = rtems_ada_self;
           rtems_ada_self = heir->rtems_ada_self;
          #endif
           if (   heir->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE  )
           heir->cpu_time_budget = _Thread_Ticks_per_timeslice;
          
           _ISR_Enable(   level  );
          
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           {
           Timestamp_Control uptime,   ran;
           _TOD_Get_uptime(   &uptime  );
           _Timestamp_Subtract(  
           &_Thread_Time_of_last_context_switch,  
           &uptime,  
           &ran
            );
           _Timestamp_Add_to(   &executing->cpu_time_used,   &ran  );
           _Thread_Time_of_last_context_switch = uptime;
           }
           #else
           heir->cpu_time_used++;
           #endif
          
           /*
           * Switch libc's task specific data.
           */
           if (   _Thread_libc_reent  ) {
           executing->libc_reent = *_Thread_libc_reent;
           *_Thread_libc_reent = heir->libc_reent;
           }
          
           _User_extensions_Thread_switch(   executing,   heir  );
          
           /*
           * If the CPU has hardware floating point,   then we must address saving
           * and restoring it as part of the context switch.
           *
           * The second conditional compilation section selects the algorithm used
           * to context switch between floating point tasks. The deferred algorithm
           * can be significantly better in a system with few floating point tasks
           * because it reduces the total number of save and restore FP context
           * operations. However,   this algorithm can not be used on all CPUs due
           * to unpredictable use of FP registers by some compilers for integer
           * operations.
           */
          
          #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
          #if (   CPU_USE_DEFERRED_FP_SWITCH != TRUE  )
           if (   executing->fp_context != NULL  )
           _Context_Save_fp(   &executing->fp_context  );
          #endif
          #endif
          
           _Context_Switch(   &executing->Registers,   &heir->Registers  );
          
          #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
          #if (   CPU_USE_DEFERRED_FP_SWITCH == TRUE  )
           if (   (  executing->fp_context != NULL ) &&
           !_Thread_Is_allocated_fp(   executing  )  ) {
           if (   _Thread_Allocated_fp != NULL  )
           _Context_Save_fp(   &_Thread_Allocated_fp->fp_context  );
           _Context_Restore_fp(   &executing->fp_context  );
           _Thread_Allocated_fp = executing;
           }
          #else
           if (   executing->fp_context != NULL  )
           _Context_Restore_fp(   &executing->fp_context  );
          #endif
          #endif
          
           executing = _Thread_Executing;
          
           _ISR_Disable(   level  );
           }
          
          post_switch:
           _Thread_Dispatch_disable_level = 0;
          
           _ISR_Enable(   level  );
          
           _API_extensions_Run_postswitch(   );
          }

score/src/threadget.c

       1  /*
           * Thread Handler - Object Id to Thread Pointer
           *
           * COPYRIGHT (  c ) 1989-2010.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadget.c,  v 1.15 2010/07/27 02:17:31 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          
          
          /**
           * This function maps thread IDs to thread control
           * blocks. If ID corresponds to a local thread,   then it
           * returns the_thread control pointer which maps to ID
           * and location is set to OBJECTS_LOCAL. If the thread ID is
           * global and resides on a remote node,   then location is set
           * to OBJECTS_REMOTE,   and the_thread is undefined.
           * Otherwise,   location is set to OBJECTS_ERROR and
           * the_thread is undefined.
           *
           * @note The performance of many RTEMS services depends upon
           * the quick execution of the "good object" path in this
           * routine. If there is a possibility of saving a few
           * cycles off the execution time,   this routine is worth
           * further optimization attention.
           */
      47  Thread_Control *_Thread_Get (  
           Objects_Id id,  
           Objects_Locations *location
           )
          {
           uint32_t the_api;
           uint32_t the_class;
           Objects_Information **api_information;
           Objects_Information *information;
           Thread_Control *tp = (  Thread_Control * ) 0;
          
           if (   _Objects_Are_ids_equal(   id,   OBJECTS_ID_OF_SELF  )  ) {
           _Thread_Disable_dispatch(   );
           *location = OBJECTS_LOCAL;
           tp = _Thread_Executing;
           goto done;
           }
          
           the_api = _Objects_Get_API(   id  );
           if (   !_Objects_Is_api_valid(   the_api  )  ) {
           *location = OBJECTS_ERROR;
           goto done;
           }
          
           the_class = _Objects_Get_class(   id  );
           if (   the_class != 1  ) { /* threads are always first class : ) */
           *location = OBJECTS_ERROR;
           goto done;
           }
          
           api_information = _Objects_Information_table[ the_api ];
           /*
           * There is no way for this to happen if POSIX is enabled.
           */
           #if !defined(  RTEMS_POSIX_API )
           if (   !api_information  ) {
           *location = OBJECTS_ERROR;
           goto done;
           }
           #endif
          
           information = api_information[ the_class ];
           if (   !information  ) {
           *location = OBJECTS_ERROR;
           goto done;
           }
          
           tp = (  Thread_Control * ) _Objects_Get(   information,   id,   location  );
          
          done:
           return tp;
          }
          

score/src/threadhandler.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2009.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadhandler.c,  v 1.29 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          #if defined(  __AVR__ )
           #undef __USE_INIT_FINI__
          #endif
          
          #if defined(  __USE_INIT_FINI__ )
           #if defined(  __M32R__ )
           #define INIT_NAME __init
           #else
           #define INIT_NAME _init
           #endif
          
      44   extern void INIT_NAME(  void );
           #define EXECUTE_GLOBAL_CONSTRUCTORS
          #endif
          
          #if defined(  __USE__MAIN__ )
      49   extern void _main(  void );
           #define INIT_NAME __main
           #define EXECUTE_GLOBAL_CONSTRUCTORS
          #endif
          
          /*PAGE
           *
           * _Thread_Handler
           *
           * This routine is the "primal" entry point for all threads.
           * _Context_Initialize(   ) dummies up the thread's initial context
           * to cause the first Context_Switch(   ) to jump to _Thread_Handler(   ).
           *
           * This routine is the default thread exitted error handler. It is
           * returned to when a thread exits. The configured fatal error handler
           * is invoked to process the exit.
           *
           * NOTE:
           *
           * On entry,   it is assumed all interrupts are blocked and that this
           * routine needs to set the initial isr level. This may or may not
           * actually be needed by the context switch routine and as a result
           * interrupts may already be at there proper level. Either way,  
           * setting the initial isr level properly here is safe.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      79  void _Thread_Handler(   void  )
          {
           ISR_Level level;
           Thread_Control *executing;
           #if defined(  EXECUTE_GLOBAL_CONSTRUCTORS )
           static char doneConstructors;
           char doneCons;
           #endif
          
           executing = _Thread_Executing;
          
           /*
           * Some CPUs need to tinker with the call frame or registers when the
           * thread actually begins to execute for the first time. This is a
           * hook point where the port gets a shot at doing whatever it requires.
           */
           _Context_Initialization_at_thread_begin(   );
          
           /*
           * have to put level into a register for those cpu's that use
           * inline asm here
           */
          
           level = executing->Start.isr_level;
           _ISR_Set_level(  level );
          
           #if defined(  EXECUTE_GLOBAL_CONSTRUCTORS )
           doneCons = doneConstructors;
           doneConstructors = 1;
           #endif
          
           #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
           #if (   CPU_USE_DEFERRED_FP_SWITCH == TRUE  )
           if (   (  executing->fp_context != NULL ) &&
           !_Thread_Is_allocated_fp(   executing  )  ) {
           if (   _Thread_Allocated_fp != NULL  )
           _Context_Save_fp(   &_Thread_Allocated_fp->fp_context  );
           _Thread_Allocated_fp = executing;
           }
           #endif
           #endif
          
           /*
           * Take care that 'begin' extensions get to complete before
           * 'switch' extensions can run. This means must keep dispatch
           * disabled until all 'begin' extensions complete.
           */
           _User_extensions_Thread_begin(   executing  );
          
           /*
           * At this point,   the dispatch disable level BETTER be 1.
           */
           _Thread_Enable_dispatch(   );
          
           #if defined(  EXECUTE_GLOBAL_CONSTRUCTORS )
           /*
           * _init could be a weak symbol and we SHOULD test it but it isn't
           * in any configuration I know of and it generates a warning on every
           * RTEMS target configuration. --joel (  12 May 2007 )
           */
           if (  !doneCons ) /* && (  volatile void * )_init ) */ {
           INIT_NAME (   );
           }
           #endif
          
           if (   executing->Start.prototype == THREAD_START_NUMERIC  ) {
           executing->Wait.return_argument =
           (  *(  Thread_Entry_numeric ) executing->Start.entry_point )(  
           executing->Start.numeric_argument
            );
           }
           #if defined(  RTEMS_POSIX_API )
           else if (   executing->Start.prototype == THREAD_START_POINTER  ) {
           executing->Wait.return_argument =
           (  *(  Thread_Entry_pointer ) executing->Start.entry_point )(  
           executing->Start.pointer_argument
            );
           }
           #endif
           #if defined(  FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API )
           else if (   executing->Start.prototype == THREAD_START_BOTH_POINTER_FIRST  ) {
           executing->Wait.return_argument =
           (  *(  Thread_Entry_both_pointer_first ) executing->Start.entry_point )(  
           executing->Start.pointer_argument,  
           executing->Start.numeric_argument
            );
           }
           else if (   executing->Start.prototype == THREAD_START_BOTH_NUMERIC_FIRST  ) {
           executing->Wait.return_argument =
           (  *(  Thread_Entry_both_numeric_first ) executing->Start.entry_point )(  
           executing->Start.numeric_argument,  
           executing->Start.pointer_argument
            );
           }
           #endif
          
           /*
           * In the switch above,   the return code from the user thread body
           * was placed in return_argument. This assumed that if it returned
           * anything (  which is not supporting in all APIs ),   then it would be
           * able to fit in a (  void * ).
           */
          
           _User_extensions_Thread_exitted(   executing  );
          
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_THREAD_EXITTED
            );
          }

score/src/threadinitialize.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2009.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadinitialize.c,  v 1.39 2010/06/18 02:56:26 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Initialize
           *
           * This routine initializes the specified the thread. It allocates
           * all memory associated with this thread. It completes by adding
           * the thread to the local object table so operations on this
           * thread id are allowed.
           */
          
      44  bool _Thread_Initialize(  
           Objects_Information *information,  
           Thread_Control *the_thread,  
           void *stack_area,  
           size_t stack_size,  
           bool is_fp,  
           Priority_Control priority,  
           bool is_preemptible,  
           Thread_CPU_budget_algorithms budget_algorithm,  
           Thread_CPU_budget_algorithm_callout budget_callout,  
           uint32_t isr_level,  
           Objects_Name name
           )
          {
           size_t actual_stack_size = 0;
           void *stack = NULL;
           #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
           void *fp_area;
           #endif
           void *extensions_area;
           bool extension_status;
           int i;
          
           /*
           * Initialize the Ada self pointer
           */
           #if __RTEMS_ADA__
           the_thread->rtems_ada_self = NULL;
           #endif
          
           /*
           * Zero out all the allocated memory fields
           */
           for (   i=0 ; i <= THREAD_API_LAST ; i++  )
           the_thread->API_Extensions[i] = NULL;
          
           extensions_area = NULL;
           the_thread->libc_reent = NULL;
          
           #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
           fp_area = NULL;
           #endif
          
           /*
           * Allocate and Initialize the stack for this thread.
           */
           #if !defined(  RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API )
           actual_stack_size = _Thread_Stack_Allocate(   the_thread,   stack_size  );
           if (   !actual_stack_size || actual_stack_size < stack_size  )
           return false; /* stack allocation failed */
          
           stack = the_thread->Start.stack;
           #else
           if (   !stack_area  ) {
           actual_stack_size = _Thread_Stack_Allocate(   the_thread,   stack_size  );
           if (   !actual_stack_size || actual_stack_size < stack_size  )
           return false; /* stack allocation failed */
          
           stack = the_thread->Start.stack;
           the_thread->Start.core_allocated_stack = true;
           } else {
           stack = stack_area;
           actual_stack_size = stack_size;
           the_thread->Start.core_allocated_stack = false;
           }
           #endif
          
           _Stack_Initialize(  
           &the_thread->Start.Initial_stack,  
           stack,  
           actual_stack_size
            );
          
           /*
           * Allocate the floating point area for this thread
           */
           #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
           if (   is_fp  ) {
           fp_area = _Workspace_Allocate(   CONTEXT_FP_SIZE  );
           if (   !fp_area  )
           goto failed;
           fp_area = _Context_Fp_start(   fp_area,   0  );
           }
           the_thread->fp_context = fp_area;
           the_thread->Start.fp_context = fp_area;
           #endif
          
           /*
           * Initialize the thread timer
           */
           _Watchdog_Initialize(   &the_thread->Timer,   NULL,   0,   NULL  );
          
           #ifdef __RTEMS_STRICT_ORDER_MUTEX__
           /* Initialize the head of chain of held mutexes */
           _Chain_Initialize_empty(  &the_thread->lock_mutex );
           #endif
          
           /*
           * Allocate the extensions area for this thread
           */
           if (   _Thread_Maximum_extensions  ) {
           extensions_area = _Workspace_Allocate(  
           (  _Thread_Maximum_extensions + 1 ) * sizeof(   void *  )
            );
           if (   !extensions_area  )
           goto failed;
           }
           the_thread->extensions = (  void ** ) extensions_area;
          
           /*
           * Clear the extensions area so extension users can determine
           * if they are linked to the thread. An extension user may
           * create the extension long after tasks have been created
           * so they cannot rely on the thread create user extension
           * call.
           */
           if (   the_thread->extensions  ) {
           for (   i = 0; i <= _Thread_Maximum_extensions ; i++  )
           the_thread->extensions[i] = NULL;
           }
          
           /*
           * General initialization
           */
          
           the_thread->Start.is_preemptible = is_preemptible;
           the_thread->Start.budget_algorithm = budget_algorithm;
           the_thread->Start.budget_callout = budget_callout;
          
           switch (   budget_algorithm  ) {
           case THREAD_CPU_BUDGET_ALGORITHM_NONE:
           case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
           break;
           #if defined(  RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE )
           case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
           the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
           break;
           #endif
           #if defined(  RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT )
           case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
           break;
           #endif
           }
          
           the_thread->Start.isr_level = isr_level;
          
           the_thread->current_state = STATES_DORMANT;
           the_thread->Wait.queue = NULL;
           the_thread->resource_count = 0;
           the_thread->real_priority = priority;
           the_thread->Start.initial_priority = priority;
           _Thread_Set_priority(   the_thread,   priority  );
          
           /*
           * Initialize the CPU usage statistics
           */
           #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
           _Timestamp_Set_to_zero(   &the_thread->cpu_time_used  );
           #else
           the_thread->cpu_time_used = 0;
           #endif
          
           /*
           * Open the object
           */
           _Objects_Open(   information,   &the_thread->Object,   name  );
          
           /*
           * We assume the Allocator Mutex is locked and dispatching is
           * enabled when we get here. We want to be able to run the
           * user extensions with dispatching enabled. The Allocator
           * Mutex provides sufficient protection to let the user extensions
           * run safely.
           */
           extension_status = _User_extensions_Thread_create(   the_thread  );
           if (   extension_status  )
           return true;
          
          failed:
           if (   the_thread->libc_reent  )
           _Workspace_Free(   the_thread->libc_reent  );
          
           for (   i=0 ; i <= THREAD_API_LAST ; i++  )
           if (   the_thread->API_Extensions[i]  )
           _Workspace_Free(   the_thread->API_Extensions[i]  );
          
           if (   extensions_area  )
           (  void ) _Workspace_Free(   extensions_area  );
          
           #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
           if (   fp_area  )
           (  void ) _Workspace_Free(   fp_area  );
           #endif
          
           _Thread_Stack_Free(   the_thread  );
           return false;
          
          
          }

score/src/threadloadenv.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadloadenv.c,  v 1.8 2010/06/29 00:34:12 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Load_environment
           *
           * Load starting environment for another thread from its start area in the
           * thread. Only called from t_restart and t_start.
           *
           * Input parameters:
           * the_thread - thread control block pointer
           *
           * Output parameters: NONE
           */
          
      46  void _Thread_Load_environment(  
           Thread_Control *the_thread
           )
          {
           bool is_fp;
          
          #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
           if (   the_thread->Start.fp_context  ) {
           the_thread->fp_context = the_thread->Start.fp_context;
           _Context_Initialize_fp(   &the_thread->fp_context  );
           is_fp = true;
           } else
          #endif
           is_fp = false;
          
           the_thread->is_preemptible = the_thread->Start.is_preemptible;
           the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
           the_thread->budget_callout = the_thread->Start.budget_callout;
          
           _Context_Initialize(  
           &the_thread->Registers,  
           the_thread->Start.Initial_stack.area,  
           the_thread->Start.Initial_stack.size,  
           the_thread->Start.isr_level,  
           _Thread_Handler,  
           is_fp
            );
          
          }

score/src/threadmp.c

       1  /*
           * Multiprocessing Support for the Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2006.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadmp.c,  v 1.19 2008/12/22 05:52:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/mpci.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/isr.h>
          
          /*PAGE
           *
           * _Thread_MP_Handler_initialization
           *
           */
          
      32  void _Thread_MP_Handler_initialization (  
           uint32_t maximum_proxies
           )
          {
          
           _Chain_Initialize_empty(   &_Thread_MP_Active_proxies  );
          
           if (   maximum_proxies == 0  ) {
           _Chain_Initialize_empty(   &_Thread_MP_Inactive_proxies  );
           return;
           }
          
          
           _Chain_Initialize(  
           &_Thread_MP_Inactive_proxies,  
           _Workspace_Allocate_or_fatal_error(  
           maximum_proxies * sizeof(   Thread_Proxy_control  )
            ),  
           maximum_proxies,  
           sizeof(   Thread_Proxy_control  )
            );
          
          }
          
          /*PAGE
           *
           * _Thread_MP_Allocate_proxy
           *
           */
          
      62  Thread_Control *_Thread_MP_Allocate_proxy (  
           States_Control the_state
           )
          {
           Thread_Control *the_thread;
           Thread_Proxy_control *the_proxy;
          
           the_thread = (  Thread_Control * )_Chain_Get(   &_Thread_MP_Inactive_proxies  );
          
           if (   !_Thread_Is_null(   the_thread  )  ) {
          
           the_proxy = (  Thread_Proxy_control * ) the_thread;
          
           _Thread_Executing->Wait.return_code = THREAD_STATUS_PROXY_BLOCKING;
          
           the_proxy->receive_packet = _MPCI_Receive_server_tcb->receive_packet;
          
           the_proxy->Object.id = _MPCI_Receive_server_tcb->receive_packet->source_tid;
          
           the_proxy->current_priority =
           _MPCI_Receive_server_tcb->receive_packet->source_priority;
          
           the_proxy->current_state = _States_Set(   STATES_DORMANT,   the_state  );
          
           the_proxy->Wait = _Thread_Executing->Wait;
          
           _Chain_Append(   &_Thread_MP_Active_proxies,   &the_proxy->Active  );
          
           return the_thread;
           }
          
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_OUT_OF_PROXIES
            );
          
           /*
           * NOTE: The following return ensures that the compiler will
           * think that all paths return a value.
           */
          
           return NULL;
          }
          
          /*PAGE
           *
           * _Thread_MP_Find_proxy
           *
           */
          
          /*
           * The following macro provides the offset of the Active element
           * in the Thread_Proxy_control structure. This is the logical
           * equivalent of the POSITION attribute in Ada.
           */
          
          #define _Thread_MP_Proxy_Active_offset \
           (  (  uint32_t )&(  (  (  Thread_Proxy_control * )0 ) )->Active )
     121  
          Thread_Control *_Thread_MP_Find_proxy (  
           Objects_Id the_id
           )
          {
          
           Chain_Node *proxy_node;
           Thread_Control *the_thread;
           ISR_Level level;
          
          restart:
          
           _ISR_Disable(   level  );
          
           for (   proxy_node = _Thread_MP_Active_proxies.first;
           !_Chain_Is_tail(   &_Thread_MP_Active_proxies,   proxy_node  ) ;
            ) {
          
           the_thread = (  Thread_Control * ) _Addresses_Subtract_offset(  
           proxy_node,  
           _Thread_MP_Proxy_Active_offset
            );
          
           if (   _Objects_Are_ids_equal(   the_thread->Object.id,   the_id  )  ) {
           _ISR_Enable(   level  );
           return the_thread;
           }
          
           _ISR_Flash(   level  );
          
           proxy_node = proxy_node->next;
          
           /*
           * A proxy which is only dormant is not in a blocking state.
           * Therefore,   we are looking at proxy which has been moved from
           * active to inactive chain (  by an ISR ) and need to restart
           * the search.
           */
          
           if (   _States_Is_only_dormant(   the_thread->current_state  )  ) {
           _ISR_Enable(   level  );
           goto restart;
           }
           }
          
           _ISR_Enable(   level  );
           return NULL;
          }

score/src/threadq.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadq.c,  v 1.25 2008/01/22 18:28:53 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Initialize
           *
           * This routine initializes the specified threadq.
           *
           * Input parameters:
           * the_thread_queue - pointer to a threadq header
           * discipline - queueing discipline
           * state - state of waiting threads
           * timeout_status - return on a timeout
           *
           * Output parameters: NONE
           */
          
      43  void _Thread_queue_Initialize(  
           Thread_queue_Control *the_thread_queue,  
           Thread_queue_Disciplines the_discipline,  
           States_Control state,  
           uint32_t timeout_status
           )
          {
           the_thread_queue->state = state;
           the_thread_queue->discipline = the_discipline;
           the_thread_queue->timeout_status = timeout_status;
           the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
          
           if (   the_discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY  ) {
           uint32_t index;
          
           for(   index=0 ;
           index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
           index++ )
           _Chain_Initialize_empty(   &the_thread_queue->Queues.Priority[index]  );
           } else { /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
           _Chain_Initialize_empty(   &the_thread_queue->Queues.Fifo  );
           }
          
          }

score/src/threadqdequeue.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqdequeue.c,  v 1.7 2008/01/22 21:19:18 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Dequeue
           *
           * This routine removes a thread from the specified threadq. If the
           * threadq discipline is FIFO,   it unblocks a thread,   and cancels its
           * timeout timer. Priority discipline is processed elsewhere.
           *
           * Input parameters:
           * the_thread_queue - pointer to threadq
           *
           * Output parameters:
           * returns - thread dequeued or NULL
           *
           * INTERRUPT LATENCY:
           * check sync
           */
          
      46  Thread_Control *_Thread_queue_Dequeue(  
           Thread_queue_Control *the_thread_queue
           )
          {
           Thread_Control *(  *dequeue_p )(   Thread_queue_Control *  );
           Thread_Control *the_thread;
           ISR_Level level;
           Thread_blocking_operation_States sync_state;
          
           if (   the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY  )
           dequeue_p = _Thread_queue_Dequeue_priority;
           else /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
           dequeue_p = _Thread_queue_Dequeue_fifo;
          
           the_thread = (  *dequeue_p )(   the_thread_queue  );
           _ISR_Disable(   level  );
           if (   !the_thread  ) {
           sync_state = the_thread_queue->sync_state;
           if (   (  sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT ) ||
           (  sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )  ) {
           the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SATISFIED;
           the_thread = _Thread_Executing;
           }
           }
           _ISR_Enable(   level  );
           return the_thread;
          }

score/src/threadqdequeuefifo.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqdequeuefifo.c,  v 1.9 2008/01/22 21:19:18 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Dequeue_fifo
           *
           * This routine removes a thread from the specified threadq.
           *
           * Input parameters:
           * the_thread_queue - pointer to threadq
           *
           * Output parameters:
           * returns - thread dequeued or NULL
           *
           * INTERRUPT LATENCY:
           * check sync
           * FIFO
           */
          
      45  Thread_Control *_Thread_queue_Dequeue_fifo(  
           Thread_queue_Control *the_thread_queue
           )
          {
           ISR_Level level;
           Thread_Control *the_thread;
          
           _ISR_Disable(   level  );
           if (   !_Chain_Is_empty(   &the_thread_queue->Queues.Fifo  )  ) {
          
           the_thread = (  Thread_Control * )
           _Chain_Get_first_unprotected(   &the_thread_queue->Queues.Fifo  );
          
           the_thread->Wait.queue = NULL;
           if (   !_Watchdog_Is_active(   &the_thread->Timer  )  ) {
           _ISR_Enable(   level  );
           _Thread_Unblock(   the_thread  );
           } else {
           _Watchdog_Deactivate(   &the_thread->Timer  );
           _ISR_Enable(   level  );
           (  void ) _Watchdog_Remove(   &the_thread->Timer  );
           _Thread_Unblock(   the_thread  );
           }
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   !_Objects_Is_local_id(   the_thread->Object.id  )  )
           _Thread_MP_Free_proxy(   the_thread  );
          #endif
          
           return the_thread;
           }
          
           _ISR_Enable(   level  );
           return NULL;
          }

score/src/threadqdequeuepriority.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqdequeuepriority.c,  v 1.9 2008/01/22 21:19:18 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Dequeue_priority
           *
           * This routine removes a thread from the specified PRIORITY based
           * threadq,   unblocks it,   and cancels its timeout timer.
           *
           * Input parameters:
           * the_thread_queue - pointer to thread queue
           *
           * Output parameters:
           * returns - thread dequeued or NULL
           *
           * INTERRUPT LATENCY:
           * only case
           */
          
      45  Thread_Control *_Thread_queue_Dequeue_priority(  
           Thread_queue_Control *the_thread_queue
           )
          {
           uint32_t index;
           ISR_Level level;
           Thread_Control *the_thread = NULL; /* just to remove warnings */
           Thread_Control *new_first_thread;
           Chain_Node *new_first_node;
           Chain_Node *new_second_node;
           Chain_Node *last_node;
           Chain_Node *next_node;
           Chain_Node *previous_node;
          
           _ISR_Disable(   level  );
           for(   index=0 ;
           index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
           index++  ) {
           if (   !_Chain_Is_empty(   &the_thread_queue->Queues.Priority[ index ]  )  ) {
           the_thread = (  Thread_Control * )
           the_thread_queue->Queues.Priority[ index ].first;
           goto dequeue;
           }
           }
          
           /*
           * We did not find a thread to unblock.
           */
           _ISR_Enable(   level  );
           return NULL;
          
          dequeue:
           the_thread->Wait.queue = NULL;
           new_first_node = the_thread->Wait.Block2n.first;
           new_first_thread = (  Thread_Control * ) new_first_node;
           next_node = the_thread->Object.Node.next;
           previous_node = the_thread->Object.Node.previous;
          
           if (   !_Chain_Is_empty(   &the_thread->Wait.Block2n  )  ) {
           last_node = the_thread->Wait.Block2n.last;
           new_second_node = new_first_node->next;
          
           previous_node->next = new_first_node;
           next_node->previous = new_first_node;
           new_first_node->next = next_node;
           new_first_node->previous = previous_node;
          
           if (   !_Chain_Has_only_one_node(   &the_thread->Wait.Block2n  )  ) {
           /* > two threads on 2-n */
           new_second_node->previous =
           _Chain_Head(   &new_first_thread->Wait.Block2n  );
          
           new_first_thread->Wait.Block2n.first = new_second_node;
           new_first_thread->Wait.Block2n.last = last_node;
          
           last_node->next = _Chain_Tail(   &new_first_thread->Wait.Block2n  );
           }
           } else {
           previous_node->next = next_node;
           next_node->previous = previous_node;
           }
          
           if (   !_Watchdog_Is_active(   &the_thread->Timer  )  ) {
           _ISR_Enable(   level  );
           _Thread_Unblock(   the_thread  );
           } else {
           _Watchdog_Deactivate(   &the_thread->Timer  );
           _ISR_Enable(   level  );
           (  void ) _Watchdog_Remove(   &the_thread->Timer  );
           _Thread_Unblock(   the_thread  );
           }
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   !_Objects_Is_local_id(   the_thread->Object.id  )  )
           _Thread_MP_Free_proxy(   the_thread  );
          #endif
           return(   the_thread  );
          }

score/src/threadqenqueue.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqenqueue.c,  v 1.12 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Enqueue_with_handler
           *
           * This routine blocks a thread,   places it on a thread,   and optionally
           * starts a timeout timer.
           *
           * Input parameters:
           * the_thread_queue - pointer to threadq
           * timeout - interval to wait
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * only case
           */
          
      45  void _Thread_queue_Enqueue_with_handler(  
           Thread_queue_Control *the_thread_queue,  
           Watchdog_Interval timeout,  
           Thread_queue_Timeout_callout handler
           )
          {
           Thread_Control *the_thread;
           ISR_Level level;
           Thread_blocking_operation_States sync_state;
           Thread_blocking_operation_States (  *enqueue_p )(  
           Thread_queue_Control *,  
           Thread_Control *,  
           ISR_Level *
            );
          
           the_thread = _Thread_Executing;
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   _Thread_MP_Is_receive(   the_thread  ) && the_thread->receive_packet  )
           the_thread = _Thread_MP_Allocate_proxy(   the_thread_queue->state  );
           else
          #endif
           /*
           * Set the blocking state for this thread queue in the thread.
           */
           _Thread_Set_state(   the_thread,   the_thread_queue->state  );
          
           /*
           * If the thread wants to timeout,   then schedule its timer.
           */
           if (   timeout  ) {
           _Watchdog_Initialize(  
           &the_thread->Timer,  
           handler,  
           the_thread->Object.id,  
           NULL
            );
          
           _Watchdog_Insert_ticks(   &the_thread->Timer,   timeout  );
           }
          
           /*
           * Now enqueue the thread per the discipline for this thread queue.
           */
           if (   the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY  )
           enqueue_p = _Thread_queue_Enqueue_priority;
           else /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
           enqueue_p = _Thread_queue_Enqueue_fifo;
          
           sync_state = (  *enqueue_p )(   the_thread_queue,   the_thread,   &level  );
           if (   sync_state != THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED  )
           _Thread_blocking_operation_Cancel(   sync_state,   the_thread,   level  );
          }

score/src/threadqenqueuefifo.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqenqueuefifo.c,  v 1.10 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Enqueue_fifo
           *
           * This routine places a blocked thread on a FIFO thread queue.
           *
           * Input parameters:
           * the_thread_queue - pointer to threadq
           * the_thread - pointer to the thread to block
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * only case
           */
          
      44  Thread_blocking_operation_States _Thread_queue_Enqueue_fifo (  
           Thread_queue_Control *the_thread_queue,  
           Thread_Control *the_thread,  
           ISR_Level *level_p
           )
          {
           Thread_blocking_operation_States sync_state;
           ISR_Level level;
          
           _ISR_Disable(   level  );
          
           sync_state = the_thread_queue->sync_state;
           the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
           if (  sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
           _Chain_Append_unprotected(  
           &the_thread_queue->Queues.Fifo,  
           &the_thread->Object.Node
            );
           the_thread->Wait.queue = the_thread_queue;
          
           the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
           _ISR_Enable(   level  );
           return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
           }
          
           /*
           * An interrupt completed the thread's blocking request.
           * For example,   the blocking thread could have been given
           * the mutex by an ISR or timed out.
           *
           * WARNING! Returning with interrupts disabled!
           */
           *level_p = level;
           return sync_state;
          }

score/src/threadqenqueuepriority.c

       1  /*
           * Thread Queue Handler - Enqueue By Priority
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqenqueuepriority.c,  v 1.11 2009/07/10 20:32:48 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*
           * Support the user forcing the unrolling to be disabled.
           */
          #if __RTEMS_DO_NOT_UNROLL_THREADQ_ENQUEUE_PRIORITY__
           #undef CPU_UNROLL_ENQUEUE_PRIORITY
           #define CPU_UNROLL_ENQUEUE_PRIORITY FALSE
          #endif
          
          /*PAGE
           *
           * _Thread_queue_Enqueue_priority
           *
           * This routine places a blocked thread on a priority thread queue.
           *
           * Input parameters:
           * the_thread_queue - pointer to threadq
           * thread - thread to insert
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * forward less than
           * forward equal
           */
          
      52  Thread_blocking_operation_States _Thread_queue_Enqueue_priority (  
           Thread_queue_Control *the_thread_queue,  
           Thread_Control *the_thread,  
           ISR_Level *level_p
           )
          {
           Priority_Control search_priority;
           Thread_Control *search_thread;
           ISR_Level level;
           Chain_Control *header;
           uint32_t header_index;
           Chain_Node *the_node;
           Chain_Node *next_node;
           Chain_Node *previous_node;
           Chain_Node *search_node;
           Priority_Control priority;
           States_Control block_state;
          
           _Chain_Initialize_empty(   &the_thread->Wait.Block2n  );
          
           priority = the_thread->current_priority;
           header_index = _Thread_queue_Header_number(   priority  );
           header = &the_thread_queue->Queues.Priority[ header_index ];
           block_state = the_thread_queue->state;
          
           if (   _Thread_queue_Is_reverse_search(   priority  )  )
           goto restart_reverse_search;
          
          restart_forward_search:
           search_priority = PRIORITY_MINIMUM - 1;
           _ISR_Disable(   level  );
           search_thread = (  Thread_Control * ) header->first;
           while (   !_Chain_Is_tail(   header,   (  Chain_Node * )search_thread  )  ) {
           search_priority = search_thread->current_priority;
           if (   priority <= search_priority  )
           break;
          
          #if (   CPU_UNROLL_ENQUEUE_PRIORITY == TRUE  )
           search_thread = (  Thread_Control * ) search_thread->Object.Node.next;
           if (   _Chain_Is_tail(   header,   (  Chain_Node * )search_thread  )  )
           break;
           search_priority = search_thread->current_priority;
           if (   priority <= search_priority  )
           break;
          #endif
           _ISR_Flash(   level  );
           if (   !_States_Are_set(   search_thread->current_state,   block_state )  ) {
           _ISR_Enable(   level  );
           goto restart_forward_search;
           }
           search_thread =
           (  Thread_Control * )search_thread->Object.Node.next;
           }
          
           if (   the_thread_queue->sync_state !=
           THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED  )
           goto synchronize;
          
           the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
          
           if (   priority == search_priority  )
           goto equal_priority;
          
           search_node = (  Chain_Node * ) search_thread;
           previous_node = search_node->previous;
           the_node = (  Chain_Node * ) the_thread;
          
           the_node->next = search_node;
           the_node->previous = previous_node;
           previous_node->next = the_node;
           search_node->previous = the_node;
           the_thread->Wait.queue = the_thread_queue;
           _ISR_Enable(   level  );
           return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
          
          restart_reverse_search:
           search_priority = PRIORITY_MAXIMUM + 1;
          
           _ISR_Disable(   level  );
           search_thread = (  Thread_Control * ) header->last;
           while (   !_Chain_Is_head(   header,   (  Chain_Node * )search_thread  )  ) {
           search_priority = search_thread->current_priority;
           if (   priority >= search_priority  )
           break;
          #if (   CPU_UNROLL_ENQUEUE_PRIORITY == TRUE  )
           search_thread = (  Thread_Control * ) search_thread->Object.Node.previous;
           if (   _Chain_Is_head(   header,   (  Chain_Node * )search_thread  )  )
           break;
           search_priority = search_thread->current_priority;
           if (   priority >= search_priority  )
           break;
          #endif
           _ISR_Flash(   level  );
           if (   !_States_Are_set(   search_thread->current_state,   block_state )  ) {
           _ISR_Enable(   level  );
           goto restart_reverse_search;
           }
           search_thread = (  Thread_Control * )
           search_thread->Object.Node.previous;
           }
          
           if (   the_thread_queue->sync_state !=
           THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED  )
           goto synchronize;
          
           the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
          
           if (   priority == search_priority  )
           goto equal_priority;
          
           search_node = (  Chain_Node * ) search_thread;
           next_node = search_node->next;
           the_node = (  Chain_Node * ) the_thread;
          
           the_node->next = next_node;
           the_node->previous = search_node;
           search_node->next = the_node;
           next_node->previous = the_node;
           the_thread->Wait.queue = the_thread_queue;
           _ISR_Enable(   level  );
           return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
          
          equal_priority: /* add at end of priority group */
           search_node = _Chain_Tail(   &search_thread->Wait.Block2n  );
           previous_node = search_node->previous;
           the_node = (  Chain_Node * ) the_thread;
          
           the_node->next = search_node;
           the_node->previous = previous_node;
           previous_node->next = the_node;
           search_node->previous = the_node;
           the_thread->Wait.queue = the_thread_queue;
           _ISR_Enable(   level  );
           return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
          
          synchronize:
           /*
           * An interrupt completed the thread's blocking request.
           * For example,   the blocking thread could have been given
           * the mutex by an ISR or timed out.
           *
           * WARNING! Returning with interrupts disabled!
           */
           *level_p = level;
           return the_thread_queue->sync_state;
          }

score/src/threadqextract.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqextract.c,  v 1.7 2008/01/23 13:07:13 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Extract
           *
           * This routine removes a specific thread from the specified threadq,  
           * deletes any timeout,   and unblocks the thread.
           *
           * Input parameters:
           * the_thread_queue - pointer to a threadq header
           * the_thread - pointer to a thread control block
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY: NONE
           */
          
      44  void _Thread_queue_Extract(  
           Thread_queue_Control *the_thread_queue,  
           Thread_Control *the_thread
           )
          {
           /*
           * Can not use indirect function pointer here since Extract priority
           * is a macro and the underlying methods do not have the same signature.
           */
           if (   the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY  )
           _Thread_queue_Extract_priority(   the_thread_queue,   the_thread  );
           else /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
           _Thread_queue_Extract_fifo(   the_thread_queue,   the_thread  );
          
          }

score/src/threadqextractfifo.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqextractfifo.c,  v 1.9 2008/12/31 03:36:04 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Extract_fifo
           *
           * This routine removes a specific thread from the specified threadq,  
           * deletes any timeout,   and unblocks the thread.
           *
           * Input parameters:
           * the_thread_queue - pointer to a threadq header
           * the_thread - pointer to the thread to block
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * EXTRACT_FIFO
           */
          
      45  void _Thread_queue_Extract_fifo(  
           Thread_queue_Control *the_thread_queue __attribute__(  (  unused ) ),  
           Thread_Control *the_thread
           )
          {
           ISR_Level level;
          
           _ISR_Disable(   level  );
          
           if (   !_States_Is_waiting_on_thread_queue(   the_thread->current_state  )  ) {
           _ISR_Enable(   level  );
           return;
           }
          
           _Chain_Extract_unprotected(   &the_thread->Object.Node  );
          
           the_thread->Wait.queue = NULL;
          
           if (   !_Watchdog_Is_active(   &the_thread->Timer  )  ) {
           _ISR_Enable(   level  );
           } else {
           _Watchdog_Deactivate(   &the_thread->Timer  );
           _ISR_Enable(   level  );
           (  void ) _Watchdog_Remove(   &the_thread->Timer  );
           }
          
           _Thread_Unblock(   the_thread  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   !_Objects_Is_local_id(   the_thread->Object.id  )  )
           _Thread_MP_Free_proxy(   the_thread  );
          #endif
          
          }

score/src/threadqextractpriority.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqextractpriority.c,  v 1.10 2008/12/31 03:36:04 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Extract_priority
           *
           * This routine removes a specific thread from the specified threadq,  
           * deletes any timeout,   and unblocks the thread.
           *
           * Input parameters:
           * the_thread_queue - pointer to a threadq header
           * the_thread - pointer to a thread control block
           * requeuing - true if requeuing and should not alter timeout or state
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * EXTRACT_PRIORITY
           */
          
      46  void _Thread_queue_Extract_priority_helper(  
           Thread_queue_Control *the_thread_queue __attribute__(  (  unused ) ),  
           Thread_Control *the_thread,  
           bool requeuing
           )
          {
           ISR_Level level;
           Chain_Node *the_node;
           Chain_Node *next_node;
           Chain_Node *previous_node;
           Thread_Control *new_first_thread;
           Chain_Node *new_first_node;
           Chain_Node *new_second_node;
           Chain_Node *last_node;
          
           the_node = (  Chain_Node * ) the_thread;
           _ISR_Disable(   level  );
           if (   !_States_Is_waiting_on_thread_queue(   the_thread->current_state  )  ) {
           _ISR_Enable(   level  );
           return;
           }
          
           /*
           * The thread was actually waiting on a thread queue so let's remove it.
           */
          
           next_node = the_node->next;
           previous_node = the_node->previous;
          
           if (   !_Chain_Is_empty(   &the_thread->Wait.Block2n  )  ) {
           new_first_node = the_thread->Wait.Block2n.first;
           new_first_thread = (  Thread_Control * ) new_first_node;
           last_node = the_thread->Wait.Block2n.last;
           new_second_node = new_first_node->next;
          
           previous_node->next = new_first_node;
           next_node->previous = new_first_node;
           new_first_node->next = next_node;
           new_first_node->previous = previous_node;
          
           if (   !_Chain_Has_only_one_node(   &the_thread->Wait.Block2n  )  ) {
           /* > two threads on 2-n */
           new_second_node->previous =
           _Chain_Head(   &new_first_thread->Wait.Block2n  );
           new_first_thread->Wait.Block2n.first = new_second_node;
          
           new_first_thread->Wait.Block2n.last = last_node;
           last_node->next = _Chain_Tail(   &new_first_thread->Wait.Block2n  );
           }
           } else {
           previous_node->next = next_node;
           next_node->previous = previous_node;
           }
          
           /*
           * If we are not supposed to touch timers or the thread's state,   return.
           */
          
           if (   requeuing  ) {
           _ISR_Enable(   level  );
           return;
           }
          
           if (   !_Watchdog_Is_active(   &the_thread->Timer  )  ) {
           _ISR_Enable(   level  );
           } else {
           _Watchdog_Deactivate(   &the_thread->Timer  );
           _ISR_Enable(   level  );
           (  void ) _Watchdog_Remove(   &the_thread->Timer  );
           }
           _Thread_Unblock(   the_thread  );
          
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   !_Objects_Is_local_id(   the_thread->Object.id  )  )
           _Thread_MP_Free_proxy(   the_thread  );
          #endif
          }

score/src/threadqextractwithproxy.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqextractwithproxy.c,  v 1.13 2008/12/22 05:52:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Extract_with_proxy
           *
           * This routine extracts the_thread from the_thread_queue
           * and ensures that if there is a proxy for this task on
           * another node,   it is also dealt with.
           *
           * XXX
           */
          
      39  bool _Thread_queue_Extract_with_proxy(  
           Thread_Control *the_thread
           )
          {
           States_Control state;
          
           state = the_thread->current_state;
          
           if (   _States_Is_waiting_on_thread_queue(   state  )  ) {
           #if defined(  RTEMS_MULTIPROCESSING )
           if (   _States_Is_waiting_for_rpc_reply(   state  ) &&
           _States_Is_locally_blocked(   state  )  ) {
           Objects_Information *the_information;
           Objects_Thread_queue_Extract_callout proxy_extract_callout;
          
           the_information = _Objects_Get_information_id(   the_thread->Wait.id  );
           proxy_extract_callout =
           (  Objects_Thread_queue_Extract_callout ) the_information->extract;
          
           if (   proxy_extract_callout  )
           (  *proxy_extract_callout )(   the_thread  );
           }
           #endif
           _Thread_queue_Extract(   the_thread->Wait.queue,   the_thread  );
          
           return true;
           }
           return false;
          }

score/src/threadqfirst.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqfirst.c,  v 1.7 2008/01/22 19:10:04 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_First
           *
           * This routines returns a pointer to the first thread on the
           * specified threadq.
           *
           * Input parameters:
           * the_thread_queue - pointer to thread queue
           *
           * Output parameters:
           * returns - first thread or NULL
           */
          
      42  Thread_Control *_Thread_queue_First(  
           Thread_queue_Control *the_thread_queue
           )
          {
           Thread_Control * (  *first_p )(  Thread_queue_Control * );
          
           if (   the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY  )
           first_p = _Thread_queue_First_priority;
           else /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
           first_p = _Thread_queue_First_fifo;
          
           return (  *first_p )(   the_thread_queue  );
          }

score/src/threadqfirstfifo.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqfirstfifo.c,  v 1.6 2008/01/22 18:28:53 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_First_fifo
           *
           * This routines returns a pointer to the first thread on the
           * specified threadq.
           *
           * Input parameters:
           * the_thread_queue - pointer to threadq
           *
           * Output parameters:
           * returns - first thread or NULL
           */
          
      42  Thread_Control *_Thread_queue_First_fifo(  
           Thread_queue_Control *the_thread_queue
           )
          {
           if (   !_Chain_Is_empty(   &the_thread_queue->Queues.Fifo  )  )
           return (  Thread_Control * ) the_thread_queue->Queues.Fifo.first;
          
           return NULL;
          }

score/src/threadqfirstpriority.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqfirstpriority.c,  v 1.6 2008/01/22 18:28:53 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_First_priority
           *
           * This routines returns a pointer to the first thread on the
           * specified threadq.
           *
           * Input parameters:
           * the_thread_queue - pointer to thread queue
           *
           * Output parameters:
           * returns - first thread or NULL
           */
          
      42  Thread_Control *_Thread_queue_First_priority (  
           Thread_queue_Control *the_thread_queue
           )
          {
           uint32_t index;
          
           for(   index=0 ;
           index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
           index++  ) {
           if (   !_Chain_Is_empty(   &the_thread_queue->Queues.Priority[ index ]  )  )
           return (  Thread_Control * )
           the_thread_queue->Queues.Priority[ index ].first;
           }
           return NULL;
          }

score/src/threadqflush.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqflush.c,  v 1.8 2008/12/31 03:36:04 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Flush
           *
           * This kernel routine flushes the given thread queue.
           *
           * Input parameters:
           * the_thread_queue - pointer to threadq to be flushed
           * remote_extract_callout - pointer to routine which extracts a remote thread
           * status - status to return to the thread
           *
           * Output parameters: NONE
           */
          
      42  void _Thread_queue_Flush(  
           Thread_queue_Control *the_thread_queue,  
          #if defined(  RTEMS_MULTIPROCESSING )
           Thread_queue_Flush_callout remote_extract_callout,  
          #else
           Thread_queue_Flush_callout remote_extract_callout __attribute__(  (  unused ) ),  
          #endif
           uint32_t status
           )
          {
           Thread_Control *the_thread;
          
           while (   (  the_thread = _Thread_queue_Dequeue(   the_thread_queue  ) )  ) {
          #if defined(  RTEMS_MULTIPROCESSING )
           if (   !_Objects_Is_local_id(   the_thread->Object.id  )  )
           (   *remote_extract_callout  )(   the_thread  );
           else
          #endif
           the_thread->Wait.return_code = status;
           }
          }

score/src/threadqprocesstimeout.c

       1  /*
           * Thread Queue Handler - Process Timeout Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqprocesstimeout.c,  v 1.1 2008/01/30 14:56:57 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
      28  void _Thread_queue_Process_timeout(  
           Thread_Control *the_thread
           )
          {
           Thread_queue_Control *the_thread_queue = the_thread->Wait.queue;
          
           /*
           * If the_thread_queue is not synchronized,   then it is either
           * "nothing happened",   "timeout",   or "satisfied". If the_thread
           * is the executing thread,   then it is in the process of blocking
           * and it is the thread which is responsible for the synchronization
           * process.
           *
           * If it is not satisfied,   then it is "nothing happened" and
           * this is the "timeout" transition. After a request is satisfied,  
           * a timeout is not allowed to occur.
           */
          
           if (   the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_SYNCHRONIZED &&
           _Thread_Is_executing(   the_thread  )  ) {
           if (   the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_SATISFIED  ) {
           the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
           the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT;
           }
           } else {
           the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
           _Thread_queue_Extract(   the_thread->Wait.queue,   the_thread  );
           }
          }
          

score/src/threadqrequeue.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqrequeue.c,  v 1.6 2008/12/22 05:52:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*PAGE
           *
           * _Thread_queue_Requeue
           *
           * This routine is invoked when a thread changes priority and should be
           * moved to a different position on the thread queue.
           *
           * Input parameters:
           * the_thread_queue - pointer to a threadq header
           * the_thread - pointer to a thread control block
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY: NONE
           */
          
      44  void _Thread_queue_Requeue(  
           Thread_queue_Control *the_thread_queue,  
           Thread_Control *the_thread
           )
          {
           /*
           * Just in case the thread really wasn't blocked on a thread queue
           * when we get here.
           */
           if (   !the_thread_queue  )
           return;
          
           /*
           * If queueing by FIFO,   there is nothing to do. This only applies to
           * priority blocking discipline.
           */
           if (   the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY  ) {
           Thread_queue_Control *tq = the_thread_queue;
           ISR_Level level;
           ISR_Level level_ignored;
          
           _ISR_Disable(   level  );
           if (   _States_Is_waiting_on_thread_queue(   the_thread->current_state  )  ) {
           _Thread_queue_Enter_critical_section(   tq  );
           _Thread_queue_Extract_priority_helper(   tq,   the_thread,   true  );
           (  void ) _Thread_queue_Enqueue_priority(   tq,   the_thread,   &level_ignored  );
           }
           _ISR_Enable(   level  );
           }
          }
          

score/src/threadqtimeout.c

       1  /*
           * Thread Queue Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: threadqtimeout.c,  v 1.9 2008/12/31 03:36:04 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/chain.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/states.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/tqdata.h>
          
          /*
           * _Thread_queue_Timeout
           *
           * This routine processes a thread which timeouts while waiting on
           * a thread queue. It is called by the watchdog handler.
           *
           * Input parameters:
           * id - thread id
           *
           * Output parameters: NONE
           */
          
      40  void _Thread_queue_Timeout(  
           Objects_Id id,  
           void *ignored __attribute__(  (  unused ) )
           )
          {
           Thread_Control *the_thread;
           Objects_Locations location;
          
           the_thread = _Thread_Get(   id,   &location  );
           switch (   location  ) {
           case OBJECTS_ERROR:
          #if defined(  RTEMS_MULTIPROCESSING )
           case OBJECTS_REMOTE: /* impossible */
          #endif
           break;
           case OBJECTS_LOCAL:
           _Thread_queue_Process_timeout(   the_thread  );
           _Thread_Unnest_dispatch(   );
           break;
           }
          }

score/src/threadready.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2006.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadready.c,  v 1.9 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Ready
           *
           * This kernel routine readies the requested thread,   the thread chain
           * is adjusted. A new heir thread may be selected.
           *
           * Input parameters:
           * the_thread - pointer to thread control block
           *
           * Output parameters: NONE
           *
           * NOTE: This routine uses the "blocking" heir selection mechanism.
           * This ensures the correct heir after a thread restart.
           *
           * INTERRUPT LATENCY:
           * ready chain
           * select heir
           */
          
      53  void _Thread_Ready(  
           Thread_Control *the_thread
           )
          {
           ISR_Level level;
           Thread_Control *heir;
          
           _ISR_Disable(   level  );
          
           the_thread->current_state = STATES_READY;
          
           _Priority_bit_map_Add(   &the_thread->Priority_map  );
          
           _Chain_Append_unprotected(   the_thread->ready,   &the_thread->Object.Node  );
          
           _ISR_Flash(   level  );
          
           _Thread_Calculate_heir(   );
          
           heir = _Thread_Heir;
          
           if (   !_Thread_Is_executing(   heir  ) && _Thread_Executing->is_preemptible  )
           _Thread_Dispatch_necessary = true;
          
           _ISR_Enable(   level  );
          }

score/src/threadreset.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadreset.c,  v 1.10 2010/06/18 02:56:26 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*
           * _Thread_Reset
           *
           * DESCRIPTION:
           *
           * This routine resets a thread to its initial stat but does
           * not actually restart it. Some APIs do this in separate
           * operations and this division helps support this.
           */
          
      43  void _Thread_Reset(  
           Thread_Control *the_thread,  
           void *pointer_argument,  
           Thread_Entry_numeric_type numeric_argument
           )
          {
           the_thread->resource_count = 0;
           the_thread->is_preemptible = the_thread->Start.is_preemptible;
           the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
           the_thread->budget_callout = the_thread->Start.budget_callout;
          
           the_thread->Start.pointer_argument = pointer_argument;
           the_thread->Start.numeric_argument = numeric_argument;
          
           if (   !_Thread_queue_Extract_with_proxy(   the_thread  )  ) {
          
           if (   _Watchdog_Is_active(   &the_thread->Timer  )  )
           (  void ) _Watchdog_Remove(   &the_thread->Timer  );
           }
          
           if (   the_thread->current_priority != the_thread->Start.initial_priority  ) {
           the_thread->real_priority = the_thread->Start.initial_priority;
           _Thread_Set_priority(   the_thread,   the_thread->Start.initial_priority  );
           }
          }

score/src/threadrestart.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadrestart.c,  v 1.11 2008/12/22 05:52:32 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*
           * _Thread_Restart
           *
           * DESCRIPTION:
           *
           * This support routine restarts the specified task in a way that the
           * next time this thread executes,   it will begin execution at its
           * original starting point.
           */
          
      43  bool _Thread_Restart(  
           Thread_Control *the_thread,  
           void *pointer_argument,  
           Thread_Entry_numeric_type numeric_argument
           )
          {
           if (   !_States_Is_dormant(   the_thread->current_state  )  ) {
          
           _Thread_Set_transient(   the_thread  );
          
           _Thread_Reset(   the_thread,   pointer_argument,   numeric_argument  );
          
           _Thread_Load_environment(   the_thread  );
          
           _Thread_Ready(   the_thread  );
          
           _User_extensions_Thread_restart(   the_thread  );
          
           if (   _Thread_Is_executing (   the_thread  )  )
           _Thread_Restart_self(   );
          
           return true;
           }
          
           return false;
          }

score/src/threadresume.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadresume.c,  v 1.12 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Resume
           *
           * This kernel routine clears the SUSPEND state if the suspend_count
           * drops below one. If the force parameter is set the suspend_count
           * is forced back to zero. The thread ready chain is adjusted if
           * necessary and the Heir thread is set accordingly.
           *
           * Input parameters:
           * the_thread - pointer to thread control block
           * force - force the suspend count back to 0
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * priority map
           * select heir
           */
          
          
      54  void _Thread_Resume(  
           Thread_Control *the_thread,  
           bool force
           )
          {
          
           ISR_Level level;
           States_Control current_state;
          
           _ISR_Disable(   level  );
          
           current_state = the_thread->current_state;
           if (   current_state & STATES_SUSPENDED  ) {
           current_state =
           the_thread->current_state = _States_Clear(  STATES_SUSPENDED,   current_state );
          
           if (   _States_Is_ready(   current_state  )  ) {
          
           _Priority_bit_map_Add(   &the_thread->Priority_map  );
          
           _Chain_Append_unprotected(  the_thread->ready,   &the_thread->Object.Node );
          
           _ISR_Flash(   level  );
          
           if (   the_thread->current_priority < _Thread_Heir->current_priority  ) {
           _Thread_Heir = the_thread;
           if (   _Thread_Executing->is_preemptible ||
           the_thread->current_priority == 0  )
           _Thread_Dispatch_necessary = true;
           }
           }
           }
          
           _ISR_Enable(   level  );
          }

score/src/threadsetpriority.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadsetpriority.c,  v 1.5 2010/07/29 17:52:10 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Set_priority
           *
           * This directive enables and disables several modes of
           * execution for the requesting thread.
           *
           * Input parameters:
           * the_thread - pointer to thread priority
           * new_priority - new priority
           *
           * Output: NONE
           */
          
      47  void _Thread_Set_priority(  
           Thread_Control *the_thread,  
           Priority_Control new_priority
           )
          {
           the_thread->current_priority = new_priority;
           the_thread->ready = &_Thread_Ready_chain[ new_priority ];
          
           _Priority_bit_map_Initialize_information(  
           &the_thread->Priority_map,  
           new_priority
            );
          }

score/src/threadsetstate.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadsetstate.c,  v 1.8 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Set_state
           *
           * This kernel routine sets the requested state in the THREAD. The
           * THREAD chain is adjusted if necessary.
           *
           * Input parameters:
           * the_thread - pointer to thread control block
           * state - state to be set
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * ready chain
           * select map
           */
          
      51  void _Thread_Set_state(  
           Thread_Control *the_thread,  
           States_Control state
           )
          {
           ISR_Level level;
           Chain_Control *ready;
          
           ready = the_thread->ready;
           _ISR_Disable(   level  );
           if (   !_States_Is_ready(   the_thread->current_state  )  ) {
           the_thread->current_state =
           _States_Set(   state,   the_thread->current_state  );
           _ISR_Enable(   level  );
           return;
           }
          
           the_thread->current_state = state;
          
           if (   _Chain_Has_only_one_node(   ready  )  ) {
          
           _Chain_Initialize_empty(   ready  );
           _Priority_bit_map_Remove(   &the_thread->Priority_map  );
          
           } else
           _Chain_Extract_unprotected(   &the_thread->Object.Node  );
          
           _ISR_Flash(   level  );
          
           if (   _Thread_Is_heir(   the_thread  )  )
           _Thread_Calculate_heir(   );
          
           if (   _Thread_Is_executing(   the_thread  )  )
           _Thread_Dispatch_necessary = true;
          
           _ISR_Enable(   level  );
          }

score/src/threadsettransient.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadsettransient.c,  v 1.6 2010/07/29 17:52:10 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Set_transient
           *
           * This kernel routine places the requested thread in the transient state
           * which will remove it from the ready queue,   if necessary. No
           * rescheduling is necessary because it is assumed that the transient
           * state will be cleared before dispatching is enabled.
           *
           * Input parameters:
           * the_thread - pointer to thread control block
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * only case
           */
          
      51  void _Thread_Set_transient(  
           Thread_Control *the_thread
           )
          {
           ISR_Level level;
           uint32_t old_state;
           Chain_Control *ready;
          
           ready = the_thread->ready;
           _ISR_Disable(   level  );
          
           old_state = the_thread->current_state;
           the_thread->current_state = _States_Set(   STATES_TRANSIENT,   old_state  );
          
           if (   _States_Is_ready(   old_state  )  ) {
           if (   _Chain_Has_only_one_node(   ready  )  ) {
          
           _Chain_Initialize_empty(   ready  );
           _Priority_bit_map_Remove(   &the_thread->Priority_map  );
          
           } else
           _Chain_Extract_unprotected(   &the_thread->Object.Node  );
           }
          
           _ISR_Enable(   level  );
          
          }

score/src/threadstackallocate.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadstackallocate.c,  v 1.12 2008/12/15 19:21:01 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/config.h>
          
          /*PAGE
           *
           * _Thread_Stack_Allocate
           *
           * Allocate the requested stack space for the thread.
           * return the actual size allocated after any adjustment
           * or return zero if the allocation failed.
           * Set the Start.stack field to the address of the stack
           */
          
      44  size_t _Thread_Stack_Allocate(  
           Thread_Control *the_thread,  
           size_t stack_size
           )
          {
           void *stack_addr = 0;
           size_t the_stack_size = stack_size;
          
           the_stack_size = _Stack_Ensure_minimum(   stack_size  );
          
           /*
           * Call ONLY the CPU table stack allocate hook,   _or_ the
           * the RTEMS workspace allocate. This is so the stack free
           * routine can call the correct deallocation routine.
           */
          
           if (   Configuration.stack_allocate_hook  ) {
           stack_addr = (  *Configuration.stack_allocate_hook )(   the_stack_size  );
           } else {
          
           /*
           * First pad the requested size so we allocate enough memory
           * so the context initialization can align it properly. The address
           * returned the workspace allocate must be directly stored in the
           * stack control block because it is later used in the free sequence.
           *
           * Thus it is the responsibility of the CPU dependent code to
           * get and keep the stack adjust factor,   the stack alignment,   and
           * the context initialization sequence in sync.
           */
          
           the_stack_size = _Stack_Adjust_size(   the_stack_size  );
           stack_addr = _Workspace_Allocate(   the_stack_size  );
           }
          
           if (   !stack_addr  )
           the_stack_size = 0;
          
           the_thread->Start.stack = stack_addr;
          
           return the_stack_size;
          }

score/src/threadstackfree.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2008.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadstackfree.c,  v 1.7 2009/09/13 21:00:11 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/config.h>
          
          /*
           * _Thread_Stack_Free
           *
           * Deallocate the Thread's stack.
           */
          
      40  void _Thread_Stack_Free(  
           Thread_Control *the_thread
           )
          {
           #if defined(  RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API )
           /*
           * If the API provided the stack space,   then don't free it.
           */
           if (   !the_thread->Start.core_allocated_stack  )
           return;
           #endif
          
           /*
           * Call ONLY the CPU table stack free hook,   or the
           * the RTEMS workspace free. This is so the free
           * routine properly matches the allocation of the stack.
           */
          
           if (   Configuration.stack_free_hook  )
           (  *Configuration.stack_free_hook )(   the_thread->Start.Initial_stack.area  );
           else
           _Workspace_Free(   the_thread->Start.Initial_stack.area  );
          }

score/src/threadstart.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadstart.c,  v 1.9 2008/09/04 17:39:56 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*
           * _Thread_Start
           *
           * DESCRIPTION:
           *
           * This routine initializes the executable information for a thread
           * and makes it ready to execute. After this routine executes,   the
           * thread competes with all other threads for CPU time.
           */
          
      43  bool _Thread_Start(  
           Thread_Control *the_thread,  
           Thread_Start_types the_prototype,  
           void *entry_point,  
           void *pointer_argument,  
           Thread_Entry_numeric_type numeric_argument
           )
          {
           if (   _States_Is_dormant(   the_thread->current_state  )  ) {
          
           the_thread->Start.entry_point = (  Thread_Entry ) entry_point;
          
           the_thread->Start.prototype = the_prototype;
           the_thread->Start.pointer_argument = pointer_argument;
           the_thread->Start.numeric_argument = numeric_argument;
          
           _Thread_Load_environment(   the_thread  );
          
           _Thread_Ready(   the_thread  );
          
           _User_extensions_Thread_start(   the_thread  );
          
           return true;
           }
          
           return false;
          }

score/src/threadstartmultitasking.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2006.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadstartmultitasking.c,  v 1.11 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Start_multitasking
           *
           * This kernel routine readies the requested thread,   the thread chain
           * is adjusted. A new heir thread may be selected.
           *
           * Input parameters:
           * system_thread - pointer to system initialization thread control block
           * idle_thread - pointer to idle thread control block
           *
           * Output parameters: NONE
           *
           * NOTE: This routine uses the "blocking" heir selection mechanism.
           * This ensures the correct heir after a thread restart.
           *
           * INTERRUPT LATENCY:
           * ready chain
           * select heir
           */
          
      54  void _Thread_Start_multitasking(   void  )
          {
           /*
           * The system is now multitasking and completely initialized.
           * This system thread now "hides" in a single processor until
           * the system is shut down.
           */
          
           _System_state_Set(   SYSTEM_STATE_UP  );
          
           _Thread_Dispatch_necessary = false;
          
           _Thread_Executing = _Thread_Heir;
          
           /*
           * Get the init task(  s ) running.
           *
           * Note: Thread_Dispatch(   ) is normally used to dispatch threads. As
           * part of its work,   Thread_Dispatch(   ) restores floating point
           * state for the heir task.
           *
           * This code avoids Thread_Dispatch(   ),   and so we have to restore
           * (  actually initialize ) the floating point state "by hand".
           *
           * Ignore the CPU_USE_DEFERRED_FP_SWITCH because we must always
           * switch in the first thread if it is FP.
           */
          #if (   CPU_HARDWARE_FP == TRUE  ) || (   CPU_SOFTWARE_FP == TRUE  )
           /*
           * don't need to worry about saving BSP's floating point state
           */
          
           if (   _Thread_Heir->fp_context != NULL  )
           _Context_Restore_fp(   &_Thread_Heir->fp_context  );
          #endif
          
           _Context_Switch(   &_Thread_BSP_context,   &_Thread_Heir->Registers  );
          }

score/src/threadsuspend.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadsuspend.c,  v 1.9 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Suspend
           *
           * This kernel routine sets the SUSPEND state in the THREAD. The
           * THREAD chain and suspend count are adjusted if necessary.
           *
           * Input parameters:
           * the_thread - pointer to thread control block
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * ready chain
           * select map
           */
          
      50  void _Thread_Suspend(  
           Thread_Control *the_thread
           )
          {
           ISR_Level level;
           Chain_Control *ready;
          
           ready = the_thread->ready;
           _ISR_Disable(   level  );
           if (   !_States_Is_ready(   the_thread->current_state  )  ) {
           the_thread->current_state =
           _States_Set(   STATES_SUSPENDED,   the_thread->current_state  );
           _ISR_Enable(   level  );
           return;
           }
          
           the_thread->current_state = STATES_SUSPENDED;
          
           if (   _Chain_Has_only_one_node(   ready  )  ) {
          
           _Chain_Initialize_empty(   ready  );
           _Priority_bit_map_Remove(   &the_thread->Priority_map  );
          
           } else
           _Chain_Extract_unprotected(   &the_thread->Object.Node  );
          
           _ISR_Flash(   level  );
          
           if (   _Thread_Is_heir(   the_thread  )  )
           _Thread_Calculate_heir(   );
          
           if (   _Thread_Is_executing(   the_thread  )  )
           _Thread_Dispatch_necessary = true;
          
           _ISR_Enable(   level  );
          }

score/src/threadtickletimeslice.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-2009.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadtickletimeslice.c,  v 1.12 2010/06/24 21:27:30 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Tickle_timeslice
           *
           * This scheduler routine determines if timeslicing is enabled
           * for the currently executing thread and,   if so,   updates the
           * timeslice count and checks for timeslice expiration.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      46  void _Thread_Tickle_timeslice(   void  )
          {
           Thread_Control *executing;
          
           executing = _Thread_Executing;
          
           #ifdef __RTEMS_USE_TICKS_FOR_STATISTICS__
           /*
           * Increment the number of ticks this thread has been executing
           */
           executing->cpu_time_used++;
           #endif
          
           /*
           * If the thread is not preemptible or is not ready,   then
           * just return.
           */
          
           if (   !executing->is_preemptible  )
           return;
          
           if (   !_States_Is_ready(   executing->current_state  )  )
           return;
          
           /*
           * The cpu budget algorithm determines what happens next.
           */
          
           switch (   executing->budget_algorithm  ) {
           case THREAD_CPU_BUDGET_ALGORITHM_NONE:
           break;
          
           case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
           #if defined(  RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE )
           case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
           #endif
           if (   (  int )(  --executing->cpu_time_budget ) <= 0  ) {
          
           /*
           * A yield performs the ready chain mechanics needed when
           * resetting a timeslice. If no other thread's are ready
           * at the priority of the currently executing thread,   then the
           * executing thread's timeslice is reset. Otherwise,   the
           * currently executing thread is placed at the rear of the
           * FIFO for this priority and a new heir is selected.
           */
           _Thread_Yield_processor(   );
           executing->cpu_time_budget = _Thread_Ticks_per_timeslice;
           }
           break;
          
           #if defined(  RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT )
           case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
           if (   --executing->cpu_time_budget == 0  )
           (  *executing->budget_callout )(   executing  );
           break;
           #endif
           }
          }

score/src/threadyieldprocessor.c

       1  /*
           * Thread Handler
           *
           *
           * COPYRIGHT (  c ) 1989-1999.
           * On-Line Applications Research Corporation (  OAR ).
           *
           * The license and distribution terms for this file may be
           * found in found in the file LICENSE in this distribution or at
           * http://www.rtems.com/license/LICENSE.
           *
           * $Id: threadyieldprocessor.c,  v 1.6 2010/07/30 18:53:06 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/apiext.h>
          #include <rtems/score/context.h>
          #include <rtems/score/interr.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/object.h>
          #include <rtems/score/priority.h>
          #include <rtems/score/states.h>
          #include <rtems/score/sysstate.h>
          #include <rtems/score/thread.h>
          #include <rtems/score/threadq.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          
          /*PAGE
           *
           * _Thread_Yield_processor
           *
           * This kernel routine will remove the running THREAD from the ready chain
           * and place it immediatly at the rear of this chain. Reset timeslice
           * and yield the processor functions both use this routine,   therefore if
           * reset is true and this is the only thread on the chain then the
           * timeslice counter is reset. The heir THREAD will be updated if the
           * running is also the currently the heir.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           *
           * INTERRUPT LATENCY:
           * ready chain
           * select heir
           */
          
      53  void _Thread_Yield_processor(   void  )
          {
           ISR_Level level;
           Thread_Control *executing;
           Chain_Control *ready;
          
           executing = _Thread_Executing;
           ready = executing->ready;
           _ISR_Disable(   level  );
           if (   !_Chain_Has_only_one_node(   ready  )  ) {
           _Chain_Extract_unprotected(   &executing->Object.Node  );
           _Chain_Append_unprotected(   ready,   &executing->Object.Node  );
          
           _ISR_Flash(   level  );
          
           if (   _Thread_Is_heir(   executing  )  )
           _Thread_Heir = (  Thread_Control * ) ready->first;
           _Thread_Dispatch_necessary = true;
           }
           else if (   !_Thread_Is_heir(   executing  )  )
           _Thread_Dispatch_necessary = true;
          
           _ISR_Enable(   level  );
          }

score/src/timespecaddto.c

       1  /**
           * @file score/src/timespecaddto.c
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timespecaddto.c,  v 1.3 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <sys/types.h>
          #include <rtems/score/timespec.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /**
           *
           * This routines adds two timespecs. The second argument is added
           * to the first.
           */
          
      32  uint32_t _Timespec_Add_to(  
           struct timespec *time,  
           const struct timespec *add
           )
          {
           uint32_t seconds = add->tv_sec;
          
           /* Add the basics */
           time->tv_sec += add->tv_sec;
           time->tv_nsec += add->tv_nsec;
          
           /* Now adjust it so nanoseconds is in range */
           while (   time->tv_nsec >= TOD_NANOSECONDS_PER_SECOND  ) {
           time->tv_nsec -= TOD_NANOSECONDS_PER_SECOND;
           time->tv_sec++;
           seconds++;
           }
          
           return seconds;
          }

score/src/timespecdivide.c

       1  /**
           * @file score/src/timespecdivide.c
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timespecdivide.c,  v 1.6 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <sys/types.h>
          #include <rtems/score/timespec.h>
          #include <rtems/score/tod.h>
          
      25  void _Timespec_Divide(  
           const struct timespec *lhs,  
           const struct timespec *rhs,  
           uint32_t *ival_percentage,  
           uint32_t *fval_percentage
           )
          {
           uint64_t left,   right,   answer;
          
           /*
           * For math simplicity just convert the timespec to nanoseconds
           * in a 64-bit integer.
           */
           left = lhs->tv_sec * (  uint64_t )TOD_NANOSECONDS_PER_SECOND;
           left += lhs->tv_nsec;
           right = rhs->tv_sec * (  uint64_t )TOD_NANOSECONDS_PER_SECOND;
           right += rhs->tv_nsec;
          
           if (   right == 0  ) {
           *ival_percentage = 0;
           *fval_percentage = 0;
           return;
           }
          
           /*
           * Put it back in the timespec result.
           *
           * TODO: Rounding on the last digit of the fval.
           */
          
           answer = (  left * 100000 ) / right;
          
           *ival_percentage = answer / 1000;
           *fval_percentage = answer % 1000;
          }

score/src/timespecdividebyinteger.c

       1  /**
           * @file score/src/timespecdividebyinteger.c
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timespecdividebyinteger.c,  v 1.3 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <sys/types.h>
          #include <rtems/score/timespec.h>
          #include <rtems/score/tod.h>
          
      25  void _Timespec_Divide_by_integer(  
           const struct timespec *time,  
           uint32_t iterations,  
           struct timespec *result
           )
          {
           uint64_t t;
          
           /*
           * For math simplicity just convert the timespec to nanoseconds
           * in a 64-bit integer.
           */
           t = time->tv_sec;
           t *= TOD_NANOSECONDS_PER_SECOND;
           t += time->tv_nsec;
          
           /*
           * Divide to get nanoseconds per iteration
           */
          
           t /= iterations;
          
           /*
           * Put it back in the timespec result
           */
          
           result->tv_sec = t / TOD_NANOSECONDS_PER_SECOND;
           result->tv_nsec = t % TOD_NANOSECONDS_PER_SECOND;
          }

score/src/timespecfromticks.c

       1  /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timespecfromticks.c,  v 1.2 2008/12/16 17:36:00 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <time.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/timespec.h>
          #include <rtems/score/tod.h>
          
      23  void _Timespec_From_ticks(  
           uint32_t ticks,  
           struct timespec *time
           )
          {
           uint32_t usecs;
          
           usecs = ticks * rtems_configuration_get_microseconds_per_tick(   );
          
           time->tv_sec = usecs / TOD_MICROSECONDS_PER_SECOND;
           time->tv_nsec = (  usecs % TOD_MICROSECONDS_PER_SECOND ) *
           TOD_NANOSECONDS_PER_MICROSECOND;
          }

score/src/timespecgreaterthan.c

       1  /**
           * @file score/src/timespecgreaterthan.c
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timespecgreaterthan.c,  v 1.4 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timespec.h>
          #include <rtems/score/tod.h>
          
      26  bool _Timespec_Greater_than(  
           const struct timespec *lhs,  
           const struct timespec *rhs
           )
          {
           if (   lhs->tv_sec > rhs->tv_sec  )
           return true;
          
           if (   lhs->tv_sec < rhs->tv_sec  )
           return false;
          
           /* ASSERT: lhs->tv_sec == rhs->tv_sec */
           if (   lhs->tv_nsec > rhs->tv_nsec  )
           return true;
          
           return false;
          }

score/src/timespecisvalid.c

       1  /**
           * @file score/src/timespecisvalid.c
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timespecisvalid.c,  v 1.4 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timespec.h>
          #include <rtems/score/tod.h>
          
      26  bool _Timespec_Is_valid(  
           const struct timespec *time
           )
          {
           if (   !time  )
           return false;
          
           if (   time->tv_sec < 0  )
           return false;
          
           if (   time->tv_nsec < 0  )
           return false;
          
           if (   time->tv_nsec >= TOD_NANOSECONDS_PER_SECOND  )
           return false;
          
           return true;
          }

score/src/timespeclessthan.c

       1  /**
           * @file score/src/timespeclessthan.c
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timespeclessthan.c,  v 1.4 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timespec.h>
          #include <rtems/score/tod.h>
          
      26  bool _Timespec_Less_than(  
           const struct timespec *lhs,  
           const struct timespec *rhs
           )
          {
           if (   lhs->tv_sec < rhs->tv_sec  )
           return true;
          
           if (   lhs->tv_sec > rhs->tv_sec  )
           return false;
          
           /* ASSERT: lhs->tv_sec == rhs->tv_sec */
           if (   lhs->tv_nsec < rhs->tv_nsec  )
           return true;
          
           return false;
          }

score/src/timespecsubtract.c

       1  /**
           * @file score/src/timespecsubtract.c
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timespecsubtract.c,  v 1.2 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <sys/types.h>
          #include <rtems/score/timespec.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
      26  void _Timespec_Subtract(  
           const struct timespec *start,  
           const struct timespec *end,  
           struct timespec *result
           )
          {
          
           if (  end->tv_nsec < start->tv_nsec ) {
           result->tv_sec = end->tv_sec - start->tv_sec - 1;
           result->tv_nsec =
           (  TOD_NANOSECONDS_PER_SECOND - start->tv_nsec ) + end->tv_nsec;
           } else {
           result->tv_sec = end->tv_sec - start->tv_sec;
           result->tv_nsec = end->tv_nsec - start->tv_nsec;
           }
          }

score/src/timespectoticks.c

       1  /**
           * @file score/src/timespectoticks.c
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: timespectoticks.c,  v 1.3 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/timespec.h>
          #include <rtems/score/tod.h>
          #include <rtems/score/watchdog.h>
          
          /**
           *
           * This routines converts a timespec to the corresponding number of ticks.
           */
          
      33  uint32_t _Timespec_To_ticks(  
           const struct timespec *time
           )
          {
           uint32_t ticks;
          
           if (   (  time->tv_sec == 0 ) && (  time->tv_nsec == 0 )  )
           return 0;
          
           ticks = time->tv_sec * TOD_TICKS_PER_SECOND;
          
           ticks += time->tv_nsec / rtems_configuration_get_nanoseconds_per_tick(   );
          
           if (  ticks )
           return ticks;
          
           return 1;
          }

score/src/ts64addto.c

       1  /**
           * @file score/src/ts64addto.c
          */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64addto.c,  v 1.1 2008/12/09 21:27:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timestamp.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      26   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          void _Timestamp64_Add_to(  
           Timestamp64_Control *_time,  
           Timestamp64_Control *_add
           )
          {
           *_time += *_add;
          }
          #endif

score/src/ts64divide.c

       1  /**
           * @file score/src/ts64divide.c
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64divide.c,  v 1.3 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <sys/types.h>
          #include <rtems/score/timestamp.h>
          
          /* This method is never inlined. */
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 )
      26  void _Timestamp64_Divide(  
           const Timestamp64_Control *_lhs,  
           const Timestamp64_Control *_rhs,  
           uint32_t *_ival_percentage,  
           uint32_t *_fval_percentage
           )
          {
           Timestamp64_Control answer;
          
           if (   *_rhs == 0  ) {
           *_ival_percentage = 0;
           *_fval_percentage = 0;
           return;
           }
          
           /*
           * This looks odd but gives the results the proper precision.
           *
           * TODO: Rounding on the last digit of the fval.
           */
          
           answer = (  *_lhs * 100000 ) / *_rhs;
          
           *_ival_percentage = answer / 1000;
           *_fval_percentage = answer % 1000;
          }
          #endif

score/src/ts64dividebyinteger.c

       1  /**
           * @file score/src/ts64dividebyinteger.c
          */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64dividebyinteger.c,  v 1.1 2008/12/09 21:27:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timestamp.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      26   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          void _Timestamp64_Divide_by_integer(  
           Timestamp64_Control *_time,  
           uint32_t _iterations,  
           Timestamp64_Control *_result
           )
          {
           *_result = *_time / _iterations;
          }
          #endif

score/src/ts64equalto.c

       1  /**
           * @file score/src/ts64equalto.c
          */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64equalto.c,  v 1.1 2008/12/09 21:27:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timestamp.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      26   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          bool _Timestamp64_Equal_to(  
           Timestamp64_Control *_lhs,  
           Timestamp64_Control *_rhs
           )
          {
           return (  *(  _lhs ) == *(  _rhs ) );
          }
          #endif

score/src/ts64getnanoseconds.c

       1  /**
           * @file score/src/ts64toticks.c
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64getnanoseconds.c,  v 1.2 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timestamp.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      26   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          uint32_t _Timestamp64_Get_nanoseconds(  
           Timestamp64_Control *_time
           )
          {
           return *(  _time ) % 1000000000;
          }
          #endif

score/src/ts64getseconds.c

       1  /**
           * @file score/src/ts64getseconds.c
          */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64getseconds.c,  v 1.1 2008/12/09 21:27:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timestamp.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      26   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          uint32_t _Timestamp64_Get_seconds(  
           Timestamp64_Control *_time
           )
          {
           return *(  _time ) / 1000000000;
          }
          #endif

score/src/ts64greaterthan.c

       1  /**
           * @file score/src/ts64greaterthan.c
          */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64greaterthan.c,  v 1.1 2008/12/09 21:27:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timestamp.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      26   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          bool _Timestamp64_Greater_than(  
           Timestamp64_Control *_lhs,  
           Timestamp64_Control *_rhs
           )
          {
           return (  *(  _lhs ) > *(  _rhs ) );
          }
          #endif

score/src/ts64lessthan.c

       1  /**
           * @file score/src/ts64lessthan.c
          */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64lessthan.c,  v 1.1 2008/12/09 21:27:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timestamp.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      26   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          bool _Timestamp64_Less_than(  
           Timestamp64_Control *_lhs,  
           Timestamp64_Control *_rhs
           )
          {
           return (  *(  _lhs ) < *(  _rhs ) );
          }
          #endif

score/src/ts64set.c

       1  /**
           * @file score/src/ts64set.c
          */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64set.c,  v 1.1 2008/12/09 21:27:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timestamp.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      26   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          void _Timestamp64_Set(  
           Timestamp64_Control *_time,  
           long _seconds,  
           long _nanoseconds
           )
          {
           int64_t time;
          
           time = (  int64_t )_seconds * 1000000000;
           time += (  int64_t )_nanoseconds;
           *_time = time;
          }
          #endif

score/src/ts64settozero.c

       1  /**
           * @file score/src/ts64settozero.c
          */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64settozero.c,  v 1.1 2008/12/09 21:27:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timestamp.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      26   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          void _Timestamp64_Set_to_zero(  
           Timestamp64_Control *_time
           )
          {
           *_time = 0;
          }
          #endif

score/src/ts64subtract.c

       1  /**
           * @file score/src/ts64subtract.c
          */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64subtract.c,  v 1.1 2008/12/09 21:27:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timestamp.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      26   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          void _Timestamp64_Subtract(  
           Timestamp64_Control *_start,  
           Timestamp64_Control *_end,  
           Timestamp64_Control *_result
           )
          {
           *_result = *_end - *_start;
          }
          #endif

score/src/ts64toticks.c

       1  /**
           * @file score/src/ts64toticks.c
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64toticks.c,  v 1.3 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/timestamp.h>
          #include <rtems/score/tod.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      28   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          uint32_t _Timestamp64_To_ticks(  
           const Timestamp64_Control *time
           )
          {
           uint32_t ticks;
          
           ticks = *time / rtems_configuration_get_nanoseconds_per_tick(   );
           if (   ticks  )
           return ticks;
           return 1;
          }
          #endif

score/src/ts64totimespec.c

       1  /**
           * @file score/src/ts64totimespec.c
          */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: ts64totimespec.c,  v 1.1 2008/12/09 21:27:35 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <sys/types.h>
          
          #include <rtems/system.h>
          #include <rtems/score/timestamp.h>
          
          #if defined(  CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64 ) && \
      26   !defined(  CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE )
          void _Timestamp64_To_timespec(  
           Timestamp64_Control *_timestamp,  
           struct timespec *_timespec
           )
          {
           _timespec->tv_sec = *_timestamp / 1000000000;
           _timespec->tv_nsec = *_timestamp % 1000000000;
          }
          #endif

score/src/userext.c

       1  /**
           * @file
           *
           * @ingroup ScoreUserExt
           *
           * @brief User Extension Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: userext.c,  v 1.17 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/userext.h>
          #include <rtems/score/wkspace.h>
          #include <string.h>
          
      30  void _User_extensions_Handler_initialization(  void )
          {
           User_extensions_Control *extension;
           uint32_t i;
           uint32_t number_of_extensions;
           User_extensions_Table *initial_extensions;
          
           number_of_extensions = Configuration.number_of_initial_extensions;
           initial_extensions = Configuration.User_extension_table;
          
           _Chain_Initialize_empty(   &_User_extensions_List  );
           _Chain_Initialize_empty(   &_User_extensions_Switches_list  );
          
           if (   initial_extensions  ) {
           extension = (  User_extensions_Control * )
           _Workspace_Allocate_or_fatal_error(  
           number_of_extensions * sizeof(   User_extensions_Control  )
            );
          
           memset (  
           extension,  
           0,  
           number_of_extensions * sizeof(   User_extensions_Control  )
            );
          
           for (   i = 0 ; i < number_of_extensions ; i++  ) {
           _User_extensions_Add_set_with_table (  extension,   &initial_extensions[i] );
           extension++;
           }
           }
          }
          

score/src/userextaddset.c

       1  /**
           * @file
           *
           * @ingroup ScoreUserExt
           *
           * @brief User Extension Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: userextaddset.c,  v 1.2 2009/09/25 17:51:46 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/userext.h>
          
      27  void _User_extensions_Add_set(  
           User_extensions_Control *the_extension
           )
          {
           _Chain_Append(   &_User_extensions_List,   &the_extension->Node  );
          
           /*
           * If a switch handler is present,   append it to the switch chain.
           */
          
           if (   the_extension->Callouts.thread_switch != NULL  ) {
           the_extension->Switch.thread_switch =
           the_extension->Callouts.thread_switch;
           _Chain_Append(  
           &_User_extensions_Switches_list,  
           &the_extension->Switch.Node
            );
           }
          }

score/src/userextremoveset.c

       1  /**
           * @file
           *
           * @ingroup ScoreUserExt
           *
           * @brief User Extension Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: userextremoveset.c,  v 1.3 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/userext.h>
          
      27  void _User_extensions_Remove_set (  
           User_extensions_Control *the_extension
           )
          {
           _Chain_Extract(   &the_extension->Node  );
          
           /*
           * If a switch handler is present,   remove it.
           */
          
           if (   the_extension->Callouts.thread_switch != NULL  )
           _Chain_Extract(   &the_extension->Switch.Node  );
          }

score/src/userextthreadbegin.c

       1  /**
           * @file
           *
           * @ingroup ScoreUserExt
           *
           * @brief User Extension Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: userextthreadbegin.c,  v 1.4 2009/10/12 12:16:22 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/userext.h>
          
      27  void _User_extensions_Thread_begin (  
           Thread_Control *executing
           )
          {
           Chain_Node *the_node;
           User_extensions_Control *the_extension;
          
           for (   the_node = _User_extensions_List.first ;
           !_Chain_Is_tail(   &_User_extensions_List,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_extension = (  User_extensions_Control * ) the_node;
          
           if (   the_extension->Callouts.thread_begin != NULL  )
           (  *the_extension->Callouts.thread_begin )(   executing  );
           }
          }
          
      45  void _User_extensions_Thread_exitted (  
           Thread_Control *executing
           )
          {
           Chain_Node *the_node;
           User_extensions_Control *the_extension;
          
           for (   the_node = _User_extensions_List.last ;
           !_Chain_Is_head(   &_User_extensions_List,   the_node  ) ;
           the_node = the_node->previous  ) {
          
           the_extension = (  User_extensions_Control * ) the_node;
          
           if (   the_extension->Callouts.thread_exitted != NULL  )
           (  *the_extension->Callouts.thread_exitted )(   executing  );
           }
          }
          
      63  void _User_extensions_Fatal (  
           Internal_errors_Source the_source,  
           bool is_internal,  
           Internal_errors_t the_error
           )
          {
           Chain_Node *the_node;
           User_extensions_Control *the_extension;
          
           for (   the_node = _User_extensions_List.last ;
           !_Chain_Is_head(   &_User_extensions_List,   the_node  ) ;
           the_node = the_node->previous  ) {
          
           the_extension = (  User_extensions_Control * ) the_node;
          
           if (   the_extension->Callouts.fatal != NULL  )
           (  *the_extension->Callouts.fatal )(   the_source,   is_internal,   the_error  );
           }
          }

score/src/userextthreadcreate.c

       1  /**
           * @file
           *
           * @ingroup ScoreUserExt
           *
           * @brief User Extension Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: userextthreadcreate.c,  v 1.4 2009/09/25 17:51:46 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/userext.h>
          
      27  bool _User_extensions_Thread_create (  
           Thread_Control *the_thread
           )
          {
           Chain_Node *the_node;
           User_extensions_Control *the_extension;
           bool status;
          
           for (   the_node = _User_extensions_List.first ;
           !_Chain_Is_tail(   &_User_extensions_List,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_extension = (  User_extensions_Control * ) the_node;
          
           if (   the_extension->Callouts.thread_create != NULL  ) {
           status = (  *the_extension->Callouts.thread_create )(  
           _Thread_Executing,  
           the_thread
            );
           if (   !status  )
           return false;
           }
           }
          
           return true;
          }

score/src/userextthreaddelete.c

       1  /**
           * @file
           *
           * @ingroup ScoreUserExt
           *
           * @brief User Extension Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: userextthreaddelete.c,  v 1.2 2009/09/25 17:51:46 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/userext.h>
          
      27  void _User_extensions_Thread_delete (  
           Thread_Control *the_thread
           )
          {
           Chain_Node *the_node;
           User_extensions_Control *the_extension;
          
           for (   the_node = _User_extensions_List.last ;
           !_Chain_Is_head(   &_User_extensions_List,   the_node  ) ;
           the_node = the_node->previous  ) {
          
           the_extension = (  User_extensions_Control * ) the_node;
          
           if (   the_extension->Callouts.thread_delete != NULL  )
           (  *the_extension->Callouts.thread_delete )(  
           _Thread_Executing,  
           the_thread
            );
           }
          }

score/src/userextthreadrestart.c

       1  /**
           * @file
           *
           * @ingroup ScoreUserExt
           *
           * @brief User Extension Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: userextthreadrestart.c,  v 1.2 2009/09/25 17:51:46 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/userext.h>
          
      27  void _User_extensions_Thread_restart (  
           Thread_Control *the_thread
           )
          {
           Chain_Node *the_node;
           User_extensions_Control *the_extension;
          
           for (   the_node = _User_extensions_List.first ;
           !_Chain_Is_tail(   &_User_extensions_List,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_extension = (  User_extensions_Control * ) the_node;
          
           if (   the_extension->Callouts.thread_restart != NULL  )
           (  *the_extension->Callouts.thread_restart )(  
           _Thread_Executing,  
           the_thread
            );
           }
          }

score/src/userextthreadstart.c

       1  /**
           * @file
           *
           * @ingroup ScoreUserExt
           *
           * @brief User Extension Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: userextthreadstart.c,  v 1.2 2009/09/25 17:51:46 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/userext.h>
          
      27  void _User_extensions_Thread_start (  
           Thread_Control *the_thread
           )
          {
           Chain_Node *the_node;
           User_extensions_Control *the_extension;
          
           for (   the_node = _User_extensions_List.first ;
           !_Chain_Is_tail(   &_User_extensions_List,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_extension = (  User_extensions_Control * ) the_node;
          
           if (   the_extension->Callouts.thread_start != NULL  )
           (  *the_extension->Callouts.thread_start )(  
           _Thread_Executing,  
           the_thread
            );
           }
          }

score/src/userextthreadswitch.c

       1  /**
           * @file
           *
           * @ingroup ScoreUserExt
           *
           * @brief User Extension Handler implementation.
           */
          
          /*
           * COPYRIGHT (  c ) 1989-2007.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: userextthreadswitch.c,  v 1.3 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/userext.h>
          
      27  void _User_extensions_Thread_switch (  
           Thread_Control *executing,  
           Thread_Control *heir
           )
          {
           Chain_Node *the_node;
           User_extensions_Switch_control *the_extension_switch;
          
           for (   the_node = _User_extensions_Switches_list.first ;
           !_Chain_Is_tail(   &_User_extensions_Switches_list,   the_node  ) ;
           the_node = the_node->next  ) {
          
           the_extension_switch = (  User_extensions_Switch_control * ) the_node;
          
           (  *the_extension_switch->thread_switch )(   executing,   heir  );
           }
          }

score/src/watchdog.c

       1  /*
           * Watchdog Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: watchdog.c,  v 1.17 2005/01/27 05:57:05 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _Watchdog_Handler_initialization
           *
           * This routine initializes the watchdog handler.
           *
           * Input parameters: NONE
           *
           * Output parameters: NONE
           */
          
      34  void _Watchdog_Handler_initialization(   void  )
          {
           _Watchdog_Sync_count = 0;
           _Watchdog_Sync_level = 0;
           _Watchdog_Ticks_since_boot = 0;
          
           _Chain_Initialize_empty(   &_Watchdog_Ticks_chain  );
           _Chain_Initialize_empty(   &_Watchdog_Seconds_chain  );
          }

score/src/watchdogadjust.c

       1  /*
           * Watchdog Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: watchdogadjust.c,  v 1.7 2008/11/25 22:29:58 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _Watchdog_Adjust
           *
           * This routine adjusts the delta chain backward or forward in response
           * to a time change.
           *
           * Input parameters:
           * header - pointer to the delta chain to be adjusted
           * direction - forward or backward adjustment to delta chain
           * units - units to adjust
           *
           * Output parameters:
           */
          
      38  void _Watchdog_Adjust(  
           Chain_Control *header,  
           Watchdog_Adjust_directions direction,  
           Watchdog_Interval units
           )
          {
           ISR_Level level;
          
           _ISR_Disable(   level  );
          
           /*
           * NOTE: It is safe NOT to make 'header' a pointer
           * to volatile data (  contrast this with watchdoginsert.c )
           * because we call _Watchdog_Tickle(   ) below and
           * hence the compiler must not assume *header to remain
           * unmodified across that call.
           *
           * Till Straumann,   7/2003
           */
           if (   !_Chain_Is_empty(   header  )  ) {
           switch (   direction  ) {
           case WATCHDOG_BACKWARD:
           _Watchdog_First(   header  )->delta_interval += units;
           break;
           case WATCHDOG_FORWARD:
           while (   units  ) {
           if (   units < _Watchdog_First(   header  )->delta_interval  ) {
           _Watchdog_First(   header  )->delta_interval -= units;
           break;
           } else {
           units -= _Watchdog_First(   header  )->delta_interval;
           _Watchdog_First(   header  )->delta_interval = 1;
          
           _ISR_Enable(   level  );
          
           _Watchdog_Tickle(   header  );
          
           _ISR_Disable(   level  );
          
           if (   _Chain_Is_empty(   header  )  )
           break;
           }
           }
           break;
           }
           }
          
           _ISR_Enable(   level  );
          
          }

score/src/watchdogadjusttochain.c

       1  /**
           * @file watchdogadjusttochain.c
           *
           * This is used by the Timer Server task.
           */
          
          /* COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: watchdogadjusttochain.c,  v 1.4 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/watchdog.h>
          
      25  void _Watchdog_Adjust_to_chain(  
           Chain_Control *header,  
           Watchdog_Interval units_arg,  
           Chain_Control *to_fire
          
           )
          {
           Watchdog_Interval units = units_arg;
           ISR_Level level;
           Watchdog_Control *first;
          
           if (   units <= 0  ) {
           return;
           }
          
           _ISR_Disable(   level  );
          
           while (   1  ) {
           if (   units <= 0  ) {
           break;
           }
           if (   _Chain_Is_empty(   header  )  ) {
           break;
           }
           first = _Watchdog_First(   header  );
          
           /*
           * If it is longer than "units" until the first element on the chain
           * fires,   then bump it and quit.
           */
           if (   units < first->delta_interval  ) {
           first->delta_interval -= units;
           break;
           }
          
           /*
           * The first set happens in less than units,   so take all of them
           * off the chain and adjust units to reflect this.
           */
           units -= first->delta_interval;
           first->delta_interval = 0;
          
           while (   1  ) {
           _Chain_Extract_unprotected(   &first->Node  );
           _Chain_Append_unprotected(   to_fire,   &first->Node  );
          
           _ISR_Flash(   level  );
          
           if (   _Chain_Is_empty(   header  )  )
           break;
           first = _Watchdog_First(   header  );
           if (   first->delta_interval != 0  )
           break;
           }
           }
          
           _ISR_Enable(   level  );
          }
          

score/src/watchdoginsert.c

       1  /*
           * Watchdog Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: watchdoginsert.c,  v 1.10 2005/08/17 22:49:56 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _Watchdog_Insert
           *
           * This routine inserts a watchdog timer on to the appropriate delta
           * chain while updating the delta interval counters.
           */
          
      31  void _Watchdog_Insert(  
           Chain_Control *header,  
           Watchdog_Control *the_watchdog
           )
          {
           ISR_Level level;
           Watchdog_Control *after;
           uint32_t insert_isr_nest_level;
           Watchdog_Interval delta_interval;
          
          
           insert_isr_nest_level = _ISR_Nest_level;
          
           _ISR_Disable(   level  );
          
           /*
           * Check to see if the watchdog has just been inserted by a
           * higher priority interrupt. If so,   abandon this insert.
           */
          
           if (   the_watchdog->state != WATCHDOG_INACTIVE  ) {
           _ISR_Enable(   level  );
           return;
           }
          
           the_watchdog->state = WATCHDOG_BEING_INSERTED;
           _Watchdog_Sync_count++;
          
          restart:
           delta_interval = the_watchdog->initial;
          
           /*
           * We CANT use _Watchdog_First(   ) here,   because a TICK interrupt
           * could modify the chain during the _ISR_Flash(   ) below. Hence,  
           * the header is pointing to volatile data. The _Watchdog_First(   )
           * INLINE routine (  but not the macro - note the subtle difference )
           * casts away the 'volatile'...
           *
           * Also,   this is only necessary because we call no other routine
           * from this piece of code,   hence the compiler thinks it's safe to
           * cache *header!!
           *
           * Till Straumann,   7/2003 (  gcc-3.2.2 -O4 on powerpc )
           *
           */
           for (   after = (  Watchdog_Control * ) (  (  volatile Chain_Control * )header )->first ;
           ;
           after = _Watchdog_Next(   after  )  ) {
          
           if (   delta_interval == 0 || !_Watchdog_Next(   after  )  )
           break;
          
           if (   delta_interval < after->delta_interval  ) {
           after->delta_interval -= delta_interval;
           break;
           }
          
           delta_interval -= after->delta_interval;
          
           /*
           * If you experience problems comment out the _ISR_Flash line.
           * 3.2.0 was the first release with this critical section redesigned.
           * Under certain circumstances,   the PREVIOUS critical section algorithm
           * used around this flash point allowed interrupts to execute
           * which violated the design assumptions. The critical section
           * mechanism used here WAS redesigned to address this.
           */
          
           _ISR_Flash(   level  );
          
           if (   the_watchdog->state != WATCHDOG_BEING_INSERTED  ) {
           goto exit_insert;
           }
          
           if (   _Watchdog_Sync_level > insert_isr_nest_level  ) {
           _Watchdog_Sync_level = insert_isr_nest_level;
           goto restart;
           }
           }
          
           _Watchdog_Activate(   the_watchdog  );
          
           the_watchdog->delta_interval = delta_interval;
          
           _Chain_Insert_unprotected(   after->Node.previous,   &the_watchdog->Node  );
          
           the_watchdog->start_time = _Watchdog_Ticks_since_boot;
          
          exit_insert:
           _Watchdog_Sync_level = insert_isr_nest_level;
           _Watchdog_Sync_count--;
           _ISR_Enable(   level  );
          }

score/src/watchdogremove.c

       1  /*
           * Watchdog Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: watchdogremove.c,  v 1.7 2005/01/27 05:57:05 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _Watchdog_Remove
           *
           * The routine removes a watchdog from a delta chain and updates
           * the delta counters of the remaining watchdogs.
           */
          
      31  Watchdog_States _Watchdog_Remove(  
           Watchdog_Control *the_watchdog
           )
          {
           ISR_Level level;
           Watchdog_States previous_state;
           Watchdog_Control *next_watchdog;
          
           _ISR_Disable(   level  );
           previous_state = the_watchdog->state;
           switch (   previous_state  ) {
           case WATCHDOG_INACTIVE:
           break;
          
           case WATCHDOG_BEING_INSERTED:
          
           /*
           * It is not actually on the chain so just change the state and
           * the Insert operation we interrupted will be aborted.
           */
           the_watchdog->state = WATCHDOG_INACTIVE;
           break;
          
           case WATCHDOG_ACTIVE:
           case WATCHDOG_REMOVE_IT:
          
           the_watchdog->state = WATCHDOG_INACTIVE;
           next_watchdog = _Watchdog_Next(   the_watchdog  );
          
           if (   _Watchdog_Next(  next_watchdog )  )
           next_watchdog->delta_interval += the_watchdog->delta_interval;
          
           if (   _Watchdog_Sync_count  )
           _Watchdog_Sync_level = _ISR_Nest_level;
          
           _Chain_Extract_unprotected(   &the_watchdog->Node  );
           break;
           }
           the_watchdog->stop_time = _Watchdog_Ticks_since_boot;
          
           _ISR_Enable(   level  );
           return(   previous_state  );
          }

score/src/watchdogreport.c

       1  /**
           * @file watchdogreport.c
           *
           * This should only be used for debugging.
           */
          
          /* COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: watchdogreport.c,  v 1.2 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/bspIo.h>
          
      25  void _Watchdog_Report(  
           const char *name,  
           Watchdog_Control *watch
           )
          {
           printk(  
           "%s%s%4d %5d %p %p 0x%08x %p\n",  
           (  (  name ) ? name : "" ),  
           (  (  name ) ? " " : "" ),  
           watch->delta_interval,  
           watch->initial,  
           watch,  
           watch->routine,  
           watch->id,  
           watch->user_data
            );
          }

score/src/watchdogreportchain.c

       1  /**
           * @file watchdogreportchain.c
           *
           * This should only be used for debugging.
           */
          
          /* COPYRIGHT (  c ) 1989-2008.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: watchdogreportchain.c,  v 1.1 2008/11/26 16:33:30 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/watchdog.h>
          #include <rtems/score/isr.h>
          #include <rtems/bspIo.h>
          
      26  void _Watchdog_Report_chain(  
           const char *name,  
           Chain_Control *header
           )
          {
           ISR_Level level;
           Chain_Node *node;
          
           _ISR_Disable(   level  );
           printk(   "Watchdog Chain: %s %p\n",   name,   header  );
           if (   !_Chain_Is_empty(   header  )  ) {
           for (   node = header->first ;
           node != _Chain_Tail(  header ) ;
           node = node->next  )
           {
           Watchdog_Control *watch = (  Watchdog_Control * ) node;
          
           _Watchdog_Report(   NULL,   watch  );
           }
           printk(   "== end of %s \n",   name  );
           } else {
           printk(   "Chain is empty\n"  );
           }
           _ISR_Enable(   level  );
          }

score/src/watchdogtickle.c

       1  /*
           * Watchdog Handler
           *
           *
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: watchdogtickle.c,  v 1.10 2009/11/29 13:51:52 ralf Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/score/isr.h>
          #include <rtems/score/watchdog.h>
          
          /*PAGE
           *
           * _Watchdog_Tickle
           *
           * This routine decrements the delta counter in response to a tick. The
           * delta chain is updated accordingly.
           *
           * Input parameters:
           * header - pointer to the delta chain to be tickled
           *
           * Output parameters: NONE
           */
          
      36  void _Watchdog_Tickle(  
           Chain_Control *header
           )
          {
           ISR_Level level;
           Watchdog_Control *the_watchdog;
           Watchdog_States watchdog_state;
          
           /*
           * See the comment in watchdoginsert.c and watchdogadjust.c
           * about why it's safe not to declare header a pointer to
           * volatile data - till,   2003/7
           */
          
           _ISR_Disable(   level  );
          
           if (   _Chain_Is_empty(   header  )  )
           goto leave;
          
           the_watchdog = _Watchdog_First(   header  );
          
           /*
           * For some reason,   on rare occasions the_watchdog->delta_interval
           * of the head of the watchdog chain is 0. Before this test was
           * added,   on these occasions an event (  which usually was supposed
           * to have a timeout of 1 tick would have a delta_interval of 0,   which
           * would be decremented to 0xFFFFFFFF by the unprotected
           * "the_watchdog->delta_interval--;" operation.
           * This would mean the event would not timeout,   and also the chain would
           * be blocked,   because a timeout with a very high number would be at the
           * head,   rather than at the end.
           * The test "if (  the_watchdog->delta_interval != 0 )"
           * here prevents this from occuring.
           *
           * We were not able to categorically identify the situation that causes
           * this,   but proved it to be true empirically. So this check causes
           * correct behaviour in this circumstance.
           *
           * The belief is that a race condition exists whereby an event at the head
           * of the chain is removed (  by a pending ISR or higher priority task )
           * during the _ISR_Flash(   level  ); in _Watchdog_Insert,   but the watchdog
           * to be inserted has already had its delta_interval adjusted to 0,   and
           * so is added to the head of the chain with a delta_interval of 0.
           *
           * Steven Johnson - 12/2005 (  gcc-3.2.3 -O3 on powerpc )
           */
           if (  the_watchdog->delta_interval != 0 ) {
           the_watchdog->delta_interval--;
           if (   the_watchdog->delta_interval != 0  )
           goto leave;
           }
          
           do {
           watchdog_state = _Watchdog_Remove(   the_watchdog  );
          
           _ISR_Enable(   level  );
          
           switch(   watchdog_state  ) {
           case WATCHDOG_ACTIVE:
           (  *the_watchdog->routine )(  
           the_watchdog->id,  
           the_watchdog->user_data
            );
           break;
          
           case WATCHDOG_INACTIVE:
           /*
           * This state indicates that the watchdog is not on any chain.
           * Thus,   it is NOT on a chain being tickled. This case should
           * never occur.
           */
           break;
          
           case WATCHDOG_BEING_INSERTED:
           /*
           * This state indicates that the watchdog is in the process of
           * BEING inserted on the chain. Thus,   it can NOT be on a chain
           * being tickled. This case should never occur.
           */
           break;
          
           case WATCHDOG_REMOVE_IT:
           break;
           }
          
           _ISR_Disable(   level  );
          
           the_watchdog = _Watchdog_First(   header  );
           } while (   !_Chain_Is_empty(   header  ) &&
           (  the_watchdog->delta_interval == 0 )  );
          
          leave:
           _ISR_Enable(  level );
          }

score/src/wkspace.c

       1  /*
           * Workspace Handler
           *
           * COPYRIGHT (  c ) 1989-2009.
           * 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.rtems.com/license/LICENSE.
           *
           * $Id: wkspace.c,  v 1.33 2010/04/07 17:05:29 joel Exp $
           */
          
          #if HAVE_CONFIG_H
          #include "config.h"
          #endif
          
          #include <rtems/system.h>
          #include <rtems/config.h>
          #include <rtems/score/wkspace.h>
          #include <rtems/score/interr.h>
          
          #include <string.h> /* for memset */
          
          /* #define DEBUG_WORKSPACE */
          #if defined(  DEBUG_WORKSPACE )
           #include <rtems/bspIo.h>
          #endif
          
          /*
           * _Workspace_Handler_initialization
           */
      33  void _Workspace_Handler_initialization(  void )
          {
           uintptr_t memory_available = 0;
           void *starting_address = Configuration.work_space_start;
           uintptr_t size = Configuration.work_space_size;
          
           if (   Configuration.do_zero_of_workspace  )
           memset(   starting_address,   0,   size  );
          
           memory_available = _Heap_Initialize(  
           &_Workspace_Area,  
           starting_address,  
           size,  
           CPU_HEAP_ALIGNMENT
            );
          
           if (   memory_available == 0  )
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_TOO_LITTLE_WORKSPACE
            );
          }
          
          /*
           * _Workspace_Allocate
           */
      60  void *_Workspace_Allocate(  
           size_t size
           )
          {
           void *memory;
          
           memory = _Heap_Allocate(   &_Workspace_Area,   size  );
           #if defined(  DEBUG_WORKSPACE )
           printk(  
           "Workspace_Allocate(  %d ) from %p/%p -> %p\n",  
           size,  
           __builtin_return_address(   0  ),  
           __builtin_return_address(   1  ),  
           memory
            );
           #endif
           return memory;
          }
          
          /*
           * _Workspace_Free
           */
      82  bool _Workspace_Free(  
           void *block
           )
          {
           #if defined(  DEBUG_WORKSPACE )
           printk(  
           "Workspace_Free(  %p ) from %p/%p\n",  
           block,  
           __builtin_return_address(   0  ),  
           __builtin_return_address(   1  )
            );
           #endif
           return _Heap_Free(   &_Workspace_Area,   block  );
          }
          
          /*
           * _Workspace_Allocate_or_fatal_error
           */
     100  void *_Workspace_Allocate_or_fatal_error(  
           size_t size
           )
          {
           void *memory;
          
           memory = _Heap_Allocate(   &_Workspace_Area,   size  );
           #if defined(  DEBUG_WORKSPACE )
           printk(  
           "Workspace_Allocate_or_fatal_error(  %d ) from %p/%p -> %p\n",  
           size,  
           __builtin_return_address(   0  ),  
           __builtin_return_address(   1  ),  
           memory
            );
           #endif
          
           if (   memory == NULL  )
           _Internal_error_Occurred(  
           INTERNAL_ERROR_CORE,  
           true,  
           INTERNAL_ERROR_WORKSPACE_ALLOCATION
            );
          
           return memory;
          }