Beispiel #1
0
int memfile_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;

  /*
   * Take the node out of the parent's chain that contains this node
   */

  if ( the_jnode->Parent != NULL ) {
    rtems_chain_extract( (rtems_chain_node *) the_jnode );
    the_jnode->Parent = NULL;
  }

  /*
   * Decrement the link counter and see if we can free the space.
   */

  the_jnode->st_nlink--;
  IMFS_update_ctime( the_jnode );

  return memfile_check_rmnod( the_jnode );
}
Beispiel #2
0
int rtems_aio_remove_req (rtems_chain_control *chain, struct aiocb *aiocbp)
{
  if (rtems_chain_is_empty (chain))
    return AIO_ALLDONE;

  rtems_chain_node *node = rtems_chain_first (chain);
  rtems_aio_request *current;
  
  current = (rtems_aio_request *) node;

  while (!rtems_chain_is_tail (chain, node) && current->aiocbp != aiocbp) {
    node = rtems_chain_next (node);
    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;
}
Beispiel #3
0
static void
rtems_rtl_unresolved_compact (void)
{
    rtems_rtl_unresolved_t* unresolved = rtems_rtl_unresolved ();
    if (unresolved)
    {
        /*
         * Iterate backwards over the blocks removing any used records. A block is
         * compacted moving up the block.
         */
        rtems_chain_node* node = rtems_chain_last (&unresolved->blocks);
        while (!rtems_chain_is_head (&unresolved->blocks, node))
        {
            rtems_chain_node* prev = rtems_chain_previous (node);
            rtems_rtl_unresolv_block_t* block = (rtems_rtl_unresolv_block_t*) node;
            rtems_rtl_unresolv_rec_t* rec = rtems_rtl_unresolved_rec_first (block);

            while (!rtems_rtl_unresolved_rec_is_last (block, rec))
            {
                bool next = true;

                if (rec->type == rtems_rtl_unresolved_name)
                {
                    if (rec->rec.name.refs == 0)
                    {
                        size_t name_recs = rtems_rtl_unresolved_name_recs (rec->rec.name.name);
                        rtems_rtl_unresolved_clean_block (block, rec, name_recs,
                                                          unresolved->block_recs);
                        next = false;
                    }
                }
                else if (rec->type == rtems_rtl_unresolved_reloc)
                {
                    if (!rec->rec.reloc.obj)
                    {
                        rtems_rtl_unresolved_clean_block (block, rec, 1,
                                                          unresolved->block_recs);
                        next = false;
                    }
                }

                if (next)
                    rec = rtems_rtl_unresolved_rec_next (rec);
            }

            if (block->recs == 0)
            {
                rtems_chain_extract (node);
                free (block);
            }

            node = prev;
        }
    }
}
Beispiel #4
0
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 );
}
Beispiel #5
0
static void
rtems_rap_app_free (rtems_rap_app_t* app)
{
    if (app->handle)
    {
        dlclose (app->handle);
        app->handle = NULL;
    }

    if (!rtems_chain_is_node_off_chain (&app->node))
        rtems_chain_extract (&app->node);
}
Beispiel #6
0
void
rtems_rtl_obj_erase_sections (rtems_rtl_obj_t* obj)
{
  rtems_chain_node* node = rtems_chain_first (&obj->sections);
  while (!rtems_chain_is_tail (&obj->sections, node))
  {
    rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
    rtems_chain_node*     next_node = rtems_chain_next (node);
    rtems_chain_extract (node);
    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) sect->name);
    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, sect);
    node = next_node;
  }
}
Beispiel #7
0
void rtems_aio_remove_fd (rtems_aio_request_chain *r_chain)
{
  rtems_chain_control *chain;
  rtems_chain_node *node;
  chain = &r_chain->perfd;
  node = rtems_chain_first (chain);
  
  while (!rtems_chain_is_tail (chain, node))
    {
      rtems_chain_extract (node);
      rtems_aio_request *req = (rtems_aio_request *) node;
      node = rtems_chain_next (node);
      req->aiocbp->error_code = ECANCELED;
      req->aiocbp->return_value = -1;
      free (req);
    }
}
Beispiel #8
0
void mpc55xx_edma_release_channel(edma_channel_context *ctx)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  unsigned channel_index = edma_channel_index_of_tcd(ctx->edma_tcd);

  mpc55xx_edma_release_channel_by_tcd(ctx->edma_tcd);
  rtems_chain_extract(&ctx->node);

  sc = rtems_interrupt_handler_remove(
    MPC55XX_IRQ_EDMA(channel_index),
    edma_interrupt_handler,
    ctx
  );
  if (sc != RTEMS_SUCCESSFUL) {
    bsp_fatal(MPC55XX_FATAL_EDMA_IRQ_REMOVE);
  }
}
Beispiel #9
0
void
rtems_rtl_symbol_obj_erase (rtems_rtl_obj_t* obj)
{
  rtems_rtl_symbol_obj_erase_local (obj);
  if (obj->global_table)
  {
    rtems_rtl_obj_sym_t* sym;
    size_t               s;
    for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
        if (!rtems_chain_is_node_off_chain (&sym->node))
          rtems_chain_extract (&sym->node);
    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
    obj->global_table = NULL;
    obj->global_size = 0;
    obj->global_syms = 0;
  }
}
Beispiel #10
0
bool
rtems_rtl_obj_free (rtems_rtl_obj_t* obj)
{
  if (obj->users || ((obj->flags & RTEMS_RTL_OBJ_LOCKED) != 0))
  {
    rtems_rtl_set_error (EINVAL, "cannot free obj still in use");
    return false;
  }
  if (!rtems_chain_is_node_off_chain (&obj->link))
    rtems_chain_extract (&obj->link);
  rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base,
                              &obj->data_base, &obj->bss_base);
  rtems_rtl_symbol_obj_erase (obj);
  rtems_rtl_obj_free_names (obj);
  if (obj->sec_num)
    free (obj->sec_num);
  if (obj->detail)
    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*)obj->detail);
  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj);
  return true;
}
Beispiel #11
0
/**
 * 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*
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;
}
Beispiel #12
0
int
rtems_bsd_rc_conf_service_remove(const char* name)
{
  rtems_chain_node*       node = rtems_chain_first(&services);
  const rtems_chain_node* tail = rtems_chain_tail(&services);

  while (node != tail) {
    service* srv = (service*) node;

    if (strcasecmp(name, srv->name) == 0) {
      rtems_chain_extract(&srv->node);
      free((void*) srv->control);
      free((void*) srv->name);
      free(srv);
      return 0;
    }

    node = rtems_chain_next(node);
  }

  errno = ENOENT;
  return -1;
}
Beispiel #13
0
int aio_cancel(int fildes, struct aiocb  *aiocbp)
{
  rtems_chain_control *idle_req_chain = &aio_request_queue.idle_req;
  rtems_chain_control *work_req_chain = &aio_request_queue.work_req;
  rtems_aio_request_chain *r_chain;
  int result;
  
  pthread_mutex_lock (&aio_request_queue.mutex);

  if (fcntl (fildes, F_GETFD) < 0) {
    pthread_mutex_unlock(&aio_request_queue.mutex);
    rtems_set_errno_and_return_minus_one (EBADF);
  }

  /* if aiocbp is NULL remove all request for given file descriptor */
  if (aiocbp == NULL) {
    AIO_printf ("Cancel all requests\n");        
         
    r_chain = rtems_aio_search_fd (work_req_chain, fildes, 0);
    if (r_chain == NULL) {
      AIO_printf ("Request chain not on [WQ]\n");

      if (!rtems_chain_is_empty (idle_req_chain)) {
        r_chain = rtems_aio_search_fd (idle_req_chain, fildes, 0);
        if (r_chain == NULL) {
          pthread_mutex_unlock(&aio_request_queue.mutex);
          return AIO_ALLDONE;
        }

        AIO_printf ("Request chain on [IQ]\n");

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

    AIO_printf ("Request chain on [WQ]\n");

    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 {
    AIO_printf ("Cancel request\n");

    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 (work_req_chain, fildes, 0);
    if (r_chain == NULL) {
      if (!rtems_chain_is_empty (idle_req_chain)) {
        r_chain = rtems_aio_search_fd (idle_req_chain, fildes, 0);
        if (r_chain == NULL) { 
          pthread_mutex_unlock (&aio_request_queue.mutex);
          rtems_set_errno_and_return_minus_one (EINVAL);
        }      
           
        AIO_printf ("Request on [IQ]\n");                     
   
        result = rtems_aio_remove_req (&r_chain->perfd, aiocbp);
        pthread_mutex_unlock (&aio_request_queue.mutex);
        return result;
      } else {
        pthread_mutex_unlock (&aio_request_queue.mutex);
        return AIO_ALLDONE;
      }
    }  
      AIO_printf ("Request on [WQ]\n");
      
      pthread_mutex_lock (&r_chain->mutex);
      result = rtems_aio_remove_req (&r_chain->perfd, aiocbp);
      pthread_mutex_unlock (&r_chain->mutex);
      pthread_mutex_unlock (&aio_request_queue.mutex);
      return result;
  }
  return AIO_ALLDONE;
}
Beispiel #14
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 (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;
}
Beispiel #15
0
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 );

  /*
   * Take the node out of the parent's chain that contains this node
   */

  if ( the_jnode->Parent != NULL ) {
    rtems_chain_extract( (rtems_chain_node *) the_jnode );
    the_jnode->Parent = NULL;
  }

  /*
   * Decrement the link counter and see if we can free the space.
   */

  the_jnode->st_nlink--;
  IMFS_update_ctime( the_jnode );

  /*
   * The file cannot be open and the link must be less than 1 to free.
   */

  if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {

    /*
     * Is the rtems_filesystem_current is this node?
     */

    if ( rtems_filesystem_current.node_access == pathloc->node_access )
       rtems_filesystem_current.node_access = NULL;

    /*
     * Free memory associated with a memory file.
     */

    free( the_jnode );
  }

  return 0;

}
int
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);
      if (!rtems_rfs_block_size_equal (&handle->shared->size,
                                       &handle->shared->map.size))
        rtems_rfs_block_map_set_size (&handle->shared->map,
                                      &handle->shared->size);
    }
    
    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;
}
Beispiel #17
0
int
rtems_bsd_rc_conf_service_add(const char*               name,
                              const char*               control,
                              rtems_bsd_rc_conf_service entry)
{
  service* srv;
  char*    ctl = NULL;
  char*    s;
  char*    c;

  srv = malloc(sizeof(*srv));
  if (srv == NULL) {
    errno = ENOMEM;
    return -1;
  }

  memset(srv, 0, sizeof(*srv));

  srv->name = strdup(name);
  if (control != NULL) {
    ctl = strdup(control);
    srv->control = ctl;
  }
  srv->entry = entry;

  if (srv->name == NULL || (control != NULL && ctl == NULL)) {
    fprintf(stderr, "error: rc.conf: add service: no memory\n");
    free((void*) srv->control);
    free((void*) srv->name);
    free(srv);
    errno = ENOMEM;
    return -1;
  }

  if (control != NULL) {
    s = c = ctl;

    while (*c != '\0') {
      if (*c == ';') {
        *c = '\0';

        if (strncasecmp("before:", s, sizeof("before:") - 1) == 0) {
          if (srv->before == NULL) {
            srv->before = s + sizeof("before:") - 1;
            s = NULL;
          }
          else {
            fprintf(stderr, "error: rc.conf: add service: repeated 'before'\n");
            c = NULL;
          }
        }
        else if (strncasecmp("after:", s, sizeof("after:") - 1) == 0) {
          if (srv->after == NULL) {
            srv->after = s + sizeof("after:") - 1;
            s = NULL;
          }
          else {
            fprintf(stderr, "error: rc.conf: add service: repeated 'after'\n");
            c = NULL;
          }
        }
        else if (strncasecmp("require:", s, sizeof("require:") - 1) == 0) {
          if (srv->require == NULL) {
            srv->require = s + sizeof("require:") - 1;
            s = NULL;
          }
          else {
            fprintf(stderr, "error: rc.conf: add service: repeated 'require'\n");
            c = NULL;
          }
        }
        else {
          fprintf(stderr, "error: rc.conf: add service: unknown keyword: %s\n", s);
          c = NULL;
        }

        if (c == NULL) {
          free((void*) srv->control);
          free((void*) srv->name);
          free(srv);
          errno = EINVAL;
          return -1;
        }
      }
      else if (s == NULL) {
        s = c;
      }

      ++c;
    }

    if (s != NULL) {
      fprintf(stderr, "error: rc.conf: add service: no ';' found\n");
      free((void*) srv->control);
      free((void*) srv->name);
      free(srv);
      errno = EINVAL;
      return -1;
    }

    /*
     * Place on the services list. The node is removed before being inserted. If
     * there are competing positions the last position is used. As a result
     * handle 'after' before 'before'.
     */
    rtems_chain_prepend(&services, &srv->node);
  }
  else {
    /*
     * No control string, add the end.
     */
    rtems_chain_append(&services, &srv->node);
  }

  /*
   * After.
   */
  if (srv->after != NULL) {
    const char* cc = srv->after;
    while (*cc != '\0') {
      const char* cs = cc;
      size_t      l;
      while (*cc != ',' && *cc != '\0')
        ++cc;
      l = cc - cs;
      if (strncasecmp(cs, "last", l) == 0) {
        fprintf(stderr,
                "error: rc.conf: add service: 'last' in 'after': %s\n",
                control);
        rtems_chain_extract(&srv->node);
        free((void*) srv->control);
        free((void*) srv->name);
        free(srv);
        errno = EINVAL;
        return -1;
      }
      else if (strncasecmp(cs, "first", l) == 0) {
        /* already prepended */
      }
      else {
        rtems_chain_node* node = rtems_chain_first(&services);
        while (!rtems_chain_is_tail(&services, node)) {
          service* ss = (service*) node;
          if (ss != srv &&
              strlen(ss->name) == l && strncasecmp(ss->name, cs, l) == 0) {
            rtems_chain_extract(&srv->node);
            rtems_chain_insert(&ss->node, &srv->node);
            break;
          }
          node = rtems_chain_next(node);
        }
      }
    }
  }

  /*
   * Before.
   */
  if (srv->before != NULL) {
    const char* cc = srv->before;
    while (*cc != '\0') {
      const char* cs = cc;
      size_t      l;
      while (*cc != ',' && *cc != '\0')
        ++cc;
      l = cc - cs;
      if (strncasecmp(cs, "first", l) == 0) {
        fprintf(stderr, "error: rc.conf: add service: 'first' in 'before'\n");
        rtems_chain_extract(&srv->node);
        free((void*) srv->control);
        free((void*) srv->name);
        free(srv);
        errno = EINVAL;
        return -1;
      }
      else if (strncasecmp(cs, "last", l) == 0) {
        rtems_chain_extract(&srv->node);
        rtems_chain_append(&services, &srv->node);
      }
      else {
        rtems_chain_node* node = rtems_chain_first(&services);
        while (!rtems_chain_is_tail(&services, node)) {
          service* ss = (service*) node;
          if (strlen(ss->name) == l && strncasecmp(ss->name, cs, l) == 0) {
            rtems_chain_extract(&srv->node);
            if (rtems_chain_is_first(node))
              rtems_chain_prepend(&services, &srv->node);
            else {
              service* sp = (service*) rtems_chain_previous(node);
              rtems_chain_insert(&sp->node, &srv->node);
            }
            break;
          }
          node = rtems_chain_next(node);
        }
      }
    }
  }

  return 0;
}
Beispiel #18
0
static void *
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)) {

      AIO_printf ("Get new request from not empty chain\n");	
      node = rtems_chain_first (chain);
      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:
	AIO_printf ("read\n");
        result = pread (req->aiocbp->aio_fildes,
                        (void *) req->aiocbp->aio_buf,
                        req->aiocbp->aio_nbytes, req->aiocbp->aio_offset);
        break;

      case LIO_WRITE:
	AIO_printf ("write\n");
        result = pwrite (req->aiocbp->aio_fildes,
                         (void *) req->aiocbp->aio_buf,
                         req->aiocbp->aio_nbytes, req->aiocbp->aio_offset);
        break;
        
      case LIO_SYNC:
	AIO_printf ("sync\n");
      	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;
      
      AIO_printf ("Chain is empty [WQ], wait for work\n");
     
      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_printf ("Chain is empty [IQ], wait for work\n");	      

	      ++aio_request_queue.idle_threads;
	      --aio_request_queue.active_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) {
		AIO_printf ("Etimeout\n");
		--aio_request_queue.idle_threads;
		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_printf ("Work on idle\n");
	    --aio_request_queue.idle_threads;
	    ++aio_request_queue.active_threads;

	    node = rtems_chain_first (&aio_request_queue.idle_req);
	    rtems_chain_extract (node);

	    r_chain = (rtems_aio_request_chain *) node;
	    rtems_aio_move_to_work (r_chain);
	    
	  }
	}
      /* 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;
}
Beispiel #19
0
static void
bdbuf_tests_task_0_test_8 (bdbuf_task_control* tc)
{
  rtems_status_code   sc;
  bool                passed;
  int                 i;
  rtems_bdbuf_buffer* bd;
  rtems_chain_control buffers;
  rtems_chain_node*   node;
  rtems_chain_node*   pnode;

  /*
   * Set task control's passed to false to handle a timeout.
   */
  tc->passed = false;
  passed = true;

  /*
   * Clear any disk settings.
   */
  bdbuf_clear_disk_driver_watch (tc);
  bdbuf_set_disk_driver_action (tc, BDBUF_DISK_NOOP);

  /*
   * Get the blocks 0 -> 4 and hold them.
   */
  rtems_chain_initialize_empty (&buffers);

  for (i = 0; (i < 5) && passed; i++)
  {
    bdbuf_test_printf ("%s: rtems_bdbuf_read[%d]: ", tc->name, i);
    sc = rtems_bdbuf_get (tc->dd, i, &bd);
    if (!bdbuf_test_print_sc (sc, true))
      passed = false;

    rtems_chain_append (&buffers, &bd->link);
  }

  node = rtems_chain_tail (&buffers);
  node = node->previous;

  bd = (rtems_bdbuf_buffer*) node;
  pnode = node->previous;
  rtems_chain_extract (node);
  node = pnode;
  bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[4]: ", tc->name);
  passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd), true);

  bd = (rtems_bdbuf_buffer*) node;
  pnode = node->previous;
  rtems_chain_extract (node);
  node = pnode;
  bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[3]: ", tc->name);
  passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd), true);

  for (i = 0; (i < 3) && passed; i++)
  {
    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ",
                       tc->name, i);
    bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
    passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd),
                                  true);
  }

  if (passed)
  {
    /*
     * Check the block order.
     */
    bdbuf_set_disk_driver_action (tc, BDBUF_DISK_BLOCKS_INORDER);

    bdbuf_test_printf ("%s: rtems_bdbuf_syncdev[%d:%d]: checking order\n",
                       tc->name, i,
                       tc->major,
                       tc->minor);
    sc = rtems_bdbuf_syncdev (tc->dd);
    bdbuf_test_printf ("%s: rtems_bdbuf_syncdev[%d:%d]: ",
                       tc->name, i,
                       tc->major,
                       tc->minor);
    passed = bdbuf_test_print_sc (sc, true);
  }

  tc->passed = passed;
  tc->test = 0;
}
Beispiel #20
0
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 Unmount is supported by both filesystems.
     */

    if ( !fs_mount_loc->ops->unmount_h )
        rtems_set_errno_and_return_minus_one( ENOTSUP );

    if ( !fs_root_loc->ops->fsunmount_me_h )
        rtems_set_errno_and_return_minus_one( ENOTSUP );


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