Exemplo n.º 1
0
void
rtems_rtl_alloc_indirect_new (rtems_rtl_alloc_tag_t tag,
                              rtems_rtl_ptr_t*      handle,
                              size_t                size)
{
  rtems_rtl_data_t* rtl = rtems_rtl_lock ();

  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
  {
    if (!rtems_rtl_ptr_null (handle))
      printf ("rtl: alloc: inew: %s handle=%p: not null\n",
              rtems_rtl_trace_tag_label (tag), handle);
    printf ("rtl: alloc: inew: %s handle=%p size=%zd\n",
            rtems_rtl_trace_tag_label (tag), handle, size);
  }

  if (rtl)
  {
    rtems_rtl_alloc_data_t* allocator = &rtl->allocator;
    handle->pointer = rtems_rtl_alloc_new (tag, size, false);
    if (!rtems_rtl_ptr_null (handle))
      rtems_chain_append_unprotected (&allocator->indirects[tag],
                                      &handle->node);
  }

  rtems_rtl_unlock ();
}
Exemplo n.º 2
0
void _Malloc_Deferred_free( void *p )
{
  rtems_interrupt_lock_context lock_context;

  rtems_interrupt_lock_acquire( &_Malloc_GC_lock, &lock_context );
  rtems_chain_append_unprotected( &_Malloc_GC_list, (rtems_chain_node *) p );
  rtems_interrupt_lock_release( &_Malloc_GC_lock, &lock_context );
}
Exemplo n.º 3
0
rtems_status_code rtems_termios_device_install(
  const char                         *device_file,
  rtems_device_major_number           major,
  rtems_device_minor_number           minor,
  const rtems_termios_device_handler *handler,
  void                               *context
)
{
  rtems_status_code          sc;
  rtems_termios_device_node *new_device_node;
  rtems_termios_device_node *existing_device_node;

  new_device_node = malloc(sizeof(*new_device_node));
  if (new_device_node == NULL) {
    return RTEMS_NO_MEMORY;
  }

  new_device_node->major = major;
  new_device_node->minor = minor;
  new_device_node->handler = handler;
  new_device_node->context = context;
  new_device_node->tty = NULL;

  sc = rtems_semaphore_obtain(
    rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
  if (sc != RTEMS_SUCCESSFUL) {
    free(new_device_node);
    return RTEMS_INCORRECT_STATE;
  }

  existing_device_node = rtems_termios_find_device_node (major, minor);
  if (existing_device_node != NULL) {
    free(new_device_node);
    rtems_semaphore_release (rtems_termios_ttyMutex);
    return RTEMS_RESOURCE_IN_USE;
  }

  if (device_file != NULL) {
    sc = rtems_io_register_name (device_file, major, minor);
    if (sc != RTEMS_SUCCESSFUL) {
      free(new_device_node);
      rtems_semaphore_release (rtems_termios_ttyMutex);
      return RTEMS_UNSATISFIED;
    }
  }

  rtems_chain_append_unprotected(
    &rtems_termios_devices, &new_device_node->node);

  rtems_semaphore_release (rtems_termios_ttyMutex);

  return RTEMS_SUCCESSFUL;
}
Exemplo n.º 4
0
static void printer_task_append_buffer(
  rtems_printer_task_context *ctx,
  rtems_chain_control        *chain,
  printer_task_buffer        *buffer
)
{
  rtems_interrupt_lock_context lock_context;

  printer_task_acquire( ctx, &lock_context );
  rtems_chain_append_unprotected( chain, &buffer->node );
  printer_task_release( ctx, &lock_context );
}
Exemplo n.º 5
0
static void test_chain_node_count(void)
{
  rtems_chain_control chain;
  rtems_chain_node nodes[3];
  size_t count;
  size_t i;

  puts( "INIT - Verify rtems_chain_node_count_unprotected" );

  rtems_chain_initialize_empty( &chain );
  count = rtems_chain_node_count_unprotected( &chain );
  rtems_test_assert( count == 0 );

  for (i = 0; i < RTEMS_ARRAY_SIZE( nodes ); ++i) {
    rtems_chain_append_unprotected( &chain, &nodes[i] );
    count = rtems_chain_node_count_unprotected( &chain );
    rtems_test_assert( count == i + 1 );
  }
}
Exemplo n.º 6
0
static void bsp_interrupt_server_trigger(void *arg)
{
  rtems_interrupt_lock_context lock_context;
  bsp_interrupt_server_entry *e = arg;

  bsp_interrupt_vector_disable(e->vector);

  rtems_interrupt_lock_acquire(&bsp_interrupt_server_lock, &lock_context);

  if (rtems_chain_is_node_off_chain(&e->node)) {
    rtems_chain_append_unprotected(&bsp_interrupt_server_chain, &e->node);
  } else {
    ++bsp_interrupt_server_errors;
  }

  rtems_interrupt_lock_release(&bsp_interrupt_server_lock, &lock_context);

  rtems_event_system_send(bsp_interrupt_server_id, RTEMS_EVENT_SYSTEM_SERVER);
}
Exemplo n.º 7
0
static int register_subordinate_file_system(
  rtems_filesystem_mount_table_entry_t *mt_entry,
  const char *target
)
{
  int rv = 0;
  rtems_filesystem_eval_path_context_t ctx;
  int eval_flags = RTEMS_FS_PERMS_RWX
    | RTEMS_FS_FOLLOW_LINK;
  rtems_filesystem_location_info_t *currentloc =
    rtems_filesystem_eval_path_start( &ctx, target, eval_flags );

  if ( !rtems_filesystem_location_is_instance_root( currentloc ) ) {
    rtems_filesystem_location_info_t targetloc;
    rtems_filesystem_global_location_t *mt_point_node;

    rtems_filesystem_eval_path_extract_currentloc( &ctx, &targetloc );
    mt_point_node = rtems_filesystem_location_transform_to_global( &targetloc );
    mt_entry->mt_point_node = mt_point_node;
    rv = (*mt_point_node->location.mt_entry->ops->mount_h)( mt_entry );
    if ( rv == 0 ) {
      rtems_filesystem_mt_lock();
      rtems_chain_append_unprotected(
        &rtems_filesystem_mount_table,
        &mt_entry->mt_node
      );
      rtems_filesystem_mt_unlock();
    } else {
      rtems_filesystem_global_location_release( mt_point_node );
    }
  } else {
    rtems_filesystem_eval_path_error( &ctx, EBUSY );
    rv = -1;
  }

  rtems_filesystem_eval_path_cleanup( &ctx );

  return rv;
}
Exemplo n.º 8
0
static int register_root_file_system(
  rtems_filesystem_mount_table_entry_t *mt_entry
)
{
  int rv = 0;

  rtems_filesystem_mt_lock();
  if ( rtems_chain_is_empty( &rtems_filesystem_mount_table ) ) {
    rtems_chain_append_unprotected(
      &rtems_filesystem_mount_table,
      &mt_entry->mt_node
    );
  } else {
    errno = EINVAL;
    rv = -1;
  }
  rtems_filesystem_mt_unlock();

  if ( rv == 0 ) {
    rtems_filesystem_global_location_t *new_fs_root =
      rtems_filesystem_global_location_obtain( &mt_entry->mt_fs_root );
    rtems_filesystem_global_location_t *new_fs_current =
      rtems_filesystem_global_location_obtain( &mt_entry->mt_fs_root );

    rtems_filesystem_global_location_assign(
      &rtems_filesystem_root,
      new_fs_root
    );
    rtems_filesystem_global_location_assign(
      &rtems_filesystem_current,
      new_fs_current
    );
  }

  return rv;
}
Exemplo n.º 9
0
Arquivo: mmap.c Projeto: gedare/rtems
void *mmap(
  void *addr, size_t len, int prot, int flags, int fildes, off_t off
)
{
  struct stat     sb;
  mmap_mapping   *mapping;
  mmap_mapping   *current_mapping;
  ssize_t         r;
  rtems_libio_t  *iop;
  bool            map_fixed;
  bool            map_anonymous;
  bool            map_shared;
  bool            map_private;
  bool            is_shared_shm;
  int             err;

  map_fixed = (flags & MAP_FIXED) == MAP_FIXED;
  map_anonymous = (flags & MAP_ANON) == MAP_ANON;
  map_shared = (flags & MAP_SHARED) == MAP_SHARED;
  map_private = (flags & MAP_PRIVATE) == MAP_PRIVATE;

  /* Clear errno. */
  errno = 0;
  iop = NULL;

  if ( len == 0 ) {
    errno = EINVAL;
    return MAP_FAILED;
  }

  /*
   * We can provide read, write and execute because the memory in RTEMS does
   * not normally have protections but we cannot hide access to memory.
   */
  if ( prot == PROT_NONE ) {
    errno = ENOTSUP;
    return MAP_FAILED;
  }

  /*
   * We can not normally provide restriction of write access. Reject any
   * attempt to map without write permission, since we are not able to
   * prevent a write from succeeding.
   */
  if ( PROT_WRITE != (prot & PROT_WRITE) ) {
    errno = ENOTSUP;
    return MAP_FAILED;
  }

  /*
   * Anonymous mappings must have file descriptor set to -1 and the offset
   * set to 0. Shared mappings are not supported with Anonymous mappings at
   * this time
   */
  if ( map_anonymous && (fildes != -1 || off != 0 || map_shared) ) {
    errno = EINVAL;
    return MAP_FAILED;
  }

  /*
   * If MAP_ANON is declared without MAP_PRIVATE or MAP_SHARED,
   * force MAP_PRIVATE
   */
  if ( map_anonymous && !map_private && !map_shared ) {
    flags |= MAP_PRIVATE;
    map_private = true;
  }

  /* Check for supported flags */
  if ((flags & ~(MAP_SHARED | MAP_PRIVATE | MAP_FIXED | MAP_ANON)) != 0) {
    errno = EINVAL;
    return MAP_FAILED;
  }

  /* Either MAP_SHARED or MAP_PRIVATE must be defined, but not both */
  if ( map_shared ) {
    if ( map_private ) {
      errno = EINVAL;
      return MAP_FAILED;
    }
  } else if ( !map_private ) {
    errno = EINVAL;
    return MAP_FAILED;
  }

  /* Check for illegal addresses. Watch out for address wrap. */
  if ( map_fixed ) {
    if ((uintptr_t)addr & PAGE_MASK) {
      errno = EINVAL;
      return MAP_FAILED;
    }
    if ( addr == NULL ) {
      errno = EINVAL;
      return MAP_FAILED;
    }
    if (addr + len < addr) {
      errno = EINVAL;
      return MAP_FAILED;
    }
  }

  if ( !map_anonymous ) {
    /*
     * Get a stat of the file to get the dev + inode number and to make sure the
     * fd is ok. The normal libio calls cannot be used because we need to return
     * MAP_FAILED on error and they return -1 directly without coming back to
     * here.
     */
    if ( fstat( fildes, &sb ) < 0 ) {
      errno = EBADF;
      return MAP_FAILED;
    }

    /* fstat ensures we have a good file descriptor. Hold on to iop. */
    iop = rtems_libio_iop( fildes );

    /* Check the type of file we have and make sure it is supported. */
    if ( S_ISDIR( sb.st_mode ) || S_ISLNK( sb.st_mode )) {
      errno = ENODEV;
      return MAP_FAILED;
    }

    /* Check to see if the mapping is valid for a regular file. */
    if ( S_ISREG( sb.st_mode )
    /* FIXME: Should this be using strict inequality (>) comparisons? It would
     * be valid to map a region exactly equal to the st_size, e.g. see below. */
         && (( off >= sb.st_size ) || (( off + len ) >= sb.st_size ))) {
      errno = EOVERFLOW;
      return MAP_FAILED;
    }

    /* Check to see if the mapping is valid for other file/object types. */
    if ( !S_ISCHR( sb.st_mode ) && sb.st_size < off + len ) {
      errno = ENXIO;
      return MAP_FAILED;
    }

    /* Do not seek on character devices, pipes, sockets, or memory objects. */
    if ( S_ISREG( sb.st_mode ) || S_ISBLK( sb.st_mode ) ) {
      if ( lseek( fildes, off, SEEK_SET ) < 0 ) {
        return MAP_FAILED;
      }
    }

    /* cdevs do not provide private mappings of any kind. */
    if ( S_ISCHR( sb.st_mode ) && map_private ) {
      errno = EINVAL;
      return MAP_FAILED;
    }
  }

  /* Create the mapping */
  mapping = malloc( sizeof( mmap_mapping ));
  if ( !mapping ) {
    errno = ENOMEM;
    return MAP_FAILED;
  }
  memset( mapping, 0, sizeof( mmap_mapping ));
  mapping->len = len;
  mapping->flags = flags;

  if ( !map_anonymous ) {
    /*
     * HACK: We should have a better generic way to distinguish between
     * shm objects and other mmap'd files. We need to know at munmap time
     * if the mapping is to a shared memory object in order to refcnt shms.
     * We could do this by providing mmap in the file operations if needed.
     */
    if ( S_ISREG( sb.st_mode ) || S_ISBLK( sb.st_mode ) ||
         S_ISCHR( sb.st_mode ) || S_ISFIFO( sb.st_mode ) ||
         S_ISSOCK( sb.st_mode ) ) {
      is_shared_shm = false;
    } else {
      is_shared_shm = true;
    }
  } else {
    is_shared_shm = false;
  }

  if ( map_fixed ) {
    mapping->addr = addr;
  } else if ( map_private ) {
    /* private mappings of shared memory do not need special treatment. */
    is_shared_shm = false;
    posix_memalign( &mapping->addr, PAGE_SIZE, len );
    if ( !mapping->addr ) {
      free( mapping );
      errno = ENOMEM;
      return MAP_FAILED;
    }
  }

  /* MAP_FIXED is not supported for shared memory objects with MAP_SHARED. */
  if ( map_fixed && is_shared_shm ) {
    free( mapping );
    errno = ENOTSUP;
    return MAP_FAILED;
  }

  mmap_mappings_lock_obtain();

  if ( map_fixed ) {
    rtems_chain_node* node = rtems_chain_first (&mmap_mappings);
    while ( !rtems_chain_is_tail( &mmap_mappings, node )) {
      /*
       * If the map is fixed see if this address is already mapped. At this
       * point in time if there is an overlap in the mappings we return an
       * error. POSIX allows us to also return successfully by unmapping
       * the overlapping prior mappings.
       */
      current_mapping = (mmap_mapping*) node;
      if ( ( addr >= current_mapping->addr ) &&
           ( addr < ( current_mapping->addr + current_mapping->len )) ) {
        free( mapping );
        mmap_mappings_lock_release( );
        errno = ENXIO;
        return MAP_FAILED;
      }
      node = rtems_chain_next( node );
    }
  }

  /* Populate the data */
  if ( map_private ) {
    if ( !map_anonymous ) {
      /*
       * Use read() for private mappings. This updates atime as needed.
       * Changes to the underlying object will NOT be reflected in the mapping.
       * The underlying object can be removed while the mapping exists.
       */
      r = read( fildes, mapping->addr, len );

      if ( r != len ) {
        mmap_mappings_lock_release( );
        if ( !map_fixed ) {
          free( mapping->addr );
        }
        free( mapping );
        errno = ENXIO;
        return MAP_FAILED;
      }
    } else if ( !map_fixed ) {
      memset( mapping->addr, 0, len );
    }
  } else if ( map_shared ) {
    if ( is_shared_shm ) {
      /* FIXME: This use of implementation details is a hack. */
      mapping->shm = iop_to_shm( iop );
    }

    err = (*iop->pathinfo.handlers->mmap_h)(
        iop, &mapping->addr, len, prot, off );
    if ( err != 0 ) {
      mmap_mappings_lock_release( );
      free( mapping );
      return MAP_FAILED;
    }
  }

  rtems_chain_append_unprotected( &mmap_mappings, &mapping->node );

  mmap_mappings_lock_release( );

  return mapping->addr;
}
Exemplo n.º 10
0
int
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);

    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;
    }

    rtems_chain_set_off_chain (rtems_rfs_buffer_link(handle));
  }

  /*
   * Increase the reference count of the buffer.
   */
  rtems_rfs_buffer_refs_up (handle);
  rtems_chain_append_unprotected (&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;
}
Exemplo n.º 11
0
int
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_unprotected (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_unprotected (&fs->release);
            fs->release_count--;
            modified = false;
          }
          else
          {
            buffer = (rtems_rfs_buffer*)
              rtems_chain_get_unprotected (&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_unprotected (&fs->release_modified,
                                          rtems_rfs_buffer_link (handle));
          fs->release_modified_count++;
        }
        else
        {
          rtems_chain_append_unprotected (&fs->release,
                                          rtems_rfs_buffer_link (handle));
          fs->release_count++;
        }
      }
    }
    handle->buffer = NULL;
  }

  return rc;
}