⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 task.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 3 页
字号:
					}					dispatch_count++;#ifndef ISC_PLATFORM_USETHREADS					total_dispatch_count++;#endif /* ISC_PLATFORM_USETHREADS */				}				if (task->references == 0 &&				    EMPTY(task->events) &&				    !TASK_SHUTTINGDOWN(task)) {					isc_boolean_t was_idle;					/*					 * There are no references and no					 * pending events for this task,					 * which means it will not become					 * runnable again via an external					 * action (such as sending an event					 * or detaching).					 *					 * We initiate shutdown to prevent					 * it from becoming a zombie.					 *					 * We do this here instead of in					 * the "if EMPTY(task->events)" block					 * below because:					 *					 *	If we post no shutdown events,					 *	we want the task to finish.					 *					 *	If we did post shutdown events,					 *	will still want the task's					 *	quantum to be applied.					 */					was_idle = task_shutdown(task);					INSIST(!was_idle);				}				if (EMPTY(task->events)) {					/*					 * Nothing else to do for this task					 * right now.					 */					XTRACE(isc_msgcat_get(isc_msgcat,							      ISC_MSGSET_TASK,							      ISC_MSG_EMPTY,							      "empty"));					if (task->references == 0 &&					    TASK_SHUTTINGDOWN(task)) {						/*						 * The task is done.						 */						XTRACE(isc_msgcat_get(							       isc_msgcat,							       ISC_MSGSET_TASK,							       ISC_MSG_DONE,							       "done"));						finished = ISC_TRUE;						task->state = task_state_done;					} else						task->state = task_state_idle;					done = ISC_TRUE;				} else if (dispatch_count >= task->quantum) {					/*					 * Our quantum has expired, but					 * there is more work to be done.					 * We'll requeue it to the ready					 * queue later.					 *					 * We don't check quantum until					 * dispatching at least one event,					 * so the minimum quantum is one.					 */					XTRACE(isc_msgcat_get(isc_msgcat,							      ISC_MSGSET_TASK,							      ISC_MSG_QUANTUM,							      "quantum"));					task->state = task_state_ready;					requeue = ISC_TRUE;					done = ISC_TRUE;				}			} while (!done);			UNLOCK(&task->lock);			if (finished)				task_finished(task);			LOCK(&manager->lock);			manager->tasks_running--;#ifdef ISC_PLATFORM_USETHREADS			if (manager->exclusive_requested &&			    manager->tasks_running == 1) {				SIGNAL(&manager->exclusive_granted);			}#endif /* ISC_PLATFORM_USETHREADS */			if (requeue) {				/*				 * We know we're awake, so we don't have				 * to wakeup any sleeping threads if the				 * ready queue is empty before we requeue.				 *				 * A possible optimization if the queue is				 * empty is to 'goto' the 'if (task != NULL)'				 * block, avoiding the ENQUEUE of the task				 * and the subsequent immediate DEQUEUE				 * (since it is the only executable task).				 * We don't do this because then we'd be				 * skipping the exit_requested check.  The				 * cost of ENQUEUE is low anyway, especially				 * when you consider that we'd have to do				 * an extra EMPTY check to see if we could				 * do the optimization.  If the ready queue				 * were usually nonempty, the 'optimization'				 * might even hurt rather than help.				 */#ifdef ISC_PLATFORM_USETHREADS				ENQUEUE(manager->ready_tasks, task,					ready_link);#else				ENQUEUE(ready_tasks, task, ready_link);#endif			}		}	}#ifndef ISC_PLATFORM_USETHREADS	ISC_LIST_APPENDLIST(manager->ready_tasks, ready_tasks, ready_link);#endif	UNLOCK(&manager->lock);}#ifdef ISC_PLATFORM_USETHREADSstatic isc_threadresult_t#ifdef _WIN32WINAPI#endifrun(void *uap) {	isc_taskmgr_t *manager = uap;	XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,				    ISC_MSG_STARTING, "starting"));	dispatch(manager);	XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,				    ISC_MSG_EXITING, "exiting"));	return ((isc_threadresult_t)0);}#endif /* ISC_PLATFORM_USETHREADS */static voidmanager_free(isc_taskmgr_t *manager) {	isc_mem_t *mctx;#ifdef ISC_PLATFORM_USETHREADS	(void)isc_condition_destroy(&manager->exclusive_granted);		(void)isc_condition_destroy(&manager->work_available);	isc_mem_put(manager->mctx, manager->threads,		    manager->workers * sizeof(isc_thread_t));#endif /* ISC_PLATFORM_USETHREADS */	DESTROYLOCK(&manager->lock);	manager->magic = 0;	mctx = manager->mctx;	isc_mem_put(mctx, manager, sizeof(*manager));	isc_mem_detach(&mctx);}isc_result_tisc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,		   unsigned int default_quantum, isc_taskmgr_t **managerp){	isc_result_t result;	unsigned int i, started = 0;	isc_taskmgr_t *manager;	/*	 * Create a new task manager.	 */	REQUIRE(workers > 0);	REQUIRE(managerp != NULL && *managerp == NULL);#ifndef ISC_PLATFORM_USETHREADS	UNUSED(i);	UNUSED(started);	UNUSED(workers);	if (taskmgr != NULL) {		taskmgr->refs++;		*managerp = taskmgr;		return (ISC_R_SUCCESS);	}#endif /* ISC_PLATFORM_USETHREADS */	manager = isc_mem_get(mctx, sizeof(*manager));	if (manager == NULL)		return (ISC_R_NOMEMORY);	manager->magic = TASK_MANAGER_MAGIC;	manager->mctx = NULL;	manager->workers = 0;	if (isc_mutex_init(&manager->lock) != ISC_R_SUCCESS) {		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "isc_mutex_init() %s",				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,						ISC_MSG_FAILED, "failed"));		result = ISC_R_UNEXPECTED;		goto cleanup_mgr;	}#ifdef ISC_PLATFORM_USETHREADS	manager->threads = isc_mem_get(mctx, workers * sizeof(isc_thread_t));	if (manager->threads == NULL) {		result = ISC_R_NOMEMORY;		goto cleanup_lock;	}	if (isc_condition_init(&manager->work_available) != ISC_R_SUCCESS) {		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "isc_condition_init() %s",				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,						ISC_MSG_FAILED, "failed"));		result = ISC_R_UNEXPECTED;		goto cleanup_threads;	}	if (isc_condition_init(&manager->exclusive_granted) != ISC_R_SUCCESS) {		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "isc_condition_init() %s",				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,						ISC_MSG_FAILED, "failed"));		result = ISC_R_UNEXPECTED;		goto cleanup_workavailable;	}#endif /* ISC_PLATFORM_USETHREADS */	if (default_quantum == 0)		default_quantum = DEFAULT_DEFAULT_QUANTUM;	manager->default_quantum = default_quantum;	INIT_LIST(manager->tasks);	INIT_LIST(manager->ready_tasks);	manager->tasks_running = 0;	manager->exclusive_requested = ISC_FALSE;	manager->exiting = ISC_FALSE;	manager->workers = 0;	isc_mem_attach(mctx, &manager->mctx);#ifdef ISC_PLATFORM_USETHREADS	LOCK(&manager->lock);	/*	 * Start workers.	 */	for (i = 0; i < workers; i++) {		if (isc_thread_create(run, manager,				      &manager->threads[manager->workers]) ==		    ISC_R_SUCCESS) {			manager->workers++;			started++;		}	}	UNLOCK(&manager->lock);	if (started == 0) {		manager_free(manager);		return (ISC_R_NOTHREADS);	}	isc_thread_setconcurrency(workers);#else /* ISC_PLATFORM_USETHREADS */	manager->refs = 1;	taskmgr = manager;#endif /* ISC_PLATFORM_USETHREADS */	*managerp = manager;	return (ISC_R_SUCCESS);#ifdef ISC_PLATFORM_USETHREADS cleanup_workavailable:	(void)isc_condition_destroy(&manager->work_available); cleanup_threads:	isc_mem_put(mctx, manager->threads, workers * sizeof(isc_thread_t)); cleanup_lock:	DESTROYLOCK(&manager->lock);#endif cleanup_mgr:	isc_mem_put(mctx, manager, sizeof(*manager));	return (result);}voidisc_taskmgr_destroy(isc_taskmgr_t **managerp) {	isc_taskmgr_t *manager;	isc_task_t *task;	unsigned int i;	/*	 * Destroy '*managerp'.	 */	REQUIRE(managerp != NULL);	manager = *managerp;	REQUIRE(VALID_MANAGER(manager));#ifndef ISC_PLATFORM_USETHREADS	UNUSED(i);	if (manager->refs > 1) {		manager->refs--;		*managerp = NULL;		return;	}#endif /* ISC_PLATFORM_USETHREADS */	XTHREADTRACE("isc_taskmgr_destroy");	/*	 * Only one non-worker thread may ever call this routine.	 * If a worker thread wants to initiate shutdown of the	 * task manager, it should ask some non-worker thread to call	 * isc_taskmgr_destroy(), e.g. by signalling a condition variable	 * that the startup thread is sleeping on.	 */	/*	 * Unlike elsewhere, we're going to hold this lock a long time.	 * We need to do so, because otherwise the list of tasks could	 * change while we were traversing it.	 *	 * This is also the only function where we will hold both the	 * task manager lock and a task lock at the same time.	 */	LOCK(&manager->lock);	/*	 * Make sure we only get called once.	 */	INSIST(!manager->exiting);	manager->exiting = ISC_TRUE;	/*	 * Post shutdown event(s) to every task (if they haven't already been	 * posted).	 */	for (task = HEAD(manager->tasks);	     task != NULL;	     task = NEXT(task, link)) {		LOCK(&task->lock);		if (task_shutdown(task))			ENQUEUE(manager->ready_tasks, task, ready_link);		UNLOCK(&task->lock);	}#ifdef ISC_PLATFORM_USETHREADS	/*	 * Wake up any sleeping workers.  This ensures we get work done if	 * there's work left to do, and if there are already no tasks left	 * it will cause the workers to see manager->exiting.	 */	BROADCAST(&manager->work_available);	UNLOCK(&manager->lock);	/*	 * Wait for all the worker threads to exit.	 */	for (i = 0; i < manager->workers; i++)		(void)isc_thread_join(manager->threads[i], NULL);#else /* ISC_PLATFORM_USETHREADS */	/*	 * Dispatch the shutdown events.	 */	UNLOCK(&manager->lock);	while (isc__taskmgr_ready())		(void)isc__taskmgr_dispatch();	INSIST(ISC_LIST_EMPTY(manager->tasks));#endif /* ISC_PLATFORM_USETHREADS */	manager_free(manager);	*managerp = NULL;}#ifndef ISC_PLATFORM_USETHREADSisc_boolean_tisc__taskmgr_ready(void) {	if (taskmgr == NULL)		return (ISC_FALSE);	return (ISC_TF(!ISC_LIST_EMPTY(taskmgr->ready_tasks)));}isc_result_tisc__taskmgr_dispatch(void) {	isc_taskmgr_t *manager = taskmgr;	if (taskmgr == NULL)		return (ISC_R_NOTFOUND);	dispatch(manager);	return (ISC_R_SUCCESS);}#endif /* ISC_PLATFORM_USETHREADS */isc_result_tisc_task_beginexclusive(isc_task_t *task) {#ifdef ISC_PLATFORM_USETHREADS		isc_taskmgr_t *manager = task->manager;	REQUIRE(task->state == task_state_running);	LOCK(&manager->lock);	if (manager->exclusive_requested) {		UNLOCK(&manager->lock);					return (ISC_R_LOCKBUSY);	}	manager->exclusive_requested = ISC_TRUE;	while (manager->tasks_running > 1) {		WAIT(&manager->exclusive_granted, &manager->lock);	}	UNLOCK(&manager->lock);	#else	UNUSED(task);#endif	return (ISC_R_SUCCESS);}voidisc_task_endexclusive(isc_task_t *task) {#ifdef ISC_PLATFORM_USETHREADS		isc_taskmgr_t *manager = task->manager;	REQUIRE(task->state == task_state_running);	LOCK(&manager->lock);	REQUIRE(manager->exclusive_requested);	manager->exclusive_requested = ISC_FALSE;	BROADCAST(&manager->work_available);	UNLOCK(&manager->lock);#else	UNUSED(task);#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -