static void test_chain_first_and_last(void) { rtems_chain_control chain; rtems_chain_node node1, node2; rtems_chain_node *cnode; rtems_chain_initialize_empty( &chain ); rtems_chain_append( &chain, &node1 ); rtems_chain_insert( &node1, &node2 ); puts( "INIT - Verify rtems_chain_is_first" ); cnode = rtems_chain_first(&chain); rtems_test_assert( rtems_chain_is_first( cnode ) ); puts( "INIT - Verify rtems_chain_is_last" ); cnode = rtems_chain_last(&chain); rtems_test_assert( rtems_chain_is_last( cnode ) ); cnode = rtems_chain_get_first_unprotected( &chain ); rtems_test_assert( cnode == &node1 ); cnode = rtems_chain_first( &chain ); rtems_test_assert( cnode == &node2 ); cnode = rtems_chain_last( &chain ); rtems_test_assert( cnode == &node2 ); }
bool rtems_rtl_obj_add_section (rtems_rtl_obj_t* obj, int section, const char* name, size_t size, off_t offset, uint32_t alignment, int link, int info, uint32_t flags) { rtems_rtl_obj_sect_t* sect = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, sizeof (rtems_rtl_obj_sect_t), true); if (!sect) { rtems_rtl_set_error (ENOMEM, "adding allocated section"); return false; } sect->section = section; sect->name = rtems_rtl_strdup (name); sect->size = size; sect->offset = offset; sect->alignment = alignment; sect->link = link; sect->info = info; sect->flags = flags; sect->base = NULL; rtems_chain_append (&obj->sections, §->node); if (rtems_rtl_trace (RTEMS_RTL_TRACE_SECTION)) printf ("rtl: sect: %-2d: %s\n", section, name); return true; }
static void bdbuf_tests_task_0_test_7 (bdbuf_task_control* tc) { rtems_status_code sc; bool passed; int i; rtems_bdbuf_buffer* bd; rtems_chain_control buffers; dev_t device; /* * 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); device = rtems_filesystem_make_dev_t (tc->major, tc->minor); /* * 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 (device, i, &bd); if (!bdbuf_test_print_sc (sc, true)) passed = false; rtems_chain_append (&buffers, &bd->link); } for (i = 0; (i < 5) && 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) { bdbuf_test_printf ("%s: rtems_bdbuf_syncdev[%d:%d]: ", tc->name, i, rtems_filesystem_dev_major_t (device), rtems_filesystem_dev_minor_t (device)); passed = bdbuf_test_print_sc (rtems_bdbuf_syncdev (device), true); } tc->passed = passed; tc->test = 0; }
static rtems_rap_app_t* rtems_rap_app_alloc (void) { rtems_rap_app_t* app = malloc (sizeof (rtems_rap_app_t)); memset (app, 0, sizeof (rtems_rap_app_t)); rtems_chain_append (&rap_.apps, &app->node); return app; }
static void rtems_rtl_symbol_global_insert (rtems_rtl_symbols_t* symbols, rtems_rtl_obj_sym_t* symbol) { uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name); rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets], &symbol->node); }
static void test_chain_with_empty_check(void) { rtems_chain_control chain; rtems_chain_node a; rtems_chain_node b; rtems_chain_node *p; bool empty; puts( "INIT - Verify rtems_chain_append_with_empty_check" ); rtems_chain_initialize_empty( &chain ); empty = rtems_chain_append_with_empty_check( &chain, &a ); rtems_test_assert( empty ); empty = rtems_chain_append_with_empty_check( &chain, &a ); rtems_test_assert( !empty ); puts( "INIT - Verify rtems_chain_prepend_with_empty_check" ); rtems_chain_initialize_empty( &chain ); empty = rtems_chain_prepend_with_empty_check( &chain, &a ); rtems_test_assert( empty ); empty = rtems_chain_prepend_with_empty_check( &chain, &a ); rtems_test_assert( !empty ); empty = rtems_chain_prepend_with_empty_check( &chain, &b ); rtems_test_assert( !empty ); puts( "INIT - Verify rtems_chain_get_with_empty_check" ); rtems_chain_initialize_empty( &chain ); empty = rtems_chain_get_with_empty_check( &chain, &p ); rtems_test_assert( empty ); rtems_chain_append( &chain, &a ); rtems_chain_append( &chain, &b ); empty = rtems_chain_get_with_empty_check( &chain, &p ); rtems_test_assert( !empty ); rtems_test_assert( p == &a ); empty = rtems_chain_get_with_empty_check( &chain, &p ); rtems_test_assert( empty ); rtems_test_assert( p == &b ); }
static void bsp_interrupt_server_trigger(void *arg) { bsp_interrupt_server_entry *e = arg; bsp_interrupt_vector_disable(e->vector); if (e->node.next == NULL) { rtems_chain_append(&bsp_interrupt_server_chain, &e->node); } else { ++bsp_interrupt_server_errors; } rtems_event_send(bsp_interrupt_server_id, BSP_INTERRUPT_EVENT); }
rtems_task Init( rtems_task_argument ignored ) { rtems_chain_control chain1; rtems_chain_node *p; test_node node1, node2; int id; TEST_BEGIN(); puts( "Init - Initialize chain empty" ); rtems_chain_initialize_empty( &chain1 ); /* verify that the chain append and insert work */ puts( "INIT - Verify rtems_chain_insert" ); node1.id = 1; node2.id = 2; rtems_chain_append( &chain1, &node1.Node ); rtems_chain_insert( &node1.Node, &node2.Node ); for ( p = rtems_chain_first(&chain1), id = 1 ; !rtems_chain_is_tail(&chain1, p) ; p = p->next , id++ ) { test_node *t = (test_node *)p; if ( id > 2 ) { puts( "INIT - TOO MANY NODES ON CHAIN" ); rtems_test_exit(0); } if ( t->id != id ) { puts( "INIT - ERROR ON CHAIN ID MISMATCH" ); rtems_test_exit(0); } } test_chain_first_and_last(); test_chain_with_empty_check(); test_chain_with_notification(); test_chain_get_with_wait(); test_chain_control_layout(); test_chain_control_initializer(); test_chain_node_count(); test_chain_insert_ordered(); test_chain_iterator(); TEST_END(); rtems_test_exit(0); }
static rtems_rtl_unresolv_block_t* rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved_t* unresolved) { /* * The block header contains a record. */ size_t size = (sizeof(rtems_rtl_unresolv_block_t) + (sizeof(rtems_rtl_unresolv_rec_t) * (unresolved->block_recs - 1))); rtems_rtl_unresolv_block_t* block = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_EXTERNAL, size, true); if (block) rtems_chain_append (&unresolved->blocks, &block->link); else rtems_rtl_set_error (ENOMEM, "no memory for unresolved block"); return block; }
/* * This routine installs one of multiple ISRs for the general purpose * inerrupt. */ rtems_isr_entry set_EE_vector( rtems_isr_entry handler, /* isr routine */ rtems_vector_number vector /* vector number */ ) { uint16_t vec_idx = vector - Score_IRQ_First; uint32_t index; assert (Nodes_Used < NUM_LIRQ_HANDLERS); /* * If we have already installed this handler for this vector, then * just reset it. */ for ( index=0 ; index <= Nodes_Used ; index++ ) { if ( ISR_Nodes[index].vector == vector && ISR_Nodes[index].handler == handler ) return NULL; } /* * Doing things in this order makes them more atomic */ Nodes_Used++; index = Nodes_Used - 1; ISR_Nodes[index].handler = handler; ISR_Nodes[index].vector = vector; /* printf( "Vector Index: %04x, Vector: %d (%x)\n", vec_idx, vector, vector); */ rtems_chain_append( &ISR_Array[vec_idx], &ISR_Nodes[index].Node ); /* * Unmask the interrupt. */ unmask_irq( vec_idx ); return NULL; }
void malloc_deferred_free( void *pointer ) { rtems_chain_append(&RTEMS_Malloc_GC_list, (rtems_chain_node *)pointer); }
int 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; }
void *mmap( void *addr, size_t len, int prot, int flags, int fildes, off_t off ) { struct stat sb; mmap_mapping* mapping; ssize_t r; /* * Clear errno. */ errno = 0; /* * 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; } if ( len == 0 ) { errno = EINVAL; return MAP_FAILED; } /* * 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; } /* * 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 = EINVAL; return MAP_FAILED; } /* * Check to see if the mapping is valid for the file. */ if ( S_ISREG( sb.st_mode ) && (( off >= sb.st_size ) || (( off + len ) >= sb.st_size ))) { errno = EOVERFLOW; return MAP_FAILED; } /* * Obtain the mmap lock. Sets errno on failure. */ if ( !mmap_mappings_lock_obtain( ) ) return MAP_FAILED; if (( flags & MAP_FIXED ) == 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. */ mapping = (mmap_mapping*) node; if ( ( addr >= mapping->addr ) && ( addr < ( mapping->addr + mapping->len )) ) { mmap_mappings_lock_release( ); errno = ENXIO; return MAP_FAILED; } node = rtems_chain_next( node ); } } mapping = malloc( sizeof( mmap_mapping )); if ( !mapping ) { mmap_mappings_lock_release( ); errno = ENOMEM; return NULL; } memset( mapping, 0, sizeof( mmap_mapping )); mapping->len = len; mapping->flags = flags; if (( flags & MAP_FIXED ) != MAP_FIXED ) { mapping->addr = malloc( len ); if ( !mapping->addr ) { mmap_mappings_lock_release( ); free( mapping ); errno = ENOMEM; return MAP_FAILED; } /* * Do not seek on character devices, pipes or sockets. */ if ( S_ISREG( sb.st_mode ) || S_ISBLK( sb.st_mode ) ) { if ( lseek( fildes, off, SEEK_SET ) < 0 ) { mmap_mappings_lock_release( ); free( mapping->addr ); free( mapping ); return MAP_FAILED; } } } r = read( fildes, mapping->addr, len ); if ( r != len ) { mmap_mappings_lock_release( ); free( mapping->addr ); free( mapping ); errno = ENXIO; return MAP_FAILED; } rtems_chain_append( &mmap_mappings, &mapping->node ); mmap_mappings_lock_release( ); return mapping->addr; }
/** * Get all the blocks in the pool and hold them. Wake the master to tell it was * have the buffers then wait for the master to tell us to release them. */ static void bdbuf_tests_task_0_test_4 (bdbuf_task_control* tc) { rtems_status_code sc; bool passed; size_t i; rtems_bdbuf_buffer* bd; rtems_chain_control buffers; size_t num = bdbuf_test_buffer_count (); /* * 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 < num) && passed; i++) { bdbuf_test_printf ("%s: rtems_bdbuf_read[%d]: ", tc->name, i); sc = rtems_bdbuf_read (tc->dd, i, &bd); if (!bdbuf_test_print_sc (sc, true)) passed = false; rtems_chain_append (&buffers, &bd->link); } /* * Wake the master to tell it we have the buffers. */ bdbuf_send_wait_event (tc->name, "wake master", tc->master); if (passed) { bdbuf_sleep (250); bdbuf_set_disk_driver_watch (tc, num / 2); /* * Release half the buffers, wait 500msecs then release the * remainder. This tests the swap out timer on each buffer. */ bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[0]: unblocks task 1\n", tc->name); bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers); sc = rtems_bdbuf_release_modified (bd); bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[0]: ", tc->name); passed = bdbuf_test_print_sc (sc, true); if (passed) { for (i = 1; (i < (num / 2)) && passed; i++) { bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: " \ "unblocks task 1\n", tc->name, i); bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers); sc = rtems_bdbuf_release_modified (bd); bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ", tc->name, i); passed = bdbuf_test_print_sc (sc, true); if (!passed) break; } if (passed) { passed = bdbuf_disk_driver_watch_wait (tc, BDBUF_SECONDS (5)); if (passed) { bdbuf_sleep (500); bdbuf_set_disk_driver_watch (tc, num / 2); for (i = 0; (i < (num / 2)) && passed; i++) { bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ", tc->name, i + (num / 2)); bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers); passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd), true); if (!passed) break; } passed = bdbuf_disk_driver_watch_wait (tc, BDBUF_SECONDS (5)); if (passed) { if (!rtems_chain_is_empty (&buffers)) { passed = false; bdbuf_test_printf ("%s: buffer chain not empty\n", tc->name); } } } } } } tc->passed = passed; tc->test = 0; }
/** * Get the blocks 0 -> 4 and hold them. Wake the master to tell it was have the * buffers then wait for the master to tell us to release a single buffer. * Task 1 will be block waiting for each buffer. It is a higher priority. */ static void bdbuf_tests_task_0_test_2 (bdbuf_task_control* tc) { rtems_status_code sc; bool passed; int i; rtems_bdbuf_buffer* bd; rtems_chain_control buffers; /* * Set task control's passed to false to handle a timeout. */ tc->passed = false; passed = true; /* * 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_get[%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); } /* * Wake the master to tell it we have the buffers. */ bdbuf_send_wait_event (tc->name, "wake master", tc->master); if (passed) { /* * For each buffer we hold wait until the master wakes us * and then return it. Task 2 will block waiting for this * buffer. It is a higher priority task. */ for (i = 0; (i < 5) && passed; i++) { sc = bdbuf_wait (tc->name, BDBUF_SECONDS (5)); if (sc != RTEMS_SUCCESSFUL) { bdbuf_test_printf ("%s: wait failed: ", tc->name); bdbuf_test_print_sc (sc, true); passed = false; break; } else { bdbuf_test_printf ("%s: rtems_bdbuf_release[%d]: unblocks task 1\n", tc->name, i); bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers); sc = rtems_bdbuf_release (bd); bdbuf_test_printf ("%s: rtems_bdbuf_release[%d]: ", tc->name, i); if (!bdbuf_test_print_sc (sc, true)) { passed = false; break; } } } } tc->passed = passed; tc->test = 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; }
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; }
static void test_chain_with_notification(void) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_chain_control chain; rtems_chain_node a; rtems_chain_node b; rtems_chain_node *p = (rtems_chain_node *) 1; rtems_event_set out = 0; puts( "INIT - Verify rtems_chain_append_with_notification" ); rtems_chain_initialize_empty( &chain ); sc = rtems_chain_append_with_notification( &chain, &a, rtems_task_self(), EVENT ); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); sc = rtems_chain_get_with_wait( &chain, EVENT, TIMEOUT, &p ); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); rtems_test_assert( p == &a ); rtems_chain_initialize_empty( &chain ); rtems_chain_append( &chain, &b ); sc = rtems_chain_append_with_notification( &chain, &a, rtems_task_self(), EVENT ); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); rtems_test_assert( p == &a ); puts( "INIT - Verify rtems_chain_prepend_with_notification" ); rtems_chain_initialize_empty( &chain ); sc = rtems_chain_prepend_with_notification( &chain, &a, rtems_task_self(), EVENT ); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); sc = rtems_chain_get_with_wait( &chain, EVENT, TIMEOUT, &p ); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); rtems_test_assert( p == &a ); rtems_chain_prepend( &chain, &b ); sc = rtems_chain_prepend_with_notification( &chain, &a, rtems_task_self(), EVENT ); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); rtems_test_assert( p == &a ); puts( "INIT - Verify rtems_chain_prepend_with_notification" ); puts( "INIT - Verify rtems_chain_get_with_notification" ); rtems_chain_initialize_empty( &chain ); rtems_chain_append( &chain, &b ); rtems_chain_append( &chain, &a ); sc = rtems_chain_get_with_notification(&chain, rtems_task_self(), EVENT, &p); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); rtems_test_assert( p == &b ); sc = rtems_chain_get_with_notification(&chain, rtems_task_self(), EVENT, &p); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); rtems_test_assert( p == &a ); sc = rtems_event_receive( EVENT, RTEMS_EVENT_ALL | RTEMS_WAIT, TIMEOUT, &out ); rtems_test_assert( sc == RTEMS_SUCCESSFUL ); rtems_test_assert( out == EVENT ); }
/* * Create an IMFS filesystem node of an arbitrary type that is NOT * the root directory node. */ 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; /* * 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 */ switch (type) { case IMFS_DIRECTORY: rtems_chain_initialize_empty(&node->info.directory.Entries); break; case IMFS_HARD_LINK: node->info.hard_link.link_node = info->hard_link.link_node; break; case IMFS_SYM_LINK: node->info.sym_link.name = info->sym_link.name; break; case IMFS_DEVICE: node->info.device.major = info->device.major; node->info.device.minor = info->device.minor; break; case IMFS_LINEAR_FILE: node->info.linearfile.size = 0; node->info.linearfile.direct = 0; case 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; break; case IMFS_FIFO: node->info.fifo.pipe = NULL; break; default: assert(0); break; } /* * This node MUST have a parent, so put it in that directory list. */ parent = parent_loc->node_access; fs_info = parent_loc->mt_entry->fs_info; node->Parent = parent; node->st_ino = ++fs_info->ino_count; rtems_chain_append( &parent->info.directory.Entries, &node->Node ); return node; }
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; }
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 (&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 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 for node_type_h */ if (!loc.ops->node_type_h) { errno = ENOTSUP; goto cleanup_and_bail; } /* * 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 ){ errno = ENOTSUP; goto cleanup_and_bail; } 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 */ if ( loc.ops->unmount_h ) { 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; }