Ejemplo n.º 1
0
/********************************************************************************
 * upnp_igd_stop
 *
 * Description:
 *       Stop uPnP IGD context.
 *
 * Parameters:
 *   igd_ctxt -- The upnp igd context
 *
 ********************************************************************************/
int upnp_igd_stop(upnp_igd_context *igd_ctxt) {
	ithread_mutex_lock(&igd_ctxt->mutex);
	
	if(igd_ctxt->upnp_handle == -1) {
		upnp_igd_print(igd_ctxt, UPNP_IGD_WARNING, "uPnP IGD client already stopped...");
		ithread_mutex_unlock(&igd_ctxt->mutex);
		return -1;
	}

	ithread_mutex_lock(&igd_ctxt->timer_mutex);
	ithread_cond_signal(&igd_ctxt->timer_cond);
	ithread_mutex_unlock(&igd_ctxt->timer_mutex);
	ithread_join(igd_ctxt->timer_thread, NULL);

	upnp_igd_remove_all(igd_ctxt);

	UpnpUnRegisterClient(igd_ctxt->upnp_handle);
	
	// Wait that all clients are finish the callback
	// Doing UpnpUnRegisterClient no more callbacks are bone
	// But current running clients are still here
	ithread_mutex_lock(&igd_ctxt->client_mutex);
	while(igd_ctxt->client_count > 0) {	
		ithread_cond_wait(&igd_ctxt->client_cond, &igd_ctxt->client_mutex);	
	}
	ithread_mutex_unlock(&igd_ctxt->client_mutex);
		
	igd_ctxt->upnp_handle = -1;
	
	ithread_mutex_unlock(&igd_ctxt->mutex);

	// Handle remaining callbacks	
	upnp_context_handle_callbacks(igd_ctxt);
	return 0;
}
Ejemplo n.º 2
0
/****************************************************************************
 * Function: ThreadPoolAddPersistent
 *
 *  Description:
 *      Adds a long term job to the thread pool.
 *      Job will be run as soon as possible.
 *      Call will block until job is scheduled.
 *  Parameters:
 *      tp - valid thread pool pointer
 *      job-> valid ThreadPoolJob pointer with following fields
 *          func - ThreadFunction to run
 *          arg - argument to function.
 *          priority - priority of job.
 *          free_function - function to use when freeing argument
 *  Returns:
 *      0 on success, nonzero on failure
 *      EOUTOFMEM not enough memory to add job.
 *      EMAXTHREADS not enough threads to add persistent job.
 *****************************************************************************/
int ThreadPoolAddPersistent( ThreadPool *tp, ThreadPoolJob *job, int *jobId )
{
	int tempId = -1;
	ThreadPoolJob *temp = NULL;

	assert( tp != NULL );
	assert( job != NULL );
	if( ( tp == NULL ) || ( job == NULL ) ) {
		return EINVAL;
	}

	if( jobId == NULL ) {
		jobId = &tempId;
	}

	*jobId = INVALID_JOB_ID;

	ithread_mutex_lock( &tp->mutex );

	assert( job->priority == LOW_PRIORITY ||
	        job->priority == MED_PRIORITY ||
	        job->priority == HIGH_PRIORITY );

	// Create A worker if less than max threads running
	if( tp->totalThreads < tp->attr.maxThreads ) {
		CreateWorker( tp );
	} else {
		// if there is more than one worker thread
		// available then schedule job, otherwise fail
		if( tp->totalThreads - tp->persistentThreads - 1 == 0 ) {
			ithread_mutex_unlock( &tp->mutex );
			return EMAXTHREADS;
		}
	}

	temp = CreateThreadPoolJob( job, tp->lastJobId, tp );
	if( temp == NULL ) {
		ithread_mutex_unlock( &tp->mutex );
		return EOUTOFMEM;
	}

	tp->persistentJob = temp;

	// Notify a waiting thread
	ithread_cond_signal( &tp->condition );

	// wait until long job has been picked up
	while( tp->persistentJob != NULL ) {
		ithread_cond_wait( &tp->start_and_shutdown, &tp->mutex );
	}

	*jobId = tp->lastJobId++;
	ithread_mutex_unlock( &tp->mutex );

	return 0;
}
Ejemplo n.º 3
0
/************************************************************************
 * 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;
}
Ejemplo n.º 4
0
/*!
 * \brief Creates a worker thread, if the thread pool does not already have
 * max threads.
 *
 * \remark The ThreadPool object mutex must be locked prior to calling this
 * function.
 *
 * \internal
 *
 * \return
 *	\li \c 0 on success, < 0 on failure.
 *	\li \c EMAXTHREADS if already max threads reached.
 *	\li \c EAGAIN if system can not create thread.
 */
static int CreateWorker(
	/*! A pointer to the ThreadPool object. */
	ThreadPool *tp)
{
	ithread_t temp;
	int rc = 0;
	ithread_attr_t attr;

	/* if a new worker is the process of starting, wait until it fully starts */
	while (tp->pendingWorkerThreadStart) {
		ithread_cond_wait(&tp->start_and_shutdown, &tp->mutex);
	}

	if (tp->attr.maxThreads != INFINITE_THREADS &&
	    tp->totalThreads + 1 > tp->attr.maxThreads) {
		return EMAXTHREADS;
	}
	ithread_attr_init(&attr);
	ithread_attr_setstacksize(&attr, tp->attr.stackSize);
	ithread_attr_setdetachstate(&attr, ITHREAD_CREATE_DETACHED);
	rc = ithread_create(&temp, &attr, WorkerThread, tp);
	ithread_attr_destroy(&attr);
	if (rc == 0) {
		rc = ithread_detach(temp);
		/* ithread_detach will return EINVAL if thread has been
		 successfully detached by ithread_create */
		if (rc == EINVAL)
			rc = 0;
		tp->pendingWorkerThreadStart = 1;
		/* wait until the new worker thread starts */
		while (tp->pendingWorkerThreadStart) {
			ithread_cond_wait(&tp->start_and_shutdown, &tp->mutex);
		}
	}
	if (tp->stats.maxThreads < tp->totalThreads) {
		tp->stats.maxThreads = tp->totalThreads;
	}

	return rc;
}
Ejemplo n.º 5
0
int ThreadPoolAddPersistent(ThreadPool *tp, ThreadPoolJob *job, int *jobId)
{
	int ret = 0;
	int tempId = -1;
	ThreadPoolJob *temp = NULL;

	if (!tp || !job) {
		return EINVAL;
	}
	if (!jobId) {
		jobId = &tempId;
	}
	*jobId = INVALID_JOB_ID;

	ithread_mutex_lock(&tp->mutex);

	/* Create A worker if less than max threads running */
	if (tp->totalThreads < tp->attr.maxThreads) {
		CreateWorker(tp);
	} else {
		/* if there is more than one worker thread
		 * available then schedule job, otherwise fail */
		if (tp->totalThreads - tp->persistentThreads - 1 == 0) {
			ret = EMAXTHREADS;
			goto exit_function;
		}
	}
	temp = CreateThreadPoolJob(job, tp->lastJobId, tp);
	if (!temp) {
		ret = EOUTOFMEM;
		goto exit_function;
	}
	tp->persistentJob = temp;

	/* Notify a waiting thread */
	ithread_cond_signal(&tp->condition);

	/* wait until long job has been picked up */
	while (tp->persistentJob)
		ithread_cond_wait(&tp->start_and_shutdown, &tp->mutex);
	*jobId = tp->lastJobId++;

exit_function:
	ithread_mutex_unlock(&tp->mutex);

	return ret;
}
Ejemplo n.º 6
0
/****************************************************************************
 * Function: CreateWorker
 *
 *  Description:
 *      Creates a worker thread, if the thread pool
 *      does not already have max threads.
 *      Internal to thread pool.
 *  Parameters:
 *      ThreadPool *tp
 *
 *  Returns:
 *      0 on success, <0 on failure
 *      EMAXTHREADS if already max threads reached
 *      EAGAIN if system can not create thread
 *
 *****************************************************************************/
static int CreateWorker( ThreadPool *tp )
{
	//printf("%s, %d\n", __FUNCTION__, __LINE__);

	ithread_t temp;
	int rc = 1;
	int currentThreads = tp->totalThreads + 1;
	//printf("%s, %d\n", __FUNCTION__, __LINE__);

	assert( tp != NULL );

	if ( tp->attr.maxThreads != INFINITE_THREADS &&
	     currentThreads > tp->attr.maxThreads ) {
		return EMAXTHREADS;
	}
	//printf("%s, %d\n", __FUNCTION__, __LINE__);

	//rc = ithread_create( &temp, NULL, WorkerThread, tp );

	rc = pthread_create( &temp, NULL, WorkerThread, tp );
	//printf("%s, %d, %d\n", __FUNCTION__, __LINE__, rc);
	//pthread_join(temp, NULL);
	
	//printf("%s, %d\n", __FUNCTION__, __LINE__);
	if( rc == 0 ) {
		rc = ithread_detach( temp );
		//printf("%s, %d, totalThreads: %d, currentThreads: %d\n", __FUNCTION__, __LINE__, tp->totalThreads, currentThreads);
		while( tp->totalThreads < currentThreads ) {
			//printf("%s, %d\n", __FUNCTION__, __LINE__, tp->totalThreads, currentThreads);
			ithread_cond_wait( &tp->start_and_shutdown, &tp->mutex );
		}
	}
	//printf("%s, %d\n", __FUNCTION__, __LINE__);

	if( tp->stats.maxThreads < tp->totalThreads ) {
		tp->stats.maxThreads = tp->totalThreads;
	}
	//printf("%s, %d\n", __FUNCTION__, __LINE__);

	return rc;
}
Ejemplo n.º 7
0
/****************************************************************************
 * 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 );
        }

    }
}
Ejemplo n.º 8
0
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;
}