/** * Creates a semaphore * * @param semaphore : pointer to variable which will receive handle of created semaphore * * @returns WWD_SUCCESS on success, WICED_ERROR otherwise */ wwd_result_t host_rtos_init_semaphore( /*@out@*/ host_semaphore_type_t* semaphore ) /*@modifies *semaphore@*/ { return ( tx_semaphore_create( semaphore, (char*) "", 0 ) == TX_SUCCESS ) ? WWD_SUCCESS : WWD_SEMAPHORE_ERROR; }
void tx_application_define(void *first_unused_memory) { CHAR *pointer; /* Create a byte memory pool from which to allocate the thread stacks. */ tx_byte_pool_create(&byte_pool_0, "byte pool 0", first_unused_memory, DEMO_BYTE_POOL_SIZE); /* Put system definition stuff in here, e.g. thread creates and other assorted create information. */ /* Allocate the stack for thread 0. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); /* Create the main thread. */ tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, pointer, DEMO_STACK_SIZE, 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START); /* Allocate the stack for thread 1. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); /* Create threads 1 and 2. These threads pass information through a ThreadX message queue. It is also interesting to note that these threads have a time slice. */ tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, pointer, DEMO_STACK_SIZE, 16, 16, 4, TX_AUTO_START); /* Allocate the stack for thread 2. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, pointer, DEMO_STACK_SIZE, 16, 16, 4, TX_AUTO_START); /* Allocate the stack for thread 3. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); /* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore. An interesting thing here is that both threads share the same instruction area. */ tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3, pointer, DEMO_STACK_SIZE, 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); /* Allocate the stack for thread 4. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4, pointer, DEMO_STACK_SIZE, 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); /* Allocate the stack for thread 5. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); /* Create thread 5. This thread simply pends on an event flag which will be set by thread_0. */ tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, pointer, DEMO_STACK_SIZE, 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); /* Allocate the stack for thread 6. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); /* Create threads 6 and 7. These threads compete for a ThreadX mutex. */ tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6, pointer, DEMO_STACK_SIZE, 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); /* Allocate the stack for thread 7. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7, pointer, DEMO_STACK_SIZE, 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); /* Allocate the message queue. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT); /* Create the message queue shared by threads 1 and 2. */ tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG)); /* Create the semaphore used by threads 3 and 4. */ tx_semaphore_create(&semaphore_0, "semaphore 0", 1); /* Create the event flags group used by threads 1 and 5. */ tx_event_flags_create(&event_flags_0, "event flags 0"); /* Create the mutex used by thread 6 and 7 without priority inheritance. */ tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); /* Allocate the memory for a small block pool. */ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT); /* Create a block memory pool to allocate a message buffer from. */ tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE); /* Allocate a block and release the block memory. */ tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT); /* Release the block back to the pool. */ tx_block_release(pointer); }
CM_Frame_Table * CM_Frame_Table::Allocate( CM_Mem *p_mem, CM_CONFIG *p_config, CM_PREFETCH_CALLBACK *p_prefetch_callback, CM_WRITE_CALLBACK *p_write_callback, CM_Stats *p_stats, void *p_callback_context, U32 num_page_frames, void *p_page_memory) { // Allocate CM_Frame_Table object CM_Frame_Table *p_frame_table = (CM_Frame_Table *)p_mem->Allocate(sizeof(CM_Frame_Table)); if (p_frame_table == 0) return 0; // Initialize table lists. LIST_INITIALIZE(&p_frame_table->m_list_waiting_to_flush); LIST_INITIALIZE(&p_frame_table->m_list_wait_frame); // Initialize each of our dummy frames. Each of our frame lists // is a dummy frame so that, when the last frame in the list points // to the head of the list, we can treat it as a frame without // having to check to see if we are pointing to the head of the list. p_frame_table->m_clock_list.Initialize(0, CM_PAGE_STATE_CLEAN); p_frame_table->m_dirty_clock_list.Initialize(0, CM_PAGE_STATE_DIRTY); // Save callbacks. p_frame_table->m_p_prefetch_callback = p_prefetch_callback; p_frame_table->m_p_write_callback = p_write_callback; p_frame_table->m_p_callback_context = p_callback_context; // Make sure the page size is a multiple of 8 for alignment. p_frame_table->m_page_size = ((p_config->page_size + 7) / 8) * 8; p_frame_table->m_num_pages_replaceable = 0; p_frame_table->m_num_pages_clock = 0; p_frame_table->m_num_pages_dirty_clock = 0; p_frame_table->m_num_pages_being_written = 0; p_frame_table->m_num_pages_working_set = 0; p_frame_table->m_p_clock_frame = 0; p_frame_table->m_p_dirty_clock_frame = 0; // Find out how much memory is available. // Leave this for debugging. Should be close to zero. U32 memory_available = p_mem->Memory_Available(); // Save number of page frames. p_frame_table->m_num_page_frames = num_page_frames; if (p_config->page_table_size) { // Linear mapping // Don't allocate more pages than specified in the config. if (p_frame_table->m_num_page_frames > p_config->page_table_size) p_frame_table->m_num_page_frames = p_config->page_table_size; } // Allocate array of page frames p_frame_table->m_p_page_frame_array = (char *)p_page_memory; // Allocate array of frames p_frame_table->m_p_frame_array = (CM_Frame *)p_mem->Allocate(sizeof(CM_Frame) * p_frame_table->m_num_page_frames); if (p_frame_table->m_p_frame_array == 0) return 0; // When m_p_clock_frame is zero, we know that the frame table is not yet initialized. p_frame_table->m_p_clock_frame = 0; // Initialize each frame CM_Frame *p_frame; for (U32 index = 0; index < p_frame_table->m_num_page_frames; index++) { // Point to the next frame. p_frame = p_frame_table->Get_Frame(index + 1); // Have the frame initialize itself. p_frame->Initialize(index + 1, CM_PAGE_STATE_CLEAN); CT_ASSERT((p_frame_table->Get_Frame(index + 1) == p_frame), CM_Frame_Table::Allocate); CT_ASSERT((p_frame->Get_Frame_Index() == (index + 1)), CM_Frame_Table::Allocate); // Make sure the list object is first in the frame. CT_ASSERT(((CM_Frame *)&p_frame->m_list == p_frame), CM_Frame_Table::Allocate); CT_ASSERT((p_frame->Is_Replaceable()), CM_Frame_Table::Allocate); // Initially, each frame is on the clock list LIST_INSERT_TAIL(&p_frame_table->m_clock_list.m_list, &p_frame->m_list); p_frame_table->m_num_pages_clock++; p_frame_table->m_num_pages_replaceable++; } // Initialize the clocks p_frame_table->m_p_clock_frame = p_frame; p_frame_table->m_p_dirty_clock_frame = &p_frame_table->m_dirty_clock_list; // Calculate dirty page writeback threshold from the percentage in the config file. p_frame_table->m_dirty_page_writeback_threshold = (p_frame_table->m_num_page_frames * p_config->dirty_page_writeback_threshold) / 100; // Calculate dirty page error threshold from the percentage in the config file. p_frame_table->m_dirty_page_error_threshold = (p_frame_table->m_num_page_frames * p_config->dirty_page_error_threshold) / 100; // Make sure the number of reserve pages is less than the number of pages in the cache. // This would only happen in a test environment where the cache size is small. p_frame_table->m_num_reserve_pages = p_config->num_reserve_pages; if (p_frame_table->m_num_reserve_pages > p_frame_table->m_num_pages_replaceable) // Make number of reserve pages less than number of pages in the cache. p_frame_table->m_num_reserve_pages = p_frame_table->m_num_pages_replaceable - (p_frame_table->m_num_pages_replaceable / 2); // Calculate the maximum number of dirty pages. U32 max_number_dirty_pages = p_frame_table->m_num_pages_replaceable - p_frame_table->m_num_reserve_pages; // Make sure the dirty page error threshold is less than the maximum number of dirty pages; // otherwise we will have a context waiting for a page to be cleaned, and it will // never happen. This would only occur in a test situation, where cache size is small. if (p_frame_table->m_dirty_page_error_threshold > max_number_dirty_pages) // Make dirty page error threshold less than max_number_dirty_pages. p_frame_table->m_dirty_page_error_threshold = max_number_dirty_pages - (max_number_dirty_pages / 2); // Make sure the writeback threshold is less than the dirty page error threshold. if (p_frame_table->m_dirty_page_writeback_threshold > p_frame_table->m_dirty_page_error_threshold) // Make dirty page writeback threshold less than dirty page error threshold. p_frame_table->m_dirty_page_writeback_threshold = p_frame_table->m_dirty_page_error_threshold - (p_frame_table->m_dirty_page_error_threshold / 2); // Initialize pointer to statistics object p_frame_table->m_p_stats = p_stats; #ifdef _WINDOWS // Initialize Windows mutex p_frame_table->m_mutex = CreateMutex( NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes, // pointer to security attributes // If TRUE, the calling thread requests immediate ownership of the mutex object. // Otherwise, the mutex is not owned. 0, // flag for initial ownership // If lpName is NULL, the event object is created without a name. NULL // LPCTSTR lpName // pointer to semaphore-object name ); if (p_frame_table->m_mutex == 0) { DWORD erc = GetLastError(); CT_Log_Error(CT_ERROR_TYPE_FATAL, "CM_Frame_Table::Allocate", "CreateMutex failed", erc, 0); return p_frame_table; } #else #ifdef THREADX // Initialize Threadx semaphore Status status = tx_semaphore_create(&p_frame_table->m_mutex, "CmMutex", 1); // initial count #else // Initialize Nucleus semaphore Status status = NU_Create_Semaphore(&p_frame_table->m_mutex, "CmMutex", 1, // initial count NU_FIFO); #endif if (status != OK) { CT_Log_Error(CT_ERROR_TYPE_FATAL, "CM_Frame_Table::Allocate", "NU_Create_Semaphore failed", status, 0); return p_frame_table; } #endif #ifdef _DEBUG Got_Mutex = 0; #endif // Return pointer to table object return p_frame_table; } // CM_Frame_Table::Allocate