void PionOneToOneScheduler::startup(void) { // lock mutex for thread safety boost::mutex::scoped_lock scheduler_lock(m_mutex); if (! m_is_running) { PION_LOG_INFO(m_logger, "Starting thread scheduler"); m_is_running = true; // make sure there are enough services initialized while (m_service_pool.size() < m_num_threads) { boost::shared_ptr<ServicePair> service_ptr(new ServicePair()); m_service_pool.push_back(service_ptr); } // schedule a work item for each service to make sure that it doesn't complete for (ServicePool::iterator i = m_service_pool.begin(); i != m_service_pool.end(); ++i) { keepRunning((*i)->first, (*i)->second); } // start multiple threads to handle async tasks for (boost::uint32_t n = 0; n < m_num_threads; ++n) { boost::shared_ptr<boost::thread> new_thread(new boost::thread( boost::bind(&PionScheduler::processServiceWork, this, boost::ref(m_service_pool[n]->first)) )); m_thread_pool.push_back(new_thread); } } }
void timer_dump () { usize_t index; scheduler_lock (); console_print ("\n"); console_print ("Summary\n"); console_print ("-------\n"); console_print (" Supported: %u\n", CONFIG_MAX_TIMER); console_print (" Allocated: %u\n", CONFIG_MAX_TIMER - dll_size (&g_free_timer)); console_print (" .BSS Used: %u\n", ((address_t)&g_bucket_firing - (address_t)g_timer_pool) + sizeof (g_bucket_firing)); console_print ("\n"); console_print ("Statistics\n"); console_print ("----------\n"); console_print (" No Timer: %u\n", g_statistics.notimer_); console_print (" Abnormal: %u\n", g_statistics.abnormal_); console_print (" Traversed: %u\n", g_statistics.traversed_); console_print (" Queue Full: %u\n", g_statistics.queue_full_); console_print ("\n"); console_print ("Bucket Details\n"); console_print ("--------------\n"); for (index = 0; index <= BUCKET_LAST_INDEX; ++ index) { console_print (" [%u]: hit (%u), redo (%u), timer held (%u)\n", index, g_buckets [index].hit_, g_buckets [index].redo_, dll_size (&g_buckets [index].dll_)); } console_print ("\n"); scheduler_unlock (); }
void mutex_dump () { if (is_in_interrupt ()) { return; } scheduler_lock (); console_print ("\n\n"); console_print ("Summary\n"); console_print ("-------\n"); console_print (" Supported: %u\n", CONFIG_MAX_MUTEX); console_print (" Allocated: %u\n", dll_size (&g_mutex_container.used_)); console_print (" .BSS Used: %u\n", ((address_t)&g_mutex_container - (address_t)g_mutex_pool) + sizeof (g_mutex_container)); console_print ("\n"); console_print ("Statistics\n"); console_print ("----------\n"); console_print (" No Object: %u\n", g_mutex_container.stats_noobj_); console_print ("\n"); console_print ("Mutex Details\n"); console_print ("-------------\n"); (void) dll_traverse (&g_mutex_container.used_, mutex_dump_for_each, 0); console_print ("\n"); scheduler_unlock (); }
void scheduler::join(void) { std::unique_lock<std::mutex> scheduler_lock(mutex); while (running) { // sleep until scheduler_has_stopped condition is signaled scheduler_has_stopped.wait(scheduler_lock); } }
void PionScheduler::join(void) { boost::mutex::scoped_lock scheduler_lock(m_mutex); while (m_is_running) { // sleep until scheduler_has_stopped condition is signaled m_scheduler_has_stopped.wait(scheduler_lock); } }
/* * net_buffer_lock * @fd: Networking buffer file descriptor. * This function will get the lock for net buffer file descriptor. */ static int32_t net_buffer_lock(void *fd) { #ifdef CONFIG_SEMAPHORE /* Obtain data lock for networking buffers. */ return semaphore_obtain(&((NET_BUFFER_FS *)fd)->lock, MAX_WAIT); #else /* Remove some compiler warnings. */ UNUSED_PARAM(fd); /* Lock scheduler. */ scheduler_lock(); /* Return success. */ return (SUCCESS); #endif } /* net_buffer_lock */
/* * console_lock * @fd: File descriptor for the console. * This function will get the lock for a given console. */ static int32_t console_lock(void *fd) { #ifdef CONFIG_SEMAPHORE /* Obtain data lock for this console. */ return semaphore_obtain(&((CONSOLE *)fd)->lock, MAX_WAIT); #else /* Remove some compiler warnings. */ UNUSED_PARAM(fd); /* Lock scheduler. */ scheduler_lock(); /* Return success. */ return (SUCCESS); #endif } /* console_lock */
/* * scheduler_task_remove * @tcb: Task control block that is needed to be removed. * This function removes a finished task from the global task list. Once * removed user can call scheduler_task_add to run a finished task. */ void scheduler_task_remove(TASK *tcb) { /* Lock the scheduler. */ scheduler_lock(); /* Task should be in finished state. */ ASSERT(tcb->state != TASK_FINISHED); #ifdef TASK_STATS /* Remove this task from global task list. */ sll_remove(&sch_task_list, tcb, OFFSETOF(TASK, next_global)); #endif /* TASK_STATS */ /* Enable scheduling. */ scheduler_unlock(); } /* scheduler_task_remove */
void PionSingleServiceScheduler::startup(void) { // lock mutex for thread safety boost::mutex::scoped_lock scheduler_lock(m_mutex); if (! m_is_running) { PION_LOG_INFO(m_logger, "Starting thread scheduler"); m_is_running = true; // schedule a work item to make sure that the service doesn't complete m_service.reset(); keepRunning(m_service, m_timer); // start multiple threads to handle async tasks for (boost::uint32_t n = 0; n < m_num_threads; ++n) { boost::shared_ptr<boost::thread> new_thread(new boost::thread( boost::bind(&PionScheduler::processServiceWork, this, boost::ref(m_service)) )); m_thread_pool.push_back(new_thread); } } }
void PionScheduler::shutdown(void) { // lock mutex for thread safety boost::mutex::scoped_lock scheduler_lock(m_mutex); if (m_is_running) { PION_LOG_INFO(m_logger, "Shutting down the thread scheduler"); while (m_active_users > 0) { // first, wait for any active users to exit PION_LOG_INFO(m_logger, "Waiting for " << m_active_users << " scheduler users to finish"); m_no_more_active_users.wait(scheduler_lock); } // shut everything down m_is_running = false; stopServices(); stopThreads(); finishServices(); finishThreads(); PION_LOG_INFO(m_logger, "The thread scheduler has shutdown"); // Make sure anyone waiting on shutdown gets notified m_scheduler_has_stopped.notify_all(); } else { // stop and finish everything to be certain that no events are pending stopServices(); stopThreads(); finishServices(); finishThreads(); // Make sure anyone waiting on shutdown gets notified // even if the scheduler did not startup successfully m_scheduler_has_stopped.notify_all(); } }
void scheduler::startup() { // lock mutex for thread safety std::lock_guard<std::mutex> scheduler_lock(mutex); if (!running) { STATICLIB_PION_LOG_INFO(log, "Starting thread scheduler"); running = true; // schedule a work item to make sure that the service doesn't complete asio_service.reset(); keep_running(asio_service, timer); // start multiple threads to handle async tasks for (uint32_t n = 0; n < num_threads; ++n) { std::unique_ptr<std::thread> new_thread(new std::thread([this]() { this->process_service_work(this->asio_service); this->thread_stop_hook(); })); thread_pool.emplace_back(std::move(new_thread)); } } }
/* * console_unregister * @console: Console data. * This function will unregister a console. */ void console_unregister(CONSOLE *console) { /* This could be a file descriptor chain, so destroy it. */ fs_destroy_chain((FD)&console->fs); #ifndef CONFIG_SEMAPHORE /* Lock the scheduler. */ scheduler_lock(); #else /* Obtain the global data lock. */ OS_ASSERT(semaphore_obtain(&console_data.lock, MAX_WAIT) != SUCCESS); /* Obtain the lock for the console needed to be unregistered. */ if (semaphore_obtain(&console->lock, MAX_WAIT) == SUCCESS) { #endif /* Resume all tasks waiting on this file descriptor. */ fd_handle_criteria((FD)console, NULL, FS_NODE_DELETED); #ifdef CONFIG_SEMAPHORE /* Delete the console lock. */ semaphore_destroy(&console->lock); #endif /* Just remove this console from console list. */ OS_ASSERT(sll_remove(&console_data.list, console, OFFSETOF(CONSOLE, fs.next)) != console); #ifdef CONFIG_SEMAPHORE } /* Release the global data lock. */ semaphore_release(&console_data.lock); #else /* Enable scheduling. */ scheduler_unlock(); #endif } /* console_unregister */
/* * sleep_ticks * @ticks: Number of ticks for which this task is needed to sleep. * This function sleeps/suspends the current task for the given number of system * ticks. */ void sleep_ticks(uint32_t ticks) { TASK *tcb; uint32_t interrupt_level; /* Save the current task pointer. */ tcb = get_current_task(); /* Current task should not be null. */ OS_ASSERT(tcb == NULL); /* Interrupts must not be locked. */ OS_ASSERT(tcb->interrupt_lock_count != 0); /* Lock the scheduler. */ scheduler_lock(); /* Add current task to the sleep list. */ sleep_add_to_list(tcb, ticks); /* Disable interrupts. */ interrupt_level = GET_INTERRUPT_LEVEL(); DISABLE_INTERRUPTS(); /* Task is being suspended. */ tcb->status = TASK_SUSPENDED; /* Return control to the system. * We will resume from here when our required delay has been achieved. */ CONTROL_TO_SYSTEM(); /* Restore old interrupt level. */ SET_INTERRUPT_LEVEL(interrupt_level); /* Enable scheduling. */ scheduler_unlock(); } /* sleep_ticks */
/* * console_register * @console: Console data. * This function will register a console. */ void console_register(CONSOLE *console) { #ifndef CONFIG_SEMAPHORE /* Lock the scheduler. */ scheduler_lock(); #else /* Obtain the global data lock. */ OS_ASSERT(semaphore_obtain(&console_data.lock, MAX_WAIT) != SUCCESS); /* Create a semaphore to protect this console device. */ memset(&console->lock, 0, sizeof(SEMAPHORE)); semaphore_create(&console->lock, 1, 1, SEMAPHORE_PRIORITY); #endif /* This utility is called by drivers for registering consoles for the * applicable devices, so no need to check for name conflicts. */ /* Just push this file system in the list. */ sll_push(&console_data.list, console, OFFSETOF(CONSOLE, fs.next)); /* Initialize console FS data. */ console->fs.get_lock = console_lock; console->fs.release_lock = console_unlock; console->fs.timeout = MAX_WAIT; /* Initialize file system condition. */ fs_condition_init(&console->fs); #ifdef CONFIG_SEMAPHORE /* Release the global data lock. */ semaphore_release(&console_data.lock); #else /* Enable scheduling. */ scheduler_unlock(); #endif } /* console_register */
/* * mem_dynamic_print_usage * @mem_dynamic: The memory region. * @level: Flags to specify level of required information. * This function will print the information about a given dynamic region. */ void mem_dynamic_print_usage(MEM_DYNAMIC *mem_dynamic, uint32_t level) { uint32_t start, end, i, free, total_free = 0; MEM_FREE *free_mem; #ifdef CONFIG_SEMAPHORE /* Obtain the memory lock. */ OS_ASSERT(semaphore_obtain(&mem_dynamic->lock, MAX_WAIT) != SUCCESS); #else /* Lock the scheduler. */ scheduler_lock(); #endif /* CONFIG_SEMAPHORE */ /* Memory general information. */ if (level & STAT_MEM_GENERAL) { start = (uint32_t)mem_dynamic->pages[0].base_start; end = (uint32_t)mem_dynamic->pages[mem_dynamic->num_pages - 1].base_end; /* Print general information about this memory region. */ printf("Memory Region Information:\r\n"); printf("Start\t\t: 0x%X\r\n", start); printf("End\t\t: 0x%X\r\n", end); printf("Total Size\t: %d\r\n", (end - start)); } /* Page information. */ if ((level & STAT_MEM_PAGE_INFO) || (level & STAT_MEM_GENERAL)) { /* If we are only printing page information. */ if (!(level & STAT_MEM_GENERAL)) { printf("Memory Page(s) Information:\r\n"); } /* If we need to print page information. */ if (level & STAT_MEM_PAGE_INFO) { printf("P[n]\tStart\t\tEnd\t\tFree\r\n"); } /* Go through all the pages in this memory region. */ for (i = 0; i < mem_dynamic->num_pages; i++) { /* Calculate free memory on this page. */ free = 0; free_mem = mem_dynamic->pages[i].free_list.head; /* Go through free memory list. */ while (free_mem) { free += free_mem->descriptor.size; free_mem = free_mem->next; } /* Add it to total free. */ total_free += free; /* If we need to print per page information. */ if (level & STAT_MEM_PAGE_INFO) { printf("[%d]\t0x%X\t0x%X\t%d\r\n", i, mem_dynamic->pages[i].base_start, mem_dynamic->pages[i].base_end, free); } } /* Print total number of bytes free in this memory region. */ printf("Total Free\t: %d\r\n", total_free); } #ifdef CONFIG_SEMAPHORE /* Release the memory lock. */ semaphore_release(&mem_dynamic->lock); #else /* Enable scheduling. */ scheduler_unlock(); #endif /* CONFIG_SEMAPHORE */ } /* mem_dynamic_print_usage */
void scheduler::remove_active_user() { std::lock_guard<std::mutex> scheduler_lock(mutex); if (--active_users == 0) { no_more_active_users.notify_all(); } }
void PionScheduler::removeActiveUser(void) { boost::mutex::scoped_lock scheduler_lock(m_mutex); if (--m_active_users == 0) m_no_more_active_users.notify_all(); }
void PionScheduler::addActiveUser(void) { if (!m_is_running) startup(); boost::mutex::scoped_lock scheduler_lock(m_mutex); ++m_active_users; }
void scheduler::add_active_user() { if (!running) startup(); std::lock_guard<std::mutex> scheduler_lock(mutex); ++active_users; }