Example #1
0
/********************************************************************************
 * upnp_igd_timer_loop
 *
 * Description:
 *       Thread function which check the timeouts.
 *
 * Parameters:
 *   args -- The upnp igd context
 *
 ********************************************************************************/
void *upnp_igd_timer_loop(void *args) {
	upnp_igd_context *igd_ctxt = (upnp_igd_context*)args;
	struct timespec ts;
	struct timeval tp;

	/* how often to verify the timeouts, in seconds */
	int incr = igd_ctxt->timer_timeout;

	// Update timeout
	gettimeofday(&tp, NULL);
	ts.tv_sec  = tp.tv_sec;
	ts.tv_nsec = tp.tv_usec * 1000;
	ts.tv_sec += incr;
	ithread_mutex_lock(&igd_ctxt->timer_mutex);
	while(ithread_cond_timedwait(&igd_ctxt->timer_cond, &igd_ctxt->timer_mutex, &ts) == ETIMEDOUT) {
		upnp_igd_verify_timeouts(igd_ctxt, incr);
		upnp_context_handle_callbacks(igd_ctxt);

		// Update timeout
		gettimeofday(&tp, NULL);
		ts.tv_sec  = tp.tv_sec;
		ts.tv_nsec = tp.tv_usec * 1000;
		ts.tv_sec += incr;
	}
	ithread_mutex_unlock(&igd_ctxt->timer_mutex);

	return NULL;
}
Example #2
0
int wphoto_upnp_handshake(void)
{
	int ret = -1, err;
	char descurl[256];
	const char *desc_xml = "MobileDevDesc.xml";
	struct timespec timer;
	int camera_responded_save;
	char *camera_url_save;
	int pinged_camera;

	ithread_mutex_init(&state_mutex, NULL);
	ithread_cond_init(&state_cond, NULL);
	camera_url = NULL;
	camera_responded = 0;
	err = UpnpInit(NULL, 0);
	if (err != UPNP_E_SUCCESS) {
		upnp_perror("UpnpInit", err);
		goto err_init;
	}
	server_ip = UpnpGetServerIpAddress();
	server_port = UpnpGetServerPort();
	if (init_xml_docs() < 0) {
		perror("init_xml_docs");
		goto err_init;
	}

	printf("address: %s:%d\n", server_ip, server_port);

	snprintf(descurl, sizeof(descurl), "http://%s:%d/%s",
			server_ip, server_port, desc_xml);
	err = web_add_callback("/MobileDevDesc.xml", web_MobileDevDesc, NULL);
	if (err) {
		perror("web_add_callback");
		goto err_init;
	}
	err = web_add_callback("/desc_iml/CameraConnectedMobile.xml",
			web_CameraConnectedMobile, NULL);
	if (err) {
		perror("web_add_callback");
		goto err_init;
	}
	if (web_start() < 0) {
		printf("web_init error\n");
		goto err_init;
	}
	err = UpnpRegisterRootDevice(descurl, upnp_device_event_handler,
			&device_handle, &device_handle);
	if (err != UPNP_E_SUCCESS) {
		upnp_perror("UpnpRegisterRootDevice", err);
		goto err_init;
	}
	err = UpnpRegisterClient(upnp_client_event_handler,
			&client_handle, &client_handle);
	if (err != UPNP_E_SUCCESS) {
		upnp_perror("UpnpRegisterClient", err);
		goto err_register;
	}
	clock_gettime(CLOCK_REALTIME, &timer);
	discovery_timeout = 1;
	camera_responded_save = 0;
	camera_url_save = NULL;
	pinged_camera = 0;
	do {
		int wait_err;

		if (!camera_responded_save) {
			err = UpnpSendAdvertisement(device_handle, 0);
			if (err != UPNP_E_SUCCESS) {
				upnp_perror("UpnpSendAdvertisement", err);
				goto err_register;
			}
			printf("NOTIFY sent\n");
		}
		if (camera_url_save && !pinged_camera)
			if (ping_camera(camera_url_save) == 0)
				pinged_camera = 1;
		timer.tv_sec += ADVERTISEMENT_INTERVAL;
wait:
		ithread_mutex_lock(&state_mutex);
		wait_err = 0;
		while (camera_responded == camera_responded_save &&
				strcmp_null(camera_url, camera_url_save) == 0 &&
				!discovery_timeout && wait_err == 0)
			wait_err = ithread_cond_timedwait(
					&state_cond, &state_mutex, &timer);
		camera_responded_save = camera_responded;
		if (strcmp_null(camera_url, camera_url_save) != 0) {
			free(camera_url_save);
			camera_url_save = strdup(camera_url);
		}
		/*
		 * Once we have the camera url, we stop sending M-SEARCH
		 * requests
		 */
		if (discovery_timeout && !camera_url_save) {
			err = UpnpSearchAsync(client_handle, MSEARCH_INTERVAL,
					CAMERA_SERVICE_NAME, (void*)42);
			if (err != UPNP_E_SUCCESS) {
				upnp_perror("UpnpSearchAsync", err);
				goto err_register;
			}
			printf("M-SEARCH sent\n");
		}
		discovery_timeout = 0;
		ithread_mutex_unlock(&state_mutex);
		if (wait_err != ETIMEDOUT &&
				(!pinged_camera || !camera_responded_save))
			goto wait;
	} while (!pinged_camera || !camera_responded_save);
	return 0;
err_register:
	UpnpUnRegisterRootDevice(device_handle);
err_init:
	UpnpFinish();
	return ret;
}
Example #3
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;
}
Example #4
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 );
        }

    }
}
Example #5
0
/****************************************************************************
 * 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 );
	}
}