pony_ctx_t* ponyint_sched_init(uint32_t threads, bool noyield, bool nopin, bool pinasio) { pony_register_thread(); use_yield = !noyield; // If no thread count is specified, use the available physical core count. if(threads == 0) threads = ponyint_cpu_count(); scheduler_count = threads; scheduler = (scheduler_t*)ponyint_pool_alloc_size( scheduler_count * sizeof(scheduler_t)); memset(scheduler, 0, scheduler_count * sizeof(scheduler_t)); uint32_t asio_cpu = ponyint_cpu_assign(scheduler_count, scheduler, nopin, pinasio); for(uint32_t i = 0; i < scheduler_count; i++) { scheduler[i].ctx.scheduler = &scheduler[i]; scheduler[i].last_victim = &scheduler[i]; ponyint_messageq_init(&scheduler[i].mq); ponyint_mpmcq_init(&scheduler[i].q); } ponyint_mpmcq_init(&inject); ponyint_asio_init(asio_cpu); return pony_ctx(); }
bool ponyint_sched_start(bool library) { this_scheduler = NULL; if(!ponyint_asio_start()) return false; atomic_store_explicit(&detect_quiescence, !library, memory_order_relaxed); uint32_t start = 0; if(library) { pony_register_thread(); } for(uint32_t i = start; i < scheduler_count; i++) { if(!pony_thread_create(&scheduler[i].tid, run_thread, scheduler[i].cpu, &scheduler[i])) return false; } if(!library) { ponyint_sched_shutdown(); } return true; }
void asio_event_send(asio_event_t* ev, uint32_t flags, uint32_t arg) { asio_msg_t* m = (asio_msg_t*)pony_alloc_msg(POOL_INDEX(sizeof(asio_msg_t)), ev->msg_id); m->event = ev; m->flags = flags; m->arg = arg; #ifdef PLATFORM_IS_WINDOWS // On Windows, this can be called from an IOCP callback thread, which may // not have a pony_ctx() associated with it yet. pony_register_thread(); #endif pony_sendv(pony_ctx(), ev->owner, &m->msg); }