Exemplo n.º 1
0
/********************************************************************************
 * upnp_igd_destroy
 *
 * Description:
 *       Destroy an existing uPnP IGD context.
 *
 * Parameters:
 *   igd_ctxt -- The upnp igd context
 *
 ********************************************************************************/
void upnp_igd_destroy(upnp_igd_context* igd_ctxt) {
	/* Stop client if started */
	if(igd_ctxt->upnp_handle != -1) {
		upnp_igd_stop(igd_ctxt);
	}

	upnp_context_free_callbacks(igd_ctxt);
	
	UpnpFinish();
	
	ithread_mutex_destroy(&igd_ctxt->devices_mutex);

	ithread_mutex_destroy(&igd_ctxt->callback_mutex);
	
	ithread_cond_destroy(&igd_ctxt->client_cond);
	ithread_mutex_destroy(&igd_ctxt->client_mutex);
	
	ithread_cond_destroy(&igd_ctxt->timer_cond);
	ithread_mutex_destroy(&igd_ctxt->timer_mutex);

	ithread_mutex_destroy(&igd_ctxt->print_mutex);
	
	ithread_mutex_destroy(&igd_ctxt->mutex);
	
	free(igd_ctxt);
}
Exemplo n.º 2
0
/************************************************************************
 * Function: TimerThreadInit
 * 
 *  Description:
 *     Initializes and starts timer thread.
 *
 *  Parameters:
 *             timer - valid timer thread pointer.
 *             tp  - valid thread pool to use. Must be
 *                   started. Must be valid for lifetime
 *                   of timer.  Timer must be shutdown
 *                   BEFORE thread pool.
 *  Return:
 *            0 on success, nonzero on failure
 *            Returns error from ThreadPoolAddPersistent if failure.
 ************************************************************************/
int
TimerThreadInit( TimerThread * timer,
                 ThreadPool * tp )
{

    int rc = 0;

    ThreadPoolJob timerThreadWorker;

    assert( timer != NULL );
    assert( tp != NULL );

    if( ( timer == NULL ) || ( tp == NULL ) ) {
        return EINVAL;
    }

    rc += ithread_mutex_init( &timer->mutex, NULL );

    assert( rc == 0 );

    rc += ithread_mutex_lock( &timer->mutex );
    assert( rc == 0 );

    rc += ithread_cond_init( &timer->condition, NULL );
    assert( rc == 0 );

    rc += FreeListInit( &timer->freeEvents, sizeof( TimerEvent ), 100 );
    assert( rc == 0 );

    timer->shutdown = 0;
    timer->tp = tp;
    timer->lastEventId = 0;
    rc += ListInit( &timer->eventQ, NULL, NULL );

    assert( rc == 0 );

    if( rc != 0 ) {
        rc = EAGAIN;
    } else {

        TPJobInit( &timerThreadWorker, TimerThreadWorker, timer );
        TPJobSetPriority( &timerThreadWorker, HIGH_PRIORITY );

        rc = ThreadPoolAddPersistent( tp, &timerThreadWorker, NULL );
    }

    ithread_mutex_unlock( &timer->mutex );

    if( rc != 0 ) {
        ithread_cond_destroy( &timer->condition );
        ithread_mutex_destroy( &timer->mutex );
        FreeListDestroy( &timer->freeEvents );
        ListDestroy( &timer->eventQ, 0 );
    }

    return rc;

}
Exemplo 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;
}
Exemplo n.º 4
0
/********************************************************************************
 * upnp_igd_create
 *
 * Description:
 *       Create and  return uPnP IGD context if there is no error otherwise
 *       NULL.
 *
 * Parameters:
 *   cb_fct    -- The function to call back for each events
 *   print_fct -- The function used for print logs
 *   cookie    -- The cookie pass in cb_fct or print_fct
 *
 ********************************************************************************/
upnp_igd_context* upnp_igd_create(upnp_igd_callback_function cb_fct, upnp_igd_print_function print_fct, const char *address, void *cookie) {
	int ret;
	unsigned short port = 0;
	const char *ip_address = address;
	upnp_igd_context *igd_ctxt = (upnp_igd_context*)malloc(sizeof(upnp_igd_context));
	igd_ctxt->devices = NULL;
	igd_ctxt->callback_fct = cb_fct;
	igd_ctxt->callback_events = NULL;
	igd_ctxt->print_fct = print_fct;
	igd_ctxt->cookie = cookie;
	igd_ctxt->max_adv_timeout = 60*3;
	igd_ctxt->timer_timeout = igd_ctxt->max_adv_timeout/2;
	igd_ctxt->upnp_handle = -1;
	igd_ctxt->client_count = 0;
	igd_ctxt->timer_thread = (ithread_t)NULL;

	/* Initialize mutex */
	{
		ithread_mutexattr_t attr;
		ithread_mutexattr_init(&attr);
		ithread_mutexattr_setkind_np(&attr, ITHREAD_MUTEX_RECURSIVE_NP);
		ithread_mutex_init(&igd_ctxt->mutex, &attr);
		ithread_mutexattr_destroy(&attr);
	}
	
	/* Initialize print mutex */
	{
		ithread_mutexattr_t attr;
		ithread_mutexattr_init(&attr);
		ithread_mutexattr_setkind_np(&attr, ITHREAD_MUTEX_RECURSIVE_NP);
		ithread_mutex_init(&igd_ctxt->print_mutex, &attr);
		ithread_mutexattr_destroy(&attr);
	}

	/* Initialize callback mutex */
	{
		ithread_mutexattr_t attr;
		ithread_mutexattr_init(&attr);
		ithread_mutexattr_setkind_np(&attr, ITHREAD_MUTEX_RECURSIVE_NP);
		ithread_mutex_init(&igd_ctxt->callback_mutex, &attr);
		ithread_mutexattr_destroy(&attr);
	}

	/* Initialize device mutex */
	{
		ithread_mutexattr_t attr;
		ithread_mutexattr_init(&attr);
		ithread_mutexattr_setkind_np(&attr, ITHREAD_MUTEX_RECURSIVE_NP);
		ithread_mutex_init(&igd_ctxt->devices_mutex, &attr);
		ithread_mutexattr_destroy(&attr);
	}

	/* Initialize timer stuff */
	{
		ithread_mutexattr_t attr;
		ithread_mutexattr_init(&attr);
		ithread_mutexattr_setkind_np(&attr, ITHREAD_MUTEX_FAST_NP);
		ithread_mutex_init(&igd_ctxt->timer_mutex, &attr);
		ithread_mutexattr_destroy(&attr);
		ithread_cond_init(&igd_ctxt->timer_cond, NULL);
	}
	
	/* Initialize client stuff */
	{
		ithread_mutexattr_t attr;
		ithread_mutexattr_init(&attr);
		ithread_mutexattr_setkind_np(&attr, ITHREAD_MUTEX_RECURSIVE_NP);
		ithread_mutex_init(&igd_ctxt->client_mutex, &attr);
		ithread_mutexattr_destroy(&attr);
		ithread_cond_init(&igd_ctxt->client_cond, NULL);
	}

	upnp_igd_print(igd_ctxt, UPNP_IGD_DEBUG, "Initializing uPnP IGD with ipaddress:%s port:%u", ip_address ? ip_address : "{NULL}", port);

	ret = UpnpInit(ip_address, port);
	if (ret != UPNP_E_SUCCESS) {
		upnp_igd_print(igd_ctxt, UPNP_IGD_ERROR, "UpnpInit() Error: %d", ret);
		UpnpFinish();
		ithread_mutex_destroy(&igd_ctxt->print_mutex);
		ithread_mutex_destroy(&igd_ctxt->devices_mutex);
		ithread_mutex_destroy(&igd_ctxt->timer_mutex);
		ithread_cond_destroy(&igd_ctxt->timer_cond);
		ithread_mutex_destroy(&igd_ctxt->callback_mutex);
		ithread_mutex_destroy(&igd_ctxt->client_mutex);
		ithread_cond_destroy(&igd_ctxt->client_cond);
		ithread_mutex_destroy(&igd_ctxt->mutex);
		free(igd_ctxt);
		return NULL;
	}
	if (!ip_address) {
		ip_address = UpnpGetServerIpAddress();
	}
	if (!port) {
		port = UpnpGetServerPort();
	}

	upnp_igd_print(igd_ctxt, UPNP_IGD_MESSAGE, "uPnP IGD Initialized ipaddress:%s port:%u", ip_address ? ip_address : "{NULL}", port);

	return igd_ctxt;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
int ThreadPoolInit(ThreadPool *tp, ThreadPoolAttr *attr)
{
	int retCode = 0;
	int i = 0;

	if (!tp) {
		return EINVAL;
	}

	retCode += ithread_mutex_init(&tp->mutex, NULL);
	retCode += ithread_mutex_lock(&tp->mutex);

	retCode += ithread_cond_init(&tp->condition, NULL);
	retCode += ithread_cond_init(&tp->start_and_shutdown, NULL);
	if (retCode) {
		ithread_mutex_unlock(&tp->mutex);
		ithread_mutex_destroy(&tp->mutex);
		ithread_cond_destroy(&tp->condition);
		ithread_cond_destroy(&tp->start_and_shutdown);
		return EAGAIN;
	}
	if (attr) {
		tp->attr = *attr;
	} else {
		TPAttrInit(&tp->attr);
	}
	if (SetPolicyType(tp->attr.schedPolicy) != 0) {
		ithread_mutex_unlock(&tp->mutex);
		ithread_mutex_destroy(&tp->mutex);
		ithread_cond_destroy(&tp->condition);
		ithread_cond_destroy(&tp->start_and_shutdown);

		return INVALID_POLICY;
	}
	retCode += FreeListInit(
		&tp->jobFreeList, sizeof(ThreadPoolJob), JOBFREELISTSIZE);
	StatsInit(&tp->stats);
	retCode += ListInit(&tp->highJobQ, CmpThreadPoolJob, NULL);
	retCode += ListInit(&tp->medJobQ, CmpThreadPoolJob, NULL);
	retCode += ListInit(&tp->lowJobQ, CmpThreadPoolJob, NULL);
	if (retCode) {
		retCode = EAGAIN;
	} else {
		tp->persistentJob = NULL;
		tp->lastJobId = 0;
		tp->shutdown = 0;
		tp->totalThreads = 0;
		tp->busyThreads = 0;
		tp->persistentThreads = 0;
		tp->pendingWorkerThreadStart = 0;
		for (i = 0; i < tp->attr.minThreads; ++i) {
			retCode = CreateWorker(tp);
			if (retCode) {
				break;
			}
		}
	}

	ithread_mutex_unlock(&tp->mutex);

	if (retCode) {
		/* clean up if the min threads could not be created */
		ThreadPoolShutdown(tp);
	}

	return retCode;
}
Exemplo n.º 7
0
/****************************************************************************
 * Function: ThreadPoolInit
 *
 *  Description:
 *      Initializes and starts ThreadPool. Must be called first.
 *      And only once for ThreadPool.
 *  Parameters:
 *      tp  - must be valid, non null, pointer to ThreadPool.
 *      minWorkerThreads - minimum number of worker threads
 *                         thread pool will never have less than this
 *                         number of threads.
 *      maxWorkerThreads - maximum number of worker threads
 *                         thread pool will never have more than this
 *                         number of threads.
 *      maxIdleTime      - maximum time that a worker thread will spend
 *                         idle. If a worker is idle longer than this
 *                         time and there are more than the min
 *                         number of workers running, than the
 *                         worker thread exits.
 *      jobsPerThread    - ratio of jobs to thread to try and maintain
 *                         if a job is scheduled and the number of jobs per
 *                         thread is greater than this number,and
 *                         if less than the maximum number of
 *                         workers are running then a new thread is
 *                         started to help out with efficiency.
 *      schedPolicy      - scheduling policy to try and set (OS dependent)
 *  Returns:
 *      0 on success, nonzero on failure.
 *      EAGAIN if not enough system resources to create minimum threads.
 *      INVALID_POLICY if schedPolicy can't be set
 *      EMAXTHREADS if minimum threads is greater than maximum threads
 *****************************************************************************/
int ThreadPoolInit( ThreadPool *tp, ThreadPoolAttr *attr )
{
	int retCode = 0;
	int i = 0;
	//printf("%s, %d\n", __FUNCTION__, __LINE__);

	assert( tp != NULL );
	if( tp == NULL ) {
		return EINVAL;
	}
#ifdef WIN32
#ifdef PTW32_STATIC_LIB
	pthread_win32_process_attach_np();
#endif
#endif
	//printf("%s, %d\n", __FUNCTION__, __LINE__);

	retCode += ithread_mutex_init( &tp->mutex, NULL );
	assert( retCode == 0 );

	retCode += ithread_mutex_lock( &tp->mutex );
	assert( retCode == 0 );

	retCode += ithread_cond_init( &tp->condition, NULL );
	assert( retCode == 0 );

	retCode += ithread_cond_init( &tp->start_and_shutdown, NULL );
	assert( retCode == 0 );
	//printf("%s, %d\n", __FUNCTION__, __LINE__);

	if( retCode != 0 ) {
		return EAGAIN;
	}

	if( attr ) {
		tp->attr = ( *attr );
	} else {
		TPAttrInit( &tp->attr );
	}
	//printf("%s, %d, minthreads: %d\n", __FUNCTION__, __LINE__, tp->attr.minThreads);

	if( SetPolicyType( tp->attr.schedPolicy ) != 0 ) {
		ithread_mutex_unlock( &tp->mutex );
		ithread_mutex_destroy( &tp->mutex );
		ithread_cond_destroy( &tp->condition );
		ithread_cond_destroy( &tp->start_and_shutdown );
		return INVALID_POLICY;
	}
	//printf("%s, %d\n", __FUNCTION__, __LINE__);

	retCode += FreeListInit(
		&tp->jobFreeList, sizeof( ThreadPoolJob ), JOBFREELISTSIZE );
	assert( retCode == 0 );

	StatsInit( &tp->stats );

	retCode += ListInit( &tp->highJobQ, CmpThreadPoolJob, NULL );
	assert( retCode == 0 );

	retCode += ListInit( &tp->medJobQ, CmpThreadPoolJob, NULL );
	assert( retCode == 0 );

	retCode += ListInit( &tp->lowJobQ, CmpThreadPoolJob, NULL );
	assert( retCode == 0 );
	//printf("%s, %d, retcode is %d\n", __FUNCTION__, __LINE__, retCode);

	if( retCode != 0 ) {
		retCode = EAGAIN;
		//printf("%s, %d\n", __FUNCTION__, __LINE__);
	} else {
	//printf("%s, %d\n", __FUNCTION__, __LINE__);
		tp->persistentJob = NULL;
		tp->lastJobId = 0;
		tp->shutdown = 0;
		tp->totalThreads = 0;
		tp->persistentThreads = 0;
		//printf("%s, %d\n", __FUNCTION__, __LINE__);
		for( i = 0; i < tp->attr.minThreads; ++i ) {
			if( ( retCode = CreateWorker( tp ) ) != 0 ) {
				//printf("%s, %d\n", __FUNCTION__, __LINE__);

				break;
			}
		}
	}
	//printf("%s, %d\n", __FUNCTION__, __LINE__);

	ithread_mutex_unlock( &tp->mutex );

	if( retCode != 0 ) {
		// clean up if the min threads could not be created
		ThreadPoolShutdown( tp );
	}
	//printf("%s, %d\n", __FUNCTION__, __LINE__);

	return retCode;
}