loop_t* loop_new(unsigned hint) { loop_t* loop; int epfd; (void)current_tid(); loop = (loop_t*)malloc(sizeof(loop_t)); memset(loop, 0, sizeof(*loop)); loop->run = 0; if (hint < 64) { hint = 64; } epfd = epoll_create(hint); if (epfd < 0) { free(loop); log_error("loop_new: epoll_create() failed, error: %d", errno); return NULL; } loop->epfd = epfd; loop->max_event_count = hint; loop->events = (struct epoll_event*)malloc(sizeof(struct epoll_event) * hint); memset(loop->events, 0, (sizeof(struct epoll_event) * hint)); loop->task_queue = async_task_queue_create(loop); loop->timer_queue = timer_queue_create(loop); return loop; }
int loop_inloopthread(loop_t* loop) { if (NULL == loop) { return 0; } return (loop->threadId == current_tid()) ? 1 : 0; }
void loop_run_inloop(loop_t* loop, void(*callback)(void *userdata), void* userdata) { if (NULL == loop || NULL == callback) { return; } if ((loop->run == 0) || (loop->threadId == current_tid())) { callback(userdata); } else { async_task_queue_submit(loop->task_queue, callback, userdata); } return; }
void loop_loop(loop_t *loop) { int result; int i; long timeout; struct epoll_event *event; channel_t* channel; int error; struct rlimit limit; if (NULL == loop) { return; } loop->threadId = current_tid(); loop->run = 1; while (loop->run != 0) { timeout = timer_queue_gettimeout(loop->timer_queue); memset(loop->events, 0, loop->max_event_count * sizeof(struct epoll_event)); result = epoll_wait(loop->epfd, loop->events, loop->max_event_count, timeout); error = errno; if (result > 0) { for (i = 0; i < result; ++i) { event = &(loop->events[i]); channel = (channel_t*)event->data.ptr; channel_setrevent(channel, event->events); } for (i = 0; i < result; ++i) { event = &(loop->events[i]); channel = (channel_t*)event->data.ptr; channel_onevent(channel); } if (result == loop->max_event_count) { memset(&limit, 0, sizeof(limit)); getrlimit(RLIMIT_NOFILE, &limit); if (result < limit.rlim_cur) { result *= 2; if (result > limit.rlim_cur) { result = limit.rlim_cur; } loop->events = realloc(loop->events, result*sizeof(struct epoll_event)); loop->max_event_count = result; } } } else if (0 > result && EINTR != error) { log_error("loop_loop: epoll_wait() failed, errno: %d", error); } timer_queue_process_inloop(loop->timer_queue); } return; }
int begin_wait_thread( int pid, int tid, int *rc ) { int success = -1; int size; struct wait_info *nw = NULL; struct process *proc; struct thread *tr; ASSERT( pid == current_pid() ); proc = checkout_process( pid, WRITER ); ASSERT( proc != NULL ); tr = find_thread_with_id( proc, tid ); if ( tr == NULL ) { commit_process( proc ); return -1; } // -------------------------------- size = sizeof(struct wait_info); nw = (struct wait_info*)malloc( size ); nw->next = NULL; nw->prev = NULL; nw->pid = current_pid(); nw->tid = current_tid(); nw->success = -1; // Assume failure from the very beginning. nw->rc = -1; current_thread()->active_wait = nw; // Set our active wait information. // Now we insert it into the wait list. if ( tr->waits != NULL ) tr->waits->prev = nw; nw->next = tr->waits; tr->waits = nw; // ----------------------------- commit_process( proc ); // ------ Now we go to sleep ------------- proc = checkout_process( current_pid(), WRITER ); if ( proc == NULL ) { /// \todo freak out and handle stuff properly return -1; } disable_interrupts(); atomic_dec( &(proc->kernel_threads) ); set_thread_state( current_thread(), THREAD_WAITING ); commit_process( proc ); enable_interrupts(); sched_yield(); // Release! // Secure ourselves. atomic_inc( &(proc->kernel_threads) ); // Get our process back. proc = checkout_process( current_pid(), WRITER ); if ( proc == NULL ) return -1; current_thread()->active_wait = NULL; commit_process( proc ); // We're back. Return the correct info. *rc = nw->rc; success = nw->success; // nw should have been unlinked by the scheduler. // waiter should have active_wait cleared by the // scheduler as well. // we just need to delete it. free( nw ); return success; }
int begin_wait_process( int pid, int *rc ) { int success = -1; struct wait_info *nw = NULL; struct process *proc; proc = checkout_process( pid, WRITER ); if ( proc == NULL ) return -1; nw = (struct wait_info*)malloc( sizeof(struct wait_info) ); nw->next = NULL; nw->prev = NULL; nw->pid = current_pid(); nw->tid = current_tid(); nw->success = -1; // Assume failure from the very beginning. nw->rc = -1; // Now we insert it into the wait list. if ( proc->waits != NULL ) proc->waits->prev = nw; nw->next = proc->waits; proc->waits = nw; // ----------------------------- commit_process( proc ); // ------ Now we go to sleep ------------- proc = checkout_process( current_pid(), WRITER ); ASSERT( proc != NULL ); current_thread()->active_wait = nw; // Save our active wait. disable_interrupts(); atomic_dec( &(proc->kernel_threads) ); set_thread_state( current_thread(), THREAD_WAITING ); commit_process( proc ); enable_interrupts(); sched_yield(); atomic_inc( &(proc->kernel_threads) ); // Secure this thread. // Get our process back. proc = checkout_process( current_pid(), WRITER ); ASSERT( proc != NULL ); current_thread()->active_wait = NULL; commit_process( proc ); // We're back. Return the correct info. *rc = nw->rc; success = nw->success; // nw should have been unlinked by the scheduler. // waiter should have active_wait cleared by the // scheduler as well. // we just need to delete it. free( nw ); /// \todo active_waits for threads. return success; }