int workqueue_create(struct workqueue **wqp, const char *name, void (*callback_func)(struct work *, void *), void *callback_arg, pri_t prio, int ipl, int flags) { struct workqueue *wq; struct workqueue_queue *q; void *ptr; int error = 0; CTASSERT(sizeof(work_impl_t) <= sizeof(struct work)); ptr = kmem_zalloc(workqueue_size(flags), KM_SLEEP); wq = (void *)roundup2((uintptr_t)ptr, coherency_unit); wq->wq_ptr = ptr; wq->wq_flags = flags; workqueue_init(wq, name, callback_func, callback_arg, prio, ipl); if (flags & WQ_PERCPU) { struct cpu_info *ci; CPU_INFO_ITERATOR cii; /* create the work-queue for each CPU */ for (CPU_INFO_FOREACH(cii, ci)) { q = workqueue_queue_lookup(wq, ci); error = workqueue_initqueue(wq, q, ipl, ci); if (error) { break; } } } else {
int rate_submit_init(struct thread_data *td, struct sk_out *sk_out) { if (td->o.io_submit_mode != IO_MODE_OFFLOAD) return 0; return workqueue_init(td, &td->io_wq, &rated_wq_ops, td->o.iodepth, sk_out); }
kstat_t krhino_init(void) { g_sys_stat = RHINO_STOPPED; #if (RHINO_CONFIG_USER_HOOK > 0) krhino_init_hook(); #endif runqueue_init(&g_ready_queue); tick_list_init(); #if (RHINO_CONFIG_SYSTEM_STATS > 0) kobj_list_init(); #endif #if (RHINO_CONFIG_MM_TLF > 0) k_mm_init(); #endif #if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0) klist_init(&g_res_list); krhino_sem_create(&g_res_sem, "res_sem", 0); dyn_mem_proc_task_start(); #endif #if (RHINO_CONFIG_CPU_NUM > 1) for (uint8_t i = 0; i < RHINO_CONFIG_CPU_NUM; i++) { krhino_task_cpu_create(&g_idle_task[i], "idle_task", NULL, RHINO_IDLE_PRI, 0, &g_idle_task_stack[i][0], RHINO_CONFIG_IDLE_TASK_STACK_SIZE, idle_task, i, 1u); } #else krhino_task_create(&g_idle_task[0], "idle_task", NULL, RHINO_IDLE_PRI, 0, &g_idle_task_stack[0][0], RHINO_CONFIG_IDLE_TASK_STACK_SIZE, idle_task, 1u); #endif #if (RHINO_CONFIG_WORKQUEUE > 0) workqueue_init(); #endif #if (RHINO_CONFIG_TIMER > 0) ktimer_init(); #endif #if (RHINO_CONFIG_CPU_USAGE_STATS > 0) cpu_usage_stats_start(); #endif rhino_stack_check_init(); return RHINO_SUCCESS; }
int main(int argc, char **argv) { int rc; workqueue_t wq; rc = workqueue_init(&wq, "thread"); assert(rc == 0); rc = workqueue_submit(&wq, hello, NULL); assert(rc == 0); workqueue_lock(&wq); while (!workqueue_idle(&wq)) { workqueue_wait(&wq, 0); } workqueue_unlock(&wq); workqueue_destroy(&wq); return 0; }
int main(int argc, char *argv[]) { struct prg_ctx prg; int i; int num_jobs = 3; int ret; printf("starting\n"); signal(SIGTERM, sighandler_func); prg.counter = 0; prg.ctx = workqueue_init(32, 1, NULL); for (i = 0; i < num_jobs; i++) { ret = workqueue_add_work(prg.ctx, 2, 0, callback_func, &prg); if (ret >= 0) { printf("Added job %d \n", ret); } else { printf("Error adding job err=%d\n", ret); } } workqueue_show_status(prg.ctx, stdout); for (i = 0; i < num_jobs; i++) { printf("job %d is queued=%d running=%d queued_or_running=%d\n", i, workqueue_job_queued(prg.ctx, i), workqueue_job_running(prg.ctx, i), workqueue_job_queued_or_running(prg.ctx, i)); } workqueue_show_status(prg.ctx, stdout); for (i = 0; i < num_jobs; i++) { ret = workqueue_dequeue(prg.ctx, i), printf(" dequeue job %d ret=%d\n", i , ret); } workqueue_show_status(prg.ctx, stdout); for (i = 0; i < num_jobs; i++) { ret = workqueue_add_work(prg.ctx, 2, 0, callback_func, &prg); if (ret >= 0) { printf("Added job %d \n", ret); } else { printf("Error adding job err=%d\n", ret); } } for (i = 0; i < num_jobs*2; i++) { ret = workqueue_dequeue(prg.ctx, i), printf(" dequeue job %d ret=%d\n", i , ret); } for (i = 20; i && (ret = workqueue_get_queue_len(prg.ctx)); i--) { printf("waiting for %d jobs \n", ret); sleep(1); } workqueue_destroy(prg.ctx); #ifdef WINDOWS system("pause"); #endif return 0; }
int main(int argc, char *argv[]) { struct prg_ctx prg; int i; int num_jobs=6; int ret; printf("starting\n"); prg.counter = 0; prg.ctx = workqueue_init(32, 1, NULL); for (i = 0; i < num_jobs; i++) { ret = workqueue_add_work(prg.ctx, 2, 0, callback_func, &prg); if (ret >= 0) { printf("Added job %d \n", ret); } else { printf("Error adding job err=%d\n", ret); } } workqueue_show_status(prg.ctx, stdout); for (i = 0; i < num_jobs; i++) { printf("job %d is queued=%d running=%d queued_or_running=%d\n", i, workqueue_job_queued(prg.ctx, i), workqueue_job_running(prg.ctx, i), workqueue_job_queued_or_running(prg.ctx, i)); } for (i = 0; i < num_jobs/2; i++) { ret = workqueue_add_work(prg.ctx, 5, 0, callback_func, &prg); if (ret >= 0) { printf("Added job %d \n", ret); } else { printf("Error adding job err=%d\n", ret); } } workqueue_show_status(prg.ctx, stdout); for (i = 0; i < num_jobs/2; i++) { ret = workqueue_add_work(prg.ctx, 1, 0, callback_func, &prg); if (ret >= 0) { printf("Added job %d \n", ret); } else { printf("Error adding job err=%d\n", ret); } } workqueue_show_status(prg.ctx, stdout); for (i = 20; i && (ret = workqueue_get_queue_len(prg.ctx)) > 5; i--) { printf("waiting for %d jobs \n", ret); sleep(1); } // empty out remaining jobs and wait for running job to finish workqueue_empty_wait(prg.ctx); workqueue_destroy(prg.ctx); #ifdef WINDOWS system("pause"); #endif return 0; }
/** * Run the server. This function blocks, only returning when the server has terminated. */ int runServer(void) { int sockfd; struct sockaddr_in listen_addr; struct event ev_accept; int reuseaddr_on; /* Initialize libevent. */ event_init(); /* Set signal handlers sigset_t:信号集,其被定义为一种数据类型 struct sigaction { void (*sa_handler)(int); //此参数和signal()的参数handler 相同, 代表新的信号处理函数 void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; //用来设置在处理该信号时暂时将sa_mask 指定的信号搁置 int sa_flags; //用来设置信号处理的其他相关操作, A_NOCLDSTOP: 如果参数signum 为SIGCHLD, 则当子进程暂停时并不会通知父进程;SA_RESTART: 被信号中断的系统调用会自行重启; void (*sa_restorer)(void); //此参数没有使用 }; */ sigset_t sigset; sigemptyset(&sigset); //初始化信号集,信号集里面的所有信号被清空 /*struct sigaction siginfo = { .sa_handler = sighandler, .sa_mask = sigset, .sa_flags = SA_RESTART, };*/ struct sigaction siginfo; siginfo.sa_handler = sighandler; siginfo.sa_mask = sigset; siginfo.sa_flags = SA_RESTART; sigaction(SIGINT, &siginfo, NULL); //程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出 sigaction(SIGTERM, &siginfo, NULL); //程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理.通常用来要求程序自己正常退出.shell命令kill缺省产生这个信号. /* Create our listening socket. */ sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { err(1, "listen failed"); } memset(&listen_addr, 0, sizeof(listen_addr)); listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = INADDR_ANY; listen_addr.sin_port = htons(SERVER_PORT); if (bind(sockfd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) { err(1, "bind failed"); } if (listen(sockfd, CONNECTION_BACKLOG) < 0) { err(1, "listen failed"); } reuseaddr_on = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, sizeof(reuseaddr_on)); /* Set the socket to non-blocking, this is essential in event * based programming with libevent. */ if (setnonblock(sockfd) < 0) { err(1, "failed to set server socket to non-blocking"); } evbase_accept = event_base_new(); if (NULL == evbase_accept) { perror("Unable to create socket accept event base"); close(sockfd); return 1; } /* Initialize work queue. */ if (workqueue_init(&workqueue, NUM_THREADS)) { perror("Failed to create work queue"); close(sockfd); workqueue_shutdown(&workqueue); return 1; } /* We now have a listening socket, we create a read event to * be notified when a client connects. */ event_set(&ev_accept, sockfd, EV_READ | EV_PERSIST, on_accept, (void *)&workqueue); event_base_set(evbase_accept, &ev_accept); event_add(&ev_accept, NULL); printf("Server is running...\n"); /* Start the event loop. */ event_base_dispatch(evbase_accept); event_base_free(evbase_accept); evbase_accept = NULL; close(sockfd); printf("Server shutdown.\n"); return 0; }
/** * Run the server. This function blocks, only returning when the server has terminated. */ int runServer(void) { int listenfd; struct sockaddr_in listen_addr; struct event ev_accept; int reuseaddr_on; /* Initialize libevent. */ event_init(); /* Set signal handlers */ sigset_t sigset; sigemptyset(&sigset); struct sigaction siginfo = { .sa_handler = sighandler, .sa_mask = sigset, .sa_flags = SA_RESTART, }; sigaction(SIGINT, &siginfo, NULL); sigaction(SIGTERM, &siginfo, NULL); /* Create our listening socket. */ listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd < 0) { err(1, "listen failed"); } memset(&listen_addr, 0, sizeof(listen_addr)); listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = INADDR_ANY; listen_addr.sin_port = htons(SERVER_PORT); if (bind(listenfd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) { err(1, "bind failed"); } if (listen(listenfd, CONNECTION_BACKLOG) < 0) { err(1, "listen failed"); } reuseaddr_on = 1; setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, sizeof(reuseaddr_on)); /* Set the socket to non-blocking, this is essential in event * based programming with libevent. */ if (setnonblock(listenfd) < 0) { err(1, "failed to set server socket to non-blocking"); } if ((evbase_accept = event_base_new()) == NULL) { perror("Unable to create socket accept event base"); close(listenfd); return 1; } /* Initialize work queue. */ if (workqueue_init(&workqueue, NUM_THREADS)) { perror("Failed to create work queue"); close(listenfd); workqueue_shutdown(&workqueue); return 1; } /* We now have a listening socket, we create a read event to * be notified when a client connects. */ event_set(&ev_accept, listenfd, EV_READ|EV_PERSIST, on_accept, (void *)&workqueue); event_base_set(evbase_accept, &ev_accept); event_add(&ev_accept, NULL); printf("Server running.\n"); /* Start the event loop. */ event_base_dispatch(evbase_accept); event_base_free(evbase_accept); evbase_accept = NULL; close(listenfd); printf("Server shutdown.\n"); return 0; }