int ThreadPoolRemove(ThreadPool *tp, int jobId, ThreadPoolJob *out) { int ret = INVALID_JOB_ID; ThreadPoolJob *temp = NULL; ListNode *tempNode = NULL; ThreadPoolJob dummy; if (!tp) return EINVAL; if (!out) out = &dummy; dummy.jobId = jobId; ithread_mutex_lock(&tp->mutex); tempNode = ListFind(&tp->highJobQ, NULL, &dummy); if (tempNode) { temp = (ThreadPoolJob *)tempNode->item; *out = *temp; ListDelNode(&tp->highJobQ, tempNode, 0); FreeThreadPoolJob(tp, temp); ret = 0; goto exit_function; } tempNode = ListFind(&tp->medJobQ, NULL, &dummy); if (tempNode) { temp = (ThreadPoolJob *)tempNode->item; *out = *temp; ListDelNode(&tp->medJobQ, tempNode, 0); FreeThreadPoolJob(tp, temp); ret = 0; goto exit_function; } tempNode = ListFind(&tp->lowJobQ, NULL, &dummy); if (tempNode) { temp = (ThreadPoolJob *)tempNode->item; *out = *temp; ListDelNode(&tp->lowJobQ, tempNode, 0); FreeThreadPoolJob(tp, temp); ret = 0; goto exit_function; } if (tp->persistentJob && tp->persistentJob->jobId == jobId) { *out = *tp->persistentJob; FreeThreadPoolJob(tp, tp->persistentJob); tp->persistentJob = NULL; ret = 0; goto exit_function; } exit_function: ithread_mutex_unlock(&tp->mutex); return ret; }
/* * This gets called before queuing a new event. * - The list size can never go over MAX_SUBSCRIPTION_QUEUED_EVENTS so we * discard the oldest non-active event if it is already at the max * - We also discard any non-active event older than MAX_SUBSCRIPTION_EVENT_AGE. * non-active: any but the head of queue, which is already copied to * the thread pool */ static void maybeDiscardEvents(LinkedList *listp) { time_t now = time(0L); while (ListSize(listp) > 1) { ListNode *node = ListHead(listp); /* The first candidate is the second event: first non-active */ if (node == 0 || (node = node->next) == 0) { /* Major inconsistency, really, should abort here. */ fprintf(stderr, "gena_device: maybeDiscardEvents: " "list is inconsistent\n"); break; } notify_thread_struct *ntsp = (notify_thread_struct *)(((ThreadPoolJob *)node->item)->arg); if (ListSize(listp) > g_UpnpSdkEQMaxLen || now - ntsp->ctime > g_UpnpSdkEQMaxAge) { free_notify_struct(ntsp); free(node->item); ListDelNode(listp, node, 0); } else { /* If the list is smaller than the max and the oldest * task is young enough, stop pruning */ break; } } }
/************************************************************************ * Function: TimerThreadShutdown * * Description: * Shutdown the timer thread * Events scheduled in the future will NOT be run. * Timer thread should be shutdown BEFORE it's associated * thread pool. * Returns: * returns 0 if succesfull, * nonzero otherwise. * Always returns 0. ***********************************************************************/ int TimerThreadShutdown( TimerThread * timer ) { ListNode *tempNode2 = NULL; ListNode *tempNode = NULL; assert( timer != NULL ); if( timer == NULL ) { return EINVAL; } ithread_mutex_lock( &timer->mutex ); timer->shutdown = 1; tempNode = ListHead( &timer->eventQ ); //Delete nodes in Q //call registered free function //on argument while( tempNode != NULL ) { TimerEvent *temp = ( TimerEvent * ) tempNode->item; tempNode2 = ListNext( &timer->eventQ, tempNode ); ListDelNode( &timer->eventQ, tempNode, 0 ); if( temp->job.free_func ) { temp->job.free_func( temp->job.arg ); } FreeTimerEvent( timer, temp ); tempNode = tempNode2; } ListDestroy( &timer->eventQ, 0 ); FreeListDestroy( &timer->freeEvents ); ithread_cond_broadcast( &timer->condition ); while( timer->shutdown ) //wait for timer thread to shutdown { ithread_cond_wait( &timer->condition, &timer->mutex ); } ithread_mutex_unlock( &timer->mutex ); //destroy condition while( ithread_cond_destroy( &timer->condition ) != 0 ) { } //destroy mutex while( ithread_mutex_destroy( &timer->mutex ) != 0 ) { } return 0; }
/**************************************************************************** * Function: BumpPriority * * Description: * Determines whether any jobs * need to be bumped to a higher priority Q and bumps them. * * tp->mutex must be locked. * Internal Only. * Parameters: * ThreadPool *tp *****************************************************************************/ static void BumpPriority( ThreadPool *tp ) { int done = 0; struct timeval now; unsigned long diffTime = 0; ThreadPoolJob *tempJob = NULL; assert( tp != NULL ); gettimeofday(&now, NULL); while( !done ) { if( tp->medJobQ.size ) { tempJob = ( ThreadPoolJob *) tp->medJobQ.head.next->item; diffTime = DiffMillis( &now, &tempJob->requestTime ); if( diffTime >= ( tp->attr.starvationTime ) ) { // If job has waited longer than the starvation time // bump priority (add to higher priority Q) StatsAccountMQ( tp, diffTime ); ListDelNode( &tp->medJobQ, tp->medJobQ.head.next, 0 ); ListAddTail( &tp->highJobQ, tempJob ); continue; } } if( tp->lowJobQ.size ) { tempJob = ( ThreadPoolJob *) tp->lowJobQ.head.next->item; diffTime = DiffMillis( &now, &tempJob->requestTime ); if( diffTime >= ( tp->attr.maxIdleTime ) ) { // If job has waited longer than the starvation time // bump priority (add to higher priority Q) StatsAccountLQ( tp, diffTime ); ListDelNode( &tp->lowJobQ, tp->lowJobQ.head.next, 0 ); ListAddTail( &tp->medJobQ, tempJob ); continue; } } done = 1; } }
/************************************************************************ * Function : searchExpired * * Parameters: * IN void * arg: * * Description: * This function * * Returns: void * ***************************************************************************/ void searchExpired( void *arg ) { int *id = ( int * )arg; int handle = -1; struct Handle_Info *ctrlpt_info = NULL; //remove search Target from list and call client back ListNode *node = NULL; SsdpSearchArg *item; Upnp_FunPtr ctrlpt_callback; void *cookie = NULL; int found = 0; HandleLock( ); //remove search target from search list if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) { free( id ); HandleUnlock( ); return; } ctrlpt_callback = ctrlpt_info->Callback; node = ListHead( &ctrlpt_info->SsdpSearchList ); while( node != NULL ) { item = ( SsdpSearchArg * ) node->item; if( item->timeoutEventId == ( *id ) ) { free( item->searchTarget ); cookie = item->cookie; found = 1; item->searchTarget = NULL; free( item ); ListDelNode( &ctrlpt_info->SsdpSearchList, node, 0 ); break; } node = ListNext( &ctrlpt_info->SsdpSearchList, node ); } HandleUnlock( ); if( found ) { ctrlpt_callback( UPNP_DISCOVERY_SEARCH_TIMEOUT, NULL, cookie ); } free( id ); }
static void s_Delete_Object(t_FAKE_OBJ *fake_hnd) { ListNode *node = ListHead(&s_object_list); while( node ) { if( node->item == (void*)fake_hnd ) { free(fake_hnd); ListDelNode(&s_object_list, node, 0); break; } node = ListNext(&s_object_list, node); } }
/**************************************************************************** * Function: ListDestroy * * Description: * Removes all memory associated with list nodes. * Does not free LinkedList *list. * Items stored in the list are not freed, only nodes are. * Parameters: * LinkedList *list - must be valid, non null, pointer to a linked list. * Returns: * 0 on success. Nonzero on failure. * Always returns 0. * Precondition: * The list has been initialized. *****************************************************************************/ int ListDestroy( LinkedList * list, int freeItem ) { ListNode *dnode = NULL; ListNode *temp = NULL; if( list == NULL ) return EINVAL; for( dnode = list->head.next; dnode != &list->tail; ) { temp = dnode->next; ListDelNode( list, dnode, freeItem ); dnode = temp; } list->size = 0; FreeListDestroy( &list->freeNodeList ); return 0; }
void freeSubscriptionQueuedEvents(subscription *sub) { if (ListSize(&sub->outgoing) > 0) { /* The first event is discarded without dealing notify_thread_struct: there is a mirror ThreadPool entry for this one, and it will take care of the refcount etc. Other entries must be fully cleaned-up here */ int first = 1; ListNode *node = ListHead(&sub->outgoing); while (node) { ThreadPoolJob *job = (ThreadPoolJob *)node->item; if (first) { first = 0; } else { free_notify_struct((notify_thread_struct *)job->arg); } free(node->item); ListDelNode(&sub->outgoing, node, 0); node = ListHead(&sub->outgoing); } } }
/************************************************************************ * Function: TimerThreadRemove * * Description: * Removes an event from the timer Q. * Events can only be removed * before they have been placed in the * thread pool. * * Parameters: * timer - valid timer thread pointer. * id - id of event to remove. * out - space for returned job (Can be NULL) * Return: * 0 on success. * INVALID_EVENT_ID on error. * ************************************************************************/ int TimerThreadRemove( TimerThread * timer, int id, ThreadPoolJob * out ) { int rc = INVALID_EVENT_ID; ListNode *tempNode = NULL; TimerEvent *temp = NULL; assert( timer != NULL ); if( timer == NULL ) { return EINVAL; } ithread_mutex_lock( &timer->mutex ); tempNode = ListHead( &timer->eventQ ); while( tempNode != NULL ) { temp = ( TimerEvent * ) tempNode->item; if( temp->id == id ) { ListDelNode( &timer->eventQ, tempNode, 0 ); if( out != NULL ) ( *out ) = temp->job; FreeTimerEvent( timer, temp ); rc = 0; break; } tempNode = ListNext( &timer->eventQ, tempNode ); } ithread_mutex_unlock( &timer->mutex ); return rc; }
static void s_Dmscp_UnRegister_ServiceCalback(int hnd) { int *p; ListNode *node; HT_DBG_FUNC_START(HT_MOD_DMC, HT_BIT_MANY,(int)hnd, NULL); sem_wait(&(s_dmscp_service_updated_lock)); node = ListHead(&s_dmscp_service_updated_list); while( node ) { p = (int *)(node->item); if( p[1] == hnd ) { ListDelNode(&s_dmscp_service_updated_list, node, 0); free(p); break; } node = ListNext(&s_dmscp_service_updated_list, node); } sem_post(&(s_dmscp_service_updated_lock)); HT_DBG_FUNC_END(hnd, NULL); }
/*! * \brief Thread job to Notify a control point. * * It validates the subscription and copies the subscription. Also make sure * that events are sent in order. * * \note calls the genaNotify to do the actual work. */ static void genaNotifyThread( /*! [in] notify thread structure containing all the headers and property set info. */ void *input) { subscription *sub; service_info *service; subscription sub_copy; notify_thread_struct *in = (notify_thread_struct *) input; int return_code; struct Handle_Info *handle_info; /* This should be a HandleLock and not a HandleReadLock otherwise if there * is a lot of notifications, then multiple threads will acquire a read * lock and the thread which sends the notification will be blocked forever * on the HandleLock at the end of this function. */ /*HandleReadLock(); */ HandleLock(); /* validate context */ if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) { free_notify_struct(in); HandleUnlock(); return; } if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) || !service->active || !(sub = GetSubscriptionSID(in->sid, service)) || copy_subscription(sub, &sub_copy) != HTTP_SUCCESS) { free_notify_struct(in); HandleUnlock(); return; } HandleUnlock(); /* send the notify */ return_code = genaNotify(in->headers, in->propertySet, &sub_copy); freeSubscription(&sub_copy); HandleLock(); if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) { free_notify_struct(in); HandleUnlock(); return; } /* validate context */ if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) || !service->active || !(sub = GetSubscriptionSID(in->sid, service))) { free_notify_struct(in); HandleUnlock(); return; } sub->ToSendEventKey++; if (sub->ToSendEventKey < 0) /* wrap to 1 for overflow */ sub->ToSendEventKey = 1; /* Remove head of event queue. Possibly activate next */ { ListNode *node = ListHead(&sub->outgoing); if (node) ListDelNode(&sub->outgoing, node, 1); if (ListSize(&sub->outgoing) > 0) { ThreadPoolJob *job; ListNode *node = ListHead(&sub->outgoing); job = (ThreadPoolJob*)node->item; /* The new head of queue should not have already been added to the pool, else something is very wrong */ assert(job->jobId != STALE_JOBID); ThreadPoolAdd(&gSendThreadPool, job, NULL); job->jobId = STALE_JOBID; } } if (return_code == GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB) RemoveSubscriptionSID(in->sid, service); free_notify_struct(in); HandleUnlock(); }
/**************************************************************************** * Function: TimerThreadWorker * * Description: * Implements timer thread. * Waits for next event to occur and schedules * associated job into threadpool. * Internal Only. * Parameters: * void * arg -> is cast to TimerThread * *****************************************************************************/ static void * TimerThreadWorker( void *arg ) { TimerThread *timer = ( TimerThread * ) arg; ListNode *head = NULL; TimerEvent *nextEvent = NULL; time_t currentTime = 0; time_t nextEventTime = 0; struct timespec timeToWait; int tempId; assert( timer != NULL ); ithread_mutex_lock( &timer->mutex ); while( 1 ) { //mutex should always be locked at top of loop //Check for shutdown if( timer->shutdown ) { timer->shutdown = 0; ithread_cond_signal( &timer->condition ); ithread_mutex_unlock( &timer->mutex ); return NULL; } nextEvent = NULL; //Get the next event if possible if( timer->eventQ.size > 0 ) { head = ListHead( &timer->eventQ ); nextEvent = ( TimerEvent * ) head->item; nextEventTime = nextEvent->eventTime; } currentTime = time( NULL ); //If time has elapsed, schedule job if( ( nextEvent != NULL ) && ( currentTime >= nextEventTime ) ) { if( nextEvent->persistent ) { ThreadPoolAddPersistent( timer->tp, &nextEvent->job, &tempId ); } else { ThreadPoolAdd( timer->tp, &nextEvent->job, &tempId ); } ListDelNode( &timer->eventQ, head, 0 ); FreeTimerEvent( timer, nextEvent ); continue; } if( nextEvent != NULL ) { timeToWait.tv_nsec = 0; timeToWait.tv_sec = nextEvent->eventTime; ithread_cond_timedwait( &timer->condition, &timer->mutex, &timeToWait ); } else { ithread_cond_wait( &timer->condition, &timer->mutex ); } } }
int ThreadPoolShutdown(ThreadPool *tp) { ListNode *head = NULL; ThreadPoolJob *temp = NULL; if (!tp) return EINVAL; ithread_mutex_lock(&tp->mutex); /* clean up high priority jobs */ while (tp->highJobQ.size) { head = ListHead(&tp->highJobQ); if (head == NULL) { ithread_mutex_unlock(&tp->mutex); return EINVAL; } temp = (ThreadPoolJob *)head->item; if (temp->free_func) temp->free_func(temp->arg); FreeThreadPoolJob(tp, temp); ListDelNode(&tp->highJobQ, head, 0); } ListDestroy(&tp->highJobQ, 0); /* clean up med priority jobs */ while (tp->medJobQ.size) { head = ListHead(&tp->medJobQ); if (head == NULL) { ithread_mutex_unlock(&tp->mutex); return EINVAL; } temp = (ThreadPoolJob *)head->item; if (temp->free_func) temp->free_func(temp->arg); FreeThreadPoolJob(tp, temp); ListDelNode(&tp->medJobQ, head, 0); } ListDestroy(&tp->medJobQ, 0); /* clean up low priority jobs */ while (tp->lowJobQ.size) { head = ListHead(&tp->lowJobQ); if (head == NULL) { ithread_mutex_unlock(&tp->mutex); return EINVAL; } temp = (ThreadPoolJob *)head->item; if (temp->free_func) temp->free_func(temp->arg); FreeThreadPoolJob(tp, temp); ListDelNode(&tp->lowJobQ, head, 0); } ListDestroy(&tp->lowJobQ, 0); /* clean up long term job */ if (tp->persistentJob) { temp = tp->persistentJob; if (temp->free_func) temp->free_func(temp->arg); FreeThreadPoolJob(tp, temp); tp->persistentJob = NULL; } /* signal shutdown */ tp->shutdown = 1; ithread_cond_broadcast(&tp->condition); /* wait for all threads to finish */ while (tp->totalThreads > 0) ithread_cond_wait(&tp->start_and_shutdown, &tp->mutex); /* destroy condition */ while (ithread_cond_destroy(&tp->condition) != 0) {} while (ithread_cond_destroy(&tp->start_and_shutdown) != 0) {} FreeListDestroy(&tp->jobFreeList); ithread_mutex_unlock(&tp->mutex); /* destroy mutex */ while (ithread_mutex_destroy(&tp->mutex) != 0) {} return 0; }
/*! * \brief Implements a thread pool worker. Worker waits for a job to become * available. Worker picks up persistent jobs first, high priority, * med priority, then low priority. * * If worker remains idle for more than specified max, the worker is released. * * \internal */ static void *WorkerThread( /*! arg -> is cast to (ThreadPool *). */ void *arg) { time_t start = 0; ThreadPoolJob *job = NULL; ListNode *head = NULL; struct timespec timeout; int retCode = 0; int persistent = -1; ThreadPool *tp = (ThreadPool *) arg; ithread_initialize_thread(); /* Increment total thread count */ ithread_mutex_lock(&tp->mutex); tp->totalThreads++; tp->pendingWorkerThreadStart = 0; ithread_cond_broadcast(&tp->start_and_shutdown); ithread_mutex_unlock(&tp->mutex); SetSeed(); StatsTime(&start); while (1) { ithread_mutex_lock(&tp->mutex); if (job) { tp->busyThreads--; FreeThreadPoolJob(tp, job); job = NULL; } retCode = 0; tp->stats.idleThreads++; tp->stats.totalWorkTime += (double)StatsTime(NULL) - (double)start; StatsTime(&start); if (persistent == 0) { tp->stats.workerThreads--; } else if (persistent == 1) { /* Persistent thread becomes a regular thread */ tp->persistentThreads--; } /* Check for a job or shutdown */ while (tp->lowJobQ.size == 0 && tp->medJobQ.size == 0 && tp->highJobQ.size == 0 && !tp->persistentJob && !tp->shutdown) { /* If wait timed out and we currently have more than the * min threads, or if we have more than the max threads * (only possible if the attributes have been reset) * let this thread die. */ if ((retCode == ETIMEDOUT && tp->totalThreads > tp->attr.minThreads) || (tp->attr.maxThreads != -1 && tp->totalThreads > tp->attr.maxThreads)) { tp->stats.idleThreads--; goto exit_function; } SetRelTimeout(&timeout, tp->attr.maxIdleTime); /* wait for a job up to the specified max time */ retCode = ithread_cond_timedwait( &tp->condition, &tp->mutex, &timeout); } tp->stats.idleThreads--; /* idle time */ tp->stats.totalIdleTime += (double)StatsTime(NULL) - (double)start; /* work time */ StatsTime(&start); /* bump priority of starved jobs */ BumpPriority(tp); /* if shutdown then stop */ if (tp->shutdown) { goto exit_function; } else { /* Pick up persistent job if available */ if (tp->persistentJob) { job = tp->persistentJob; tp->persistentJob = NULL; tp->persistentThreads++; persistent = 1; ithread_cond_broadcast(&tp->start_and_shutdown); } else { tp->stats.workerThreads++; persistent = 0; /* Pick the highest priority job */ if (tp->highJobQ.size > 0) { head = ListHead(&tp->highJobQ); if (head == NULL) { tp->stats.workerThreads--; goto exit_function; } job = (ThreadPoolJob *) head->item; CalcWaitTime(tp, HIGH_PRIORITY, job); ListDelNode(&tp->highJobQ, head, 0); } else if (tp->medJobQ.size > 0) { head = ListHead(&tp->medJobQ); if (head == NULL) { tp->stats.workerThreads--; goto exit_function; } job = (ThreadPoolJob *) head->item; CalcWaitTime(tp, MED_PRIORITY, job); ListDelNode(&tp->medJobQ, head, 0); } else if (tp->lowJobQ.size > 0) { head = ListHead(&tp->lowJobQ); if (head == NULL) { tp->stats.workerThreads--; goto exit_function; } job = (ThreadPoolJob *) head->item; CalcWaitTime(tp, LOW_PRIORITY, job); ListDelNode(&tp->lowJobQ, head, 0); } else { /* Should never get here */ tp->stats.workerThreads--; goto exit_function; } } } tp->busyThreads++; ithread_mutex_unlock(&tp->mutex); /* In the future can log info */ if (SetPriority(job->priority) != 0) { } else { } /* run the job */ job->func(job->arg); /* return to Normal */ SetPriority(DEFAULT_PRIORITY); } exit_function: tp->totalThreads--; ithread_cond_broadcast(&tp->start_and_shutdown); ithread_mutex_unlock(&tp->mutex); ithread_cleanup_thread(); return NULL; }
/**************************************************************************** * Function: WorkerThread * * Description: * Implements a thread pool worker. * Worker waits for a job to become available. * Worker picks up persistent jobs first, high priority, med priority, * then low priority. * If worker remains idle for more than specified max, the worker * is released. * Internal Only. * Parameters: * void * arg -> is cast to ThreadPool * *****************************************************************************/ static void *WorkerThread( void *arg ) { time_t start = 0; ThreadPoolJob *job = NULL; ListNode *head = NULL; struct timespec timeout; int retCode = 0; int persistent = -1; ThreadPool *tp = ( ThreadPool *) arg; // allow static linking #ifdef WIN32 #ifdef PTW32_STATIC_LIB pthread_win32_thread_attach_np(); #endif #endif assert( tp != NULL ); // Increment total thread count ithread_mutex_lock( &tp->mutex ); tp->totalThreads++; ithread_cond_broadcast( &tp->start_and_shutdown ); ithread_mutex_unlock( &tp->mutex ); SetSeed(); StatsTime( &start ); while( 1 ) { ithread_mutex_lock( &tp->mutex ); if( job ) { FreeThreadPoolJob( tp, job ); job = NULL; } retCode = 0; tp->stats.idleThreads++; tp->stats.totalWorkTime += ( StatsTime( NULL ) - start ); // work time StatsTime( &start ); // idle time if( persistent == 1 ) { // Persistent thread // becomes a regular thread tp->persistentThreads--; } if( persistent == 0 ) { tp->stats.workerThreads--; } // Check for a job or shutdown while( tp->lowJobQ.size == 0 && tp->medJobQ.size == 0 && tp->highJobQ.size == 0 && !tp->persistentJob && !tp->shutdown ) { // If wait timed out // and we currently have more than the // min threads, or if we have more than the max threads // (only possible if the attributes have been reset) // let this thread die. if( ( retCode == ETIMEDOUT && tp->totalThreads > tp->attr.minThreads ) || ( tp->attr.maxThreads != -1 && tp->totalThreads > tp->attr.maxThreads ) ) { tp->stats.idleThreads--; tp->totalThreads--; ithread_cond_broadcast( &tp->start_and_shutdown ); ithread_mutex_unlock( &tp->mutex ); #ifdef WIN32 #ifdef PTW32_STATIC_LIB // allow static linking pthread_win32_thread_detach_np (); #endif #endif return NULL; } SetRelTimeout( &timeout, tp->attr.maxIdleTime ); // wait for a job up to the specified max time retCode = ithread_cond_timedwait( &tp->condition, &tp->mutex, &timeout ); } tp->stats.idleThreads--; tp->stats.totalIdleTime += ( StatsTime( NULL ) - start ); // idle time StatsTime( &start ); // work time // bump priority of starved jobs BumpPriority( tp ); // if shutdown then stop if( tp->shutdown ) { tp->totalThreads--; ithread_cond_broadcast( &tp->start_and_shutdown ); ithread_mutex_unlock( &tp->mutex ); #ifdef WIN32 #ifdef PTW32_STATIC_LIB // allow static linking pthread_win32_thread_detach_np (); #endif #endif return NULL; } else { // Pick up persistent job if available if( tp->persistentJob ) { job = tp->persistentJob; tp->persistentJob = NULL; tp->persistentThreads++; persistent = 1; ithread_cond_broadcast( &tp->start_and_shutdown ); } else { tp->stats.workerThreads++; persistent = 0; // Pick the highest priority job if( tp->highJobQ.size > 0 ) { head = ListHead( &tp->highJobQ ); job = ( ThreadPoolJob *) head->item; CalcWaitTime( tp, HIGH_PRIORITY, job ); ListDelNode( &tp->highJobQ, head, 0 ); } else if( tp->medJobQ.size > 0 ) { head = ListHead( &tp->medJobQ ); job = ( ThreadPoolJob *) head->item; CalcWaitTime( tp, MED_PRIORITY, job ); ListDelNode( &tp->medJobQ, head, 0 ); } else if( tp->lowJobQ.size > 0 ) { head = ListHead( &tp->lowJobQ ); job = ( ThreadPoolJob *) head->item; CalcWaitTime( tp, LOW_PRIORITY, job ); ListDelNode( &tp->lowJobQ, head, 0 ); } else { // Should never get here assert( 0 ); tp->stats.workerThreads--; tp->totalThreads--; ithread_cond_broadcast( &tp->start_and_shutdown ); ithread_mutex_unlock( &tp->mutex ); return NULL; } } } ithread_mutex_unlock( &tp->mutex ); if( SetPriority( job->priority ) != 0 ) { // In the future can log // info } else { // In the future can log // info } // run the job job->func( job->arg ); // return to Normal SetPriority( DEFAULT_PRIORITY ); } }
/**************************************************************************** * Function: ThreadPoolRemove * * Description: * Removes a job from the thread pool. * Can only remove jobs which are not * currently running. * Parameters: * tp - valid thread pool pointer * jobId - id of job * ThreadPoolJob *out - space for removed job. * Can be null if not needed. * * Returns: * 0 on success. INVALID_JOB_ID on failure. *****************************************************************************/ int ThreadPoolRemove( ThreadPool *tp, int jobId, ThreadPoolJob *out ) { ThreadPoolJob *temp = NULL; int ret = INVALID_JOB_ID; ListNode *tempNode = NULL; ThreadPoolJob dummy; assert( tp != NULL ); if( tp == NULL ) { return EINVAL; } if( out == NULL ) { out = &dummy; } dummy.jobId = jobId; ithread_mutex_lock( &tp->mutex ); tempNode = ListFind( &tp->highJobQ, NULL, &dummy ); if( tempNode ) { temp = (ThreadPoolJob *)tempNode->item; *out = *temp; ListDelNode( &tp->highJobQ, tempNode, 0 ); FreeThreadPoolJob( tp, temp ); ithread_mutex_unlock( &tp->mutex ); return 0; } tempNode = ListFind( &tp->medJobQ, NULL, &dummy ); if( tempNode ) { temp = (ThreadPoolJob *)tempNode->item; *out = *temp; ListDelNode( &tp->medJobQ, tempNode, 0 ); FreeThreadPoolJob( tp, temp ); ithread_mutex_unlock( &tp->mutex ); return 0; } tempNode = ListFind( &tp->lowJobQ, NULL, &dummy ); if( tempNode ) { temp = (ThreadPoolJob *)tempNode->item; *out = *temp; ListDelNode( &tp->lowJobQ, tempNode, 0 ); FreeThreadPoolJob( tp, temp ); ithread_mutex_unlock( &tp->mutex ); return 0; } if( tp->persistentJob && tp->persistentJob->jobId == jobId ) { *out = *tp->persistentJob; FreeThreadPoolJob( tp, tp->persistentJob ); tp->persistentJob = NULL; ithread_mutex_unlock( &tp->mutex ); return 0; } ithread_mutex_unlock( &tp->mutex ); return ret; }