Exemple #1
0
/**
 * \internal Odpowiednik \c gethostbyname zapewniający współbieżność.
 *
 * Jeśli dany system dostarcza \c gethostbyname_r, używa się tej wersji, jeśli
 * nie, to zwykłej \c gethostbyname.
 *
 * \param hostname Nazwa serwera
 * \param addr Wskaźnik na rezultat rozwiązywania nazwy
 * \param pthread Flaga blokowania unicestwiania wątku podczas alokacji pamięci
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_gethostbyname_real(const char *hostname, struct in_addr *addr, int pthread)
{
#ifdef GG_CONFIG_HAVE_GETHOSTBYNAME_R
	char *buf = NULL;
	char *new_buf = NULL;
	struct hostent he;
	struct hostent *he_ptr = NULL;
	size_t buf_len = 1024;
	int result = -1;
	int h_errnop;
	int ret = 0;
#ifdef GG_CONFIG_HAVE_PTHREAD
	int old_state;
#endif

#ifdef GG_CONFIG_HAVE_PTHREAD
	pthread_cleanup_push(gg_gethostbyname_cleaner, &buf);

	if (pthread)
		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
#endif

	buf = malloc(buf_len);

#ifdef GG_CONFIG_HAVE_PTHREAD
	if (pthread)
		pthread_setcancelstate(old_state, NULL);
#endif

	if (buf != NULL) {
#ifndef sun
		while ((ret = gethostbyname_r(hostname, &he, buf, buf_len, &he_ptr, &h_errnop)) == ERANGE) {
#else
		while (((he_ptr = gethostbyname_r(hostname, &he, buf, buf_len, &h_errnop)) == NULL) && (errno == ERANGE)) {
#endif
			buf_len *= 2;

#ifdef GG_CONFIG_HAVE_PTHREAD
			if (pthread)
				pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
#endif

			new_buf = realloc(buf, buf_len);

			if (new_buf != NULL)
				buf = new_buf;

#ifdef GG_CONFIG_HAVE_PTHREAD
			if (pthread)
				pthread_setcancelstate(old_state, NULL);
#endif

			if (new_buf == NULL) {
				ret = ENOMEM;
				break;
			}
		}

		if (ret == 0 && he_ptr != NULL) {
			memcpy(addr, he_ptr->h_addr, sizeof(struct in_addr));
			result = 0;
		}

#ifdef GG_CONFIG_HAVE_PTHREAD
		if (pthread)
			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
#endif

		free(buf);
		buf = NULL;

#ifdef GG_CONFIG_HAVE_PTHREAD
		if (pthread)
			pthread_setcancelstate(old_state, NULL);
#endif
	}

#ifdef GG_CONFIG_HAVE_PTHREAD
	pthread_cleanup_pop(1);
#endif

	return result;
#else
	struct hostent *he;

	he = gethostbyname(hostname);

	if (he == NULL)
		return -1;

	memcpy(addr, he->h_addr, sizeof(struct in_addr));

	return 0;
#endif /* GG_CONFIG_HAVE_GETHOSTBYNAME_R */
}

/**
 * \internal Odpowiednik \c gethostbyname zapewniający współbieżność.
 *
 * Jeśli dany system dostarcza \c gethostbyname_r, używa się tej wersji, jeśli
 * nie, to zwykłej \c gethostbyname.
 *
 * \param hostname Nazwa serwera
 *
 * \return Zaalokowana struktura \c in_addr lub NULL w przypadku błędu.
 */
struct in_addr *gg_gethostbyname(const char *hostname)
{
	struct in_addr *addr;

	if (!(addr = (in_addr*)malloc(sizeof(struct in_addr))))
		return NULL;

	if (gg_gethostbyname_real(hostname, addr, 0)) {
		free(addr);
		return NULL;
	}
	return addr;
}

/**
 * \internal Struktura przekazywana do wątku rozwiązującego nazwę.
 */
struct gg_resolver_fork_data {
	int pid;		/*< Identyfikator procesu */
};

/**
 * \internal Rozwiązuje nazwę serwera w osobnym procesie.
 *
 * Połączenia asynchroniczne nie mogą blokować procesu w trakcie rozwiązywania
 * nazwy serwera. W tym celu tworzony jest potok, nowy proces i dopiero w nim
 * przeprowadzane jest rozwiązywanie nazwy. Deskryptor strony do odczytu 
 * zapisuje się w strukturze sieci i czeka na dane w postaci struktury
 * \c in_addr. Jeśli nie znaleziono nazwy, zwracana jest \c INADDR_NONE.
 *
 * \param fd Wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor
 *           potoku
 * \param priv_data Wskaźnik na zmienną, gdzie zostanie umieszczony wskaźnik
 *                  do numeru procesu potomnego rozwiązującego nazwę
 * \param hostname Nazwa serwera do rozwiązania
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
static int gg_resolver_fork_start(SOCKET *fd, void **priv_data, const char *hostname)
{
	struct gg_resolver_fork_data *data = NULL;
	struct in_addr addr;
	int new_errno;
	SOCKET pipes[2];

	gg_debug(GG_DEBUG_FUNCTION, "** gg_resolver_fork_start(%p, %p, \"%s\");\n", fd, priv_data, hostname);

	if (fd == NULL || priv_data == NULL || hostname == NULL) {
		gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() invalid arguments\n");
		errno = EFAULT;
		return -1;
	}

	data = (gg_resolver_fork_data*)malloc(sizeof(struct gg_resolver_fork_data));

	if (data == NULL) {
		gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() out of memory for resolver data\n");
		return -1;
	}

	if (pipe(pipes) == -1) {
		gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
		free(data);
		return -1;
	}

	data->pid = fork();

	if (data->pid == -1) {
		new_errno = errno;
		goto cleanup;
	}

	if (data->pid == 0) {
		gg_sock_close(pipes[0]);

		if ((addr.s_addr = inet_addr(hostname)) == INADDR_NONE) {
			/* W przypadku błędu gg_gethostbyname_real() zwróci -1
                         * i nie zmieni &addr. Tam jest już INADDR_NONE,
                         * więc nie musimy robić nic więcej. */
			gg_gethostbyname_real(hostname, &addr, 0);
		}

		if (gg_sock_write(pipes[1], &addr, sizeof(addr)) != sizeof(addr))
			exit(1);

		exit(0);
	}

	gg_sock_close(pipes[1]);

	gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() %p\n", data);

	*fd = pipes[0];
	*priv_data = data;

	return 0;

cleanup:
	free(data);
	gg_sock_close(pipes[0]);
	gg_sock_close(pipes[1]);

	errno = new_errno;

	return -1;
}

/**
 * \internal Usuwanie zasobów po procesie rozwiązywaniu nazwy.
 *
 * Funkcja wywoływana po zakończeniu rozwiązanywania nazwy lub przy zwalnianiu
 * zasobów sesji podczas rozwiązywania nazwy.
 *
 * \param priv_data Wskaźnik na zmienną przechowującą wskaźnik do prywatnych
 *                  danych
 * \param force Flaga usuwania zasobów przed zakończeniem działania
 */
static void gg_resolver_fork_cleanup(void **priv_data, int force)
{
	struct gg_resolver_fork_data *data;

	if (priv_data == NULL || *priv_data == NULL)
		return;

	data = (struct gg_resolver_fork_data*) *priv_data;
	*priv_data = NULL;

	if (force)
		kill(data->pid, SIGKILL);

	waitpid(data->pid, NULL, WNOHANG);

	free(data);
}

#ifdef GG_CONFIG_HAVE_PTHREAD

/**
 * \internal Struktura przekazywana do wątku rozwiązującego nazwę.
 */
struct gg_resolver_pthread_data {
	pthread_t thread;	/*< Identyfikator wątku */
	char *hostname;		/*< Nazwa serwera */
	SOCKET rfd;		/*< Deskryptor do odczytu */
	SOCKET wfd;		/*< Deskryptor do zapisu */
};

/**
 * \internal Usuwanie zasobów po wątku rozwiązywaniu nazwy.
 *
 * Funkcja wywoływana po zakończeniu rozwiązanywania nazwy lub przy zwalnianiu
 * zasobów sesji podczas rozwiązywania nazwy.
 *
 * \param priv_data Wskaźnik na zmienną przechowującą wskaźnik do prywatnych
 *                  danych
 * \param force Flaga usuwania zasobów przed zakończeniem działania
 */
static void gg_resolver_pthread_cleanup(void **priv_data, int force)
{
	struct gg_resolver_pthread_data *data;

	if (priv_data == NULL || *priv_data == NULL)
		return;

	data = (struct gg_resolver_pthread_data *) *priv_data;
	*priv_data = NULL;

	if (force) {
		pthread_cancel(&data->thread);
		pthread_join(&data->thread, NULL);
	}

	free(data->hostname);
	data->hostname = NULL;

	if (data->wfd != -1) {
		gg_sock_close(data->wfd);
		data->wfd = -1;
	}

	free(data);
}

/**
 * \internal Wątek rozwiązujący nazwę.
 *
 * \param arg Wskaźnik na strukturę \c gg_resolver_pthread_data
 */
static void *__stdcall gg_resolver_pthread_thread(void *arg)
{
	struct gg_resolver_pthread_data *data = (gg_resolver_pthread_data*)arg;
	struct in_addr addr;

	pthread_detach(pthread_self());

	if ((addr.s_addr = inet_addr(data->hostname)) == INADDR_NONE) {
		/* W przypadku błędu gg_gethostbyname_real() zwróci -1
                 * i nie zmieni &addr. Tam jest już INADDR_NONE,
                 * więc nie musimy robić nic więcej. */
		gg_gethostbyname_real(data->hostname, &addr, 1);
	}

	if (gg_sock_write(data->wfd, &addr, sizeof(addr)) == sizeof(addr))
		pthread_exit(NULL);
	else 
		pthread_exit((void*) -1);

	return NULL;	/* żeby kompilator nie marudził */
}

/**
 * \internal Rozwiązuje nazwę serwera w osobnym wątku.
 *
 * Funkcja działa analogicznie do \c gg_resolver_fork_start(), z tą różnicą,
 * że działa na wątkach, nie procesach. Jest dostępna wyłącznie gdy podczas
 * kompilacji włączono odpowiednią opcję.
 *
 * \param fd Wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor
 *           potoku
 * \param priv_data Wskaźnik na zmienną, gdzie zostanie umieszczony wskaźnik
 *                  do prywatnych danych wątku rozwiązującego nazwę
 * \param hostname Nazwa serwera do rozwiązania
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
static int gg_resolver_pthread_start(SOCKET *fd, void **priv_data, const char *hostname)
{
	struct gg_resolver_pthread_data *data = NULL;
	int new_errno;
	SOCKET pipes[2];

	gg_debug(GG_DEBUG_FUNCTION, "** gg_resolver_pthread_start(%p, %p, \"%s\");\n", fd, priv_data, hostname);

	if (fd == NULL || priv_data == NULL || hostname == NULL) {
		gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() invalid arguments\n");
		errno = EFAULT;
		return -1;
	}

	data = (gg_resolver_pthread_data*)malloc(sizeof(struct gg_resolver_pthread_data));

	if (data == NULL) {
		gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() out of memory for resolver data\n");
		return -1;
	}

	if (pipe(pipes) == -1) {
		gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
		free(data);
		return -1;
	}

	data->hostname = strdup(hostname);

	if (data->hostname == NULL) {
		gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() out of memory\n");
		new_errno = errno;
		goto cleanup;
	}

	data->rfd = pipes[0];
	data->wfd = pipes[1];

	if (pthread_create(&data->thread, NULL, gg_resolver_pthread_thread, data)) {
		gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() unable to create thread\n");
		new_errno = errno;
		goto cleanup;
	}

	gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() %p\n", data);

	*fd = pipes[0];
	*priv_data = data;

	return 0;

cleanup:
	if (data) {
		free(data->hostname);
		free(data);
	}

	gg_sock_close(pipes[0]);
	gg_sock_close(pipes[1]);

	errno = new_errno;

	return -1;
}

#endif /* GG_CONFIG_HAVE_PTHREAD */

/**
 * Ustawia sposób rozwiązywania nazw w sesji.
 *
 * \param gs Struktura sesji
 * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_session_set_resolver(struct gg_session *gs, gg_resolver_t type)
{
	if (gs == NULL) {
		errno = EINVAL;
		return -1;
	}

	if (type == GG_RESOLVER_DEFAULT) {
		if (gg_global_resolver_type != GG_RESOLVER_DEFAULT) {
			gs->resolver_type = gg_global_resolver_type;
			gs->resolver_start = gg_global_resolver_start;
			gs->resolver_cleanup = gg_global_resolver_cleanup;
			return 0;
		}

#if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT)
		type = GG_RESOLVER_FORK;
#else
		type = GG_RESOLVER_PTHREAD;
#endif
	}

	switch (type) {
		case GG_RESOLVER_FORK:
			gs->resolver_type = type;
			gs->resolver_start = gg_resolver_fork_start;
			gs->resolver_cleanup = gg_resolver_fork_cleanup;
			return 0;

#ifdef GG_CONFIG_HAVE_PTHREAD
		case GG_RESOLVER_PTHREAD:
			gs->resolver_type = type;
			gs->resolver_start = gg_resolver_pthread_start;
			gs->resolver_cleanup = gg_resolver_pthread_cleanup;
			return 0;
#endif

		default:
			errno = EINVAL;
			return -1;
	}
}

/**
 * Zwraca sposób rozwiązywania nazw w sesji.
 *
 * \param gs Struktura sesji
 *
 * \return Sposób rozwiązywania nazw
 */
gg_resolver_t gg_session_get_resolver(struct gg_session *gs)
{
	if (gs == NULL) {
		errno = EINVAL;
		return GG_RESOLVER_INVALID;
	}

	return gs->resolver_type;
}

/**
 * Ustawia własny sposób rozwiązywania nazw w sesji.
 *
 * \param gs Struktura sesji
 * \param resolver_start Funkcja rozpoczynająca rozwiązywanie nazwy
 * \param resolver_cleanup Funkcja zwalniająca zasoby
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_session_set_custom_resolver(struct gg_session *gs, int (*resolver_start)(SOCKET*, void**, const char*), void (*resolver_cleanup)(void**, int))
{
	if (gs == NULL || resolver_start == NULL || resolver_cleanup == NULL) {
		errno = EINVAL;
		return -1;
	}

	gs->resolver_type = GG_RESOLVER_CUSTOM;
	gs->resolver_start = resolver_start;
	gs->resolver_cleanup = resolver_cleanup;

	return 0;
}

/**
 * Ustawia sposób rozwiązywania nazw połączenia HTTP.
 *
 * \param gh Struktura połączenia
 * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_http_set_resolver(struct gg_http *gh, gg_resolver_t type)
{
	if (gh == NULL) {
		errno = EINVAL;
		return -1;
	}

	if (type == GG_RESOLVER_DEFAULT) {
		if (gg_global_resolver_type != GG_RESOLVER_DEFAULT) {
			gh->resolver_type = gg_global_resolver_type;
			gh->resolver_start = gg_global_resolver_start;
			gh->resolver_cleanup = gg_global_resolver_cleanup;
			return 0;
		}

#if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT)
		type = GG_RESOLVER_FORK;
#else
		type = GG_RESOLVER_PTHREAD;
#endif
	}

	switch (type) {
		case GG_RESOLVER_FORK:
			gh->resolver_type = type;
			gh->resolver_start = gg_resolver_fork_start;
			gh->resolver_cleanup = gg_resolver_fork_cleanup;
			return 0;

#ifdef GG_CONFIG_HAVE_PTHREAD
		case GG_RESOLVER_PTHREAD:
			gh->resolver_type = type;
			gh->resolver_start = gg_resolver_pthread_start;
			gh->resolver_cleanup = gg_resolver_pthread_cleanup;
			return 0;
#endif

		default:
			errno = EINVAL;
			return -1;
	}
}

/**
 * Zwraca sposób rozwiązywania nazw połączenia HTTP.
 *
 * \param gh Struktura połączenia
 *
 * \return Sposób rozwiązywania nazw
 */
gg_resolver_t gg_http_get_resolver(struct gg_http *gh)
{
	if (gh == NULL) {
		errno = EINVAL;
		return GG_RESOLVER_INVALID;
	}

	return gh->resolver_type;
}

/**
 * Ustawia własny sposób rozwiązywania nazw połączenia HTTP.
 *
 * \param gh Struktura sesji
 * \param resolver_start Funkcja rozpoczynająca rozwiązywanie nazwy
 * \param resolver_cleanup Funkcja zwalniająca zasoby
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_http_set_custom_resolver(struct gg_http *gh, int (*resolver_start)(SOCKET*, void**, const char*), void (*resolver_cleanup)(void**, int))
{
	if (gh == NULL || resolver_start == NULL || resolver_cleanup == NULL) {
		errno = EINVAL;
		return -1;
	}

	gh->resolver_type = GG_RESOLVER_CUSTOM;
	gh->resolver_start = resolver_start;
	gh->resolver_cleanup = resolver_cleanup;

	return 0;
}

/**
 * Ustawia sposób rozwiązywania nazw globalnie dla biblioteki.
 *
 * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_global_set_resolver(gg_resolver_t type)
{
	switch (type) {
		case GG_RESOLVER_DEFAULT:
			gg_global_resolver_type = type;
			gg_global_resolver_start = NULL;
			gg_global_resolver_cleanup = NULL;
			return 0;

		case GG_RESOLVER_FORK:
			gg_global_resolver_type = type;
			gg_global_resolver_start = gg_resolver_fork_start;
			gg_global_resolver_cleanup = gg_resolver_fork_cleanup;
			return 0;

#ifdef GG_CONFIG_HAVE_PTHREAD
		case GG_RESOLVER_PTHREAD:
			gg_global_resolver_type = type;
			gg_global_resolver_start = gg_resolver_pthread_start;
			gg_global_resolver_cleanup = gg_resolver_pthread_cleanup;
			return 0;
#endif

		default:
			errno = EINVAL;
			return -1;
	}
}

/**
 * Zwraca sposób rozwiązywania nazw globalnie dla biblioteki.
 *
 * \return Sposób rozwiązywania nazw
 */
gg_resolver_t gg_global_get_resolver(void)
{
	return gg_global_resolver_type;
}

/**
 * Ustawia własny sposób rozwiązywania nazw globalnie dla biblioteki.
 *
 * \param resolver_start Funkcja rozpoczynająca rozwiązywanie nazwy
 * \param resolver_cleanup Funkcja zwalniająca zasoby
 *
 * Parametry funkcji rozpoczynającej rozwiązywanie nazwy wyglądają następująco:
 *  - \c "SOCKET *fd" &mdash; wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor potoku
 *  - \c "void **priv_data" &mdash; wskaźnik na zmienną, gdzie można umieścić wskaźnik do prywatnych danych na potrzeby rozwiązywania nazwy
 *  - \c "const char *name" &mdash; nazwa serwera do rozwiązania
 *
 * Parametry funkcji zwalniającej zasoby wyglądają następująco:
 *  - \c "void **priv_data" &mdash; wskaźnik na zmienną przechowującą wskaźnik do prywatnych danych, należy go ustawić na \c NULL po zakończeniu
 *  - \c "int force" &mdash; flaga mówiąca o tym, że zasoby są zwalniane przed zakończeniem rozwiązywania nazwy, np. z powodu zamknięcia sesji.
 *
 * Własny kod rozwiązywania nazwy powinien stworzyć potok, parę gniazd lub
 * inny deskryptor pozwalający na co najmniej jednostronną komunikację i 
 * przekazać go w parametrze \c fd. Po zakończeniu rozwiązywania nazwy,
 * powinien wysłać otrzymany adres IP w postaci sieciowej (big-endian) do
 * deskryptora. Jeśli rozwiązywanie nazwy się nie powiedzie, należy wysłać
 * \c INADDR_NONE. Następnie zostanie wywołana funkcja zwalniająca zasoby
 * z parametrem \c force równym \c 0. Gdyby sesja została zakończona przed
 * rozwiązaniem nazwy, np. za pomocą funkcji \c gg_logoff(), funkcja
 * zwalniająca zasoby zostanie wywołana z parametrem \c force równym \c 1.
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_global_set_custom_resolver(int (*resolver_start)(SOCKET*, void**, const char*), void (*resolver_cleanup)(void**, int))
{
	if (resolver_start == NULL || resolver_cleanup == NULL) {
		errno = EINVAL;
		return -1;
	}

	gg_global_resolver_type = GG_RESOLVER_CUSTOM;
	gg_global_resolver_start = resolver_start;
	gg_global_resolver_cleanup = resolver_cleanup;

	return 0;
}
void guppi_rawdisk_thread(void *_args) {

    /* Set cpu affinity */
    cpu_set_t cpuset, cpuset_orig;
    sched_getaffinity(0, sizeof(cpu_set_t), &cpuset_orig);
    CPU_ZERO(&cpuset);
    CPU_SET(1, &cpuset);
    int rv = sched_setaffinity(0, sizeof(cpu_set_t), &cpuset);
    if (rv<0) { 
        guppi_error("guppi_rawdisk_thread", "Error setting cpu affinity.");
        perror("sched_setaffinity");
    }

    /* Get args */
    struct guppi_thread_args *args = (struct guppi_thread_args *)_args;

    /* Set priority */
    rv = setpriority(PRIO_PROCESS, 0, 0);
    if (rv<0) {
        guppi_error("guppi_rawdisk_thread", "Error setting priority level.");
        perror("set_priority");
    }

    /* Attach to status shared mem area */
    struct guppi_status st;
    rv = guppi_status_attach(&st);
    if (rv!=GUPPI_OK) {
        guppi_error("guppi_rawdisk_thread", 
                "Error attaching to status shared memory.");
        pthread_exit(NULL);
    }
    pthread_cleanup_push((void *)guppi_status_detach, &st);
    pthread_cleanup_push((void *)set_exit_status, &st);

    /* Init status */
    guppi_status_lock_safe(&st);
    hputs(st.buf, STATUS_KEY, "init");
    guppi_status_unlock_safe(&st);

    /* Read in general parameters */
    struct guppi_params gp;
#if FITS_TYPE == PSRFITS
    struct sdfits pf;
    pf.sub.dat_freqs = NULL;
    pf.sub.dat_weights = NULL;
    pf.sub.dat_offsets = NULL;
    pf.sub.dat_scales = NULL;
    pthread_cleanup_push((void *)guppi_free_psrfits, &pf);
#else
    struct sdfits pf;
    pthread_cleanup_push((void *)guppi_free_sdfits, &pf);
#endif

    /* Attach to databuf shared mem */
    struct guppi_databuf *db;
    db = guppi_databuf_attach(args->input_buffer);
    if (db==NULL) {
        guppi_error("guppi_rawdisk_thread",
                "Error attaching to databuf shared memory.");
        pthread_exit(NULL);
    }
    pthread_cleanup_push((void *)guppi_databuf_detach, db);

    /* Init output file */
    FILE *fraw = NULL;
    pthread_cleanup_push((void *)safe_fclose, fraw);

    /* Pointers for quantization params */
    double *mean = NULL;
    double *std = NULL;
    printf("casper: raw disk thread created and running\n");
    /* Loop */
    int packetidx=0, npacket=0, ndrop=0, packetsize=0, blocksize=0;
    int orig_blocksize=0;
    int curblock=0;
    int block_count=0, blocks_per_file=128, filenum=0;
    int got_packet_0=0, first=1;
    int requantize = 0;
    char *ptr, *hend;
    signal(SIGINT,cc);
    while (run) {

        /* Note waiting status */
        guppi_status_lock_safe(&st);
        hputs(st.buf, STATUS_KEY, "waiting");
        guppi_status_unlock_safe(&st);

        /* Wait for buf to have data */
        rv = guppi_databuf_wait_filled(db, curblock);
        if (rv!=0) continue;

	    printf("casper: raw disk thread rcvd data.\n");

        /* Read param struct for this block */
        ptr = guppi_databuf_header(db, curblock);
        if (first) {
            guppi_read_obs_params(ptr, &gp, &pf);
            first = 0;
        } else {
            guppi_read_subint_params(ptr, &gp, &pf);
        }

        /* Parse packet size, npacket from header */
        hgeti4(ptr, "PKTIDX", &packetidx);
        hgeti4(ptr, "PKTSIZE", &packetsize);
        hgeti4(ptr, "NPKT", &npacket);
        hgeti4(ptr, "NDROP", &ndrop);

#if FITS_TYPE == PSR_FITS
        /* Check for re-quantization flag */
        int nbits_req = 0;
        if (hgeti4(ptr, "NBITSREQ", &nbits_req) == 0) {
            /* Param not present, don't requantize */
            requantize = 0;
        } else {
            /* Param is present */
            if (nbits_req==8)
                requantize = 0;
            else if (nbits_req==2) 
                requantize = 1;
            else
                /* Invalid selection for requested nbits 
                 * .. die or ignore?
                 */
                requantize = 0;
        }
#endif

        /* Set up data ptr for quant routines */
#if FITS_TYPE == PSR_FITS
        pf.sub.data = (unsigned char *)guppi_databuf_data(db, curblock);
#else
        pf.data_columns.data = (unsigned char *)guppi_databuf_data(db, curblock);
#endif

        /* Wait for packet 0 before starting write */
        if (got_packet_0==0 && packetidx==0 && gp.stt_valid==1) {
            got_packet_0 = 1;
            guppi_read_obs_params(ptr, &gp, &pf);
#if FITS_TYPE == PSR_FITS
            orig_blocksize = pf.sub.bytes_per_subint;
#endif
            char fname[256];
            sprintf(fname, "%s.%4.4d.raw", pf.basefilename, filenum);
            fprintf(stderr, "Opening raw file '%s'\n", fname);
            // TODO: check for file exist.
            fraw = fopen(fname, "w");
            if (fraw==NULL) {
                guppi_error("guppi_rawdisk_thread", "Error opening file.");
                pthread_exit(NULL);
            }

#if FITS_TYPE == PSR_FITS
            /* Determine scaling factors for quantization if appropriate */
            if (requantize) {
                mean = (double *)realloc(mean, 
                        pf.hdr.rcvr_polns * pf.hdr.nchan * sizeof(double));
                std  = (double *)realloc(std,  
                        pf.hdr.rcvr_polns * pf.hdr.nchan * sizeof(double));
                compute_stat(&pf, mean, std);
                fprintf(stderr, "Computed 2-bit stats\n");
            }
#endif
        }
        
        /* See if we need to open next file */
        if (block_count >= blocks_per_file) {
            fclose(fraw);
            filenum++;
            char fname[256];
            sprintf(fname, "%s.%4.4d.raw", pf.basefilename, filenum);
            fprintf(stderr, "Opening raw file '%s'\n", fname);
            fraw = fopen(fname, "w");
            if (fraw==NULL) {
                guppi_error("guppi_rawdisk_thread", "Error opening file.");
                pthread_exit(NULL);
            }
            block_count=0;
        }

        /* See how full databuf is */
        //total_status = guppi_databuf_total_status(db);

        /* Requantize from 8 bits to 2 bits if necessary.
         * See raw_quant.c for more usage examples.
         */
#if FITS_TYPE == PSR_FITS
        if (requantize && got_packet_0) {
            pf.sub.bytes_per_subint = orig_blocksize;
            /* Does the quantization in-place */
            quantize_2bit(&pf, mean, std);
            /* Update some parameters for output */
            hputi4(ptr, "BLOCSIZE", pf.sub.bytes_per_subint);
            hputi4(ptr, "NBITS", pf.hdr.nbits);
        }
#endif

        /* Get full data block size */
        hgeti4(ptr, "BLOCSIZE", &blocksize);

        /* If we got packet 0, write data to disk */
        if (got_packet_0) { 

            /* Note waiting status */
            guppi_status_lock_safe(&st);
            hputs(st.buf, STATUS_KEY, "writing");
            guppi_status_unlock_safe(&st);

            /* Write header to file */
            hend = ksearch(ptr, "END");
            for (ptr=ptr; ptr<=hend; ptr+=80) {
                fwrite(ptr, 80, 1, fraw);
            }

            /* Write data */
            printf("block size: %d\n", blocksize);
            ptr = guppi_databuf_data(db, curblock);
            rv = fwrite(ptr, 1, (size_t)blocksize, fraw);
            if (rv != blocksize) { 
                guppi_error("guppi_rawdisk_thread", 
                        "Error writing data.");
            }

            /* Increment counter */
            block_count++;

            /* flush output */
            fflush(fraw);
        }

        /* Mark as free */
        guppi_databuf_set_free(db, curblock);

        /* Go to next block */
        curblock = (curblock + 1) % db->n_block;

        /* Check for cancel */
        pthread_testcancel();

    }

    pthread_exit(NULL);

    pthread_cleanup_pop(0); /* Closes fclose */
    pthread_cleanup_pop(0); /* Closes guppi_databuf_detach */
    pthread_cleanup_pop(0); /* Closes guppi_free_psrfits */
    pthread_cleanup_pop(0); /* Closes set_exit_status */
    pthread_cleanup_pop(0); /* Closes guppi_status_detach */

}
/******************************************************************************
Description.: this is the main worker thread
              it loops forever, grabs a fresh frame and stores it to file
Input Value.:
Return Value:
******************************************************************************/
void *worker_thread(void *arg)
{
    int ok = 1, frame_size = 0, decompressed_size = 0;
    unsigned char *tmp_decompressed = NULL;

    int width = 320;
    int height = 240;
    clock_t start, mid, end;

    Vision cv_runner;
    /* set cleanup handler to cleanup allocated ressources */
    pthread_cleanup_push(worker_cleanup, NULL);

    while(ok >= 0 && !pglobal->stop) {
        DBG("waiting for fresh frame\n");

        pthread_mutex_lock(&pglobal->in[input_number].db);
        pthread_cond_wait(&pglobal->in[input_number].db_update, &pglobal->in[input_number].db);
        start = clock();
        DBG("getting sizes\n");

        /* Get sizes */
        int fmt_idx = pglobal->in[input_number].currentFormat;
        if(fmt_idx > (pglobal->in[input_number].formatCount - 1)) {
            DBG("Format index out of bounds");
            return NULL;
        }
        int res_idx = pglobal->in[input_number].in_formats[fmt_idx].currentResolution;
        if(res_idx > (pglobal->in[input_number].in_formats[fmt_idx].resolutionCount - 1)) {
            DBG("Res index out of bounds");
            return NULL;
        }

        // width = pglobal->in[input_number].in_formats[fmt_idx].supportedResolutions[res_idx].width;
        // height = pglobal->in[input_number].in_formats[fmt_idx].supportedResolutions[res_idx].height;
        DBG("Width: %d,Height:%d\n", width, height);
        decompressed_size = width * height * sizeof(char) * 3;

        /* read buffer */
        frame_size = pglobal->in[input_number].size;

        // TODO: resize decompressed buffer
        if (decompressed_size > max_decompressed_size) {
            DBG("increasing decompresser size to %d\n", decompressed_size);

            max_decompressed_size = decompressed_size + (1 << 16);
            if((tmp_decompressed = (unsigned char *) realloc(decompressed, max_decompressed_size)) == NULL) {
                pthread_mutex_unlock(&pglobal->in[input_number].db);
                LOG("not enough memory\n");
                return NULL;
            }

            decompressed = tmp_decompressed;
        }


        /* allow others to access the global buffer again */
        DBG("About to make the mat\n");
        vision::process_jpeg(decompressed,pglobal->in[input_number].buf,frame_size);
        pthread_mutex_unlock(&pglobal->in[input_number].db);
        DBG("Width:%d, Height:%d\n", width, height);
        cv::Mat img(height, width, CV_8UC3, decompressed, width * 3 * sizeof(char));
        mid = clock();
        DBG("Made the mat!\n");
        ok = cv_runner.loop(img);
        end = clock();
        DBG("Wrote the image!\n");
        DBG("Decompression time: %f\n",((float)mid-start)/CLOCKS_PER_SEC);
        DBG("OpenCV time: %f\n",((float)end-mid)/CLOCKS_PER_SEC);

        // Wait 100ms so there's less overwhelming of data
        //usleep(100000);
    }

    /* cleanup now */
    pthread_cleanup_pop(1);

    return NULL;
}
Exemple #4
0
/*
 * Run a seperate thread that connects to the database server and
 * controls the backup or restore. When we close the VDI device we
 * also tear down this database control thread.
 */
static void *adoThread(void *data)
{
   HRESULT hr;
   adoThreadContext ado_ctx;
   bpContext *ctx = (bpContext *)data;
   plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;

   memset(&ado_ctx, 0, sizeof(ado_ctx));

   /*
    * When we get canceled make sure we run the cleanup function.
    */
   pthread_cleanup_push(adoCleanupThread, &ado_ctx);

   /*
    * Initialize COM for this thread.
    */
   hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
   if (!SUCCEEDED (hr)) {
      return NULL;
   }

   /*
    * Create a COM instance for an ActiveX® Data Objects connection.
    */
   hr = CoCreateInstance(CLSID_CADOConnection,
                         NULL,
                         CLSCTX_INPROC_SERVER,
                         IID_IADOConnection,
                         (void **)&ado_ctx.adoConnection);
   if (!SUCCEEDED (hr)) {
      goto bail_out;
   }

   /*
    * Make sure the connection doesn't timeout.
    * Default timeout is not long enough most of the time
    * for the backup or restore to finish and when it times
    * out it will abort the action it was performing.
    */
   hr = ado_ctx.adoConnection->put_CommandTimeout(0);
   if (!SUCCEEDED (hr)) {
      adoThreadSetError(ctx, ado_ctx.adoConnection);
      goto bail_out;
   }

   /*
    * Open a connection to the database server with the defined connection string.
    */
   ado_ctx.ado_connect_string = str_2_BSTR(p_ctx->ado_connect_string);
   hr = ado_ctx.adoConnection->Open(ado_ctx.ado_connect_string);
   if (!SUCCEEDED (hr)) {
      adoThreadSetError(ctx, ado_ctx.adoConnection);
      goto bail_out;
   }

   /*
    * Execute the backup or restore command.
    */
   ado_ctx.ado_query = str_2_BSTR(p_ctx->ado_query);
   hr = ado_ctx.adoConnection->Execute(ado_ctx.ado_query, NULL, adExecuteNoRecords, NULL);
   if (!SUCCEEDED (hr)) {
      adoThreadSetError(ctx, ado_ctx.adoConnection);
      goto bail_out;
   }

bail_out:
   /*
    * Run the thread cleanup.
    */
   pthread_cleanup_pop(1);

   return NULL;
}
Exemple #5
0
static int printf_binary (FILE *stream,const struct printf_info *info,const void *const *args) {
	char *buffer = NULL;
	register int length = 0;
	const unsigned int n = 0;

	if (BINARY_FORMAT_KEY == info->spec) {
		/*
		 * WARNING: ALWAYS read at least sizeof(unsigned long) data
		 * whatever the argument data type !!!
		 * TODO: try to find a better and less dangerous way, may be using the field width or the precision information.
		 */
		const unsigned long *value = (const unsigned long *)args[n];

		pthread_cleanup_push(printf_binary_cancel_handler, &buffer);

		/*
		 * Format the output into a string according to format specifications
		 */

		if (info->is_char) {
			/* hh flag:
			 * A  following integer conversion corresponds to a signed char or unsigned char argument,
			 * or a following n conversion corresponds to a pointer to a signed char argument.
			 */
			const size_t size = sizeof(char) * (sizeof(char)  * 8) + 1; /* 1 byte => 8 characters */
			buffer = malloc(size);
			if (buffer != NULL) {
				const unsigned char n = (*value) & 0xFF;
				length = binary_byte_string(n,buffer);
			} else {
				ERROR_MSG("failed to allocate %u bytes to printf a binary string",size);
			}
		} else if (info->is_short) {
			/* h flag:
			 * A following integer conversion corresponds to a short int or unsigned short int argument,
			 * or a following n conversion corresponds to a pointer to a short int argument.
			 */
			const size_t size = sizeof(short) * (sizeof(char)  * 8) + 1; /* 1 byte => 8 characters */
			buffer = malloc(size);
			if (buffer != NULL) {
				const unsigned short n = (*value) & 0xFFFF;
				const unsigned char *values = (const unsigned char *)&n;
				char *byteBuffer = buffer;
				length = binary_byte_string(values[1],byteBuffer);
				if (length != -1) {
					byteBuffer = buffer + length;
					length += binary_byte_string(values[0],byteBuffer);
				}
			} else {
				ERROR_MSG("failed to allocate %u bytes to printf a binary string",size);
			}
		} else if ((info->is_long_double) && (info->is_long)) {
			/* ll flag:
			 * (ell-ell).  A following integer conversion corresponds to a long long int or unsigned long long  int
			 * argument, or a following n conversion corresponds to a pointer to a long long int argument.
			 */
			const size_t size = sizeof(long long) * (sizeof(char)  * 8) + 1; /* 1 byte => 8 characters */
			buffer = malloc(size);
			if (buffer != NULL) {
				int i;
				const unsigned char *values = (const unsigned char *)value;
				for(i= (sizeof(long long) -1);((i >= 0) && (length != -1));i--) {
					char *byteBuffer = buffer + length;
					length += binary_byte_string(values[i],byteBuffer);
				}
			} else {
				ERROR_MSG("failed to allocate %u bytes to printf a binary string",size);
			}
		} else if (info->is_long_double) {
			/* L flag:
			 * A following a, A, e, E, f, F, g, or G conversion corresponds to a long double argument.
			 */
			const size_t size = sizeof(long double) * (sizeof(char)  * 8) + 1; /* 1 byte => 8 characters */
			buffer = malloc(size);
			if (buffer != NULL) {
				int i;
				const unsigned char *values = (const unsigned char *)value;
				for(i= (sizeof(long double) -1);((i >= 0) && (length != -1));i--) {
					char *byteBuffer = buffer + length;
					length += binary_byte_string(values[i],byteBuffer);
				}
			} else {
				ERROR_MSG("failed to allocate %u bytes to printf a binary string",size);
			}
		} else if (info->is_long) {
			/* l flag:
			 * (ell)  A  following integer conversion corresponds to a long int or unsigned long int argument, or a
			 * following n conversion corresponds to a pointer to a long int argument, or a following c  conversion
			 * corresponds  to  a  wint_t argument, or a following s conversion corresponds to a pointer to wchar_t
			 * argument.
			 */
			const size_t size = sizeof(long) * (sizeof(char)  * 8) + 1; /* 1 byte => 8 characters */
			buffer = malloc(size);
			if (buffer != NULL) {
				const unsigned char *values = (const unsigned char *)value;
				int i;
				for(i= (sizeof(long) -1);((i >= 0) && (length != -1));i--) {
					char *byteBuffer = buffer + length;
					length += binary_byte_string(values[i],byteBuffer);
				}
			} else {
				ERROR_MSG("failed to allocate %u bytes to printf a binary string",size);
			}
		} else {
			/*
			 * no length modifier has been set
			 * Warning: long type may be 32 or 64 bits
			 */
			const size_t size = sizeof(long) * (sizeof(char)  * 8) + 1; /* 1 byte => 8 characters */
			buffer = malloc(size);
			if (buffer != NULL) {
				int i;
				const unsigned char *values = (const unsigned char *)value;
				for(i= (sizeof(long) -1);((i >= 0) && (length != -1));i--) {
					char *byteBuffer = buffer + length;
					length += binary_byte_string(values[i],byteBuffer);
				}
			} else {
				ERROR_MSG("failed to allocate %u bytes to printf a binary string",size);
			}
		}

		/* add the "binary" prefix, pad to the minimum field width and print to the stream. */
		if (length != -1) {
			register const char *bufferStart = buffer;
			char precPadding[128];
			register char *pos = precPadding;
			if ((0 == info->width) && (-1 == info->prec)) {
				/* remove unnecessary 0 on the left */
				*pos = '\0';
				while( '0' == *bufferStart ) {
					bufferStart++;
				}
				/* just in case: keep at least the last bit value whatever it's value ! */
				if ('\0' == *bufferStart) {
					bufferStart--;
				}
			} else {
				if (info->prec > length) {
					/* add 0 to the left to get the right precision (weird cast ?) */
					while(info->prec >= length) {
						*pos = '0';
						length++;
						pos++;
					}
				}
				*pos = '\0';
				if (info->width < length) {
					/* try to remove unnecessary 0 to get the right width (without losing data !) */
					while( ('0' == *bufferStart) && (info->width < length)) {
						bufferStart++;
						length--;
					}
				} else if (info->width != 0) {
					/* add space to get the desired width */
					while(length < info->width) {
						*pos = ' ';
						length++;
						pos++;
					}
					*pos = '\0';
				}
				//length = fprintf (stream, "b%*s",(info->left ? -info->width : info->width),bufferStart);
			} /* !((0 == info->width) && (0 == info->prec))  */
			length = fprintf (stream, "b%s%s",precPadding,bufferStart);
		}

		/* Clean up and return. */
		free (buffer);
		pthread_cleanup_pop(0);
	} /* (BINARY_FORMAT_KEY == info[n].spec) */
	return length;
}
Exemple #6
0
static void *WatchdogFunc( void *userData )
{
    PaError result = paNoError, *pres = NULL;
    int err;
    PaAlsaThreading *th = (PaAlsaThreading *) userData;
    unsigned intervalMsec = 500;
    const PaTime maxSeconds = 3.;   /* Max seconds between callbacks */
    PaTime timeThen = PaUtil_GetTime(), timeNow, timeElapsed, cpuTimeThen, cpuTimeNow, cpuTimeElapsed;
    double cpuLoad, avgCpuLoad = 0.;
    int throttled = 0;

    assert( th );

    /* Execute OnWatchdogExit when exiting */
    pthread_cleanup_push( &OnWatchdogExit, th );

    /* Boost priority of callback thread */
    PA_ENSURE( result = BoostPriority( th ) );
    if( !result )
    {
        /* Boost failed, might as well exit */
        pthread_exit( NULL );
    }

    cpuTimeThen = th->callbackCpuTime;
    {
        int policy;
        struct sched_param spm = { 0 };
        pthread_getschedparam( pthread_self(), &policy, &spm );
        PA_DEBUG(( "%s: Watchdog priority is %d\n", __FUNCTION__, spm.sched_priority ));
    }

    while( 1 )
    {
        double lowpassCoeff = 0.9, lowpassCoeff1 = 0.99999 - lowpassCoeff;

        /* Test before and after in case whatever underlying sleep call isn't interrupted by pthread_cancel */
        pthread_testcancel();
        Pa_Sleep( intervalMsec );
        pthread_testcancel();

        if( PaUtil_GetTime() - th->callbackTime > maxSeconds )
        {
            PA_DEBUG(( "Watchdog: Terminating callback thread\n" ));
            /* Tell thread to terminate */
            err = pthread_kill( th->callbackThread, SIGKILL );
            pthread_exit( NULL );
        }

        PA_DEBUG(( "%s: PortAudio reports CPU load: %g\n", __FUNCTION__, PaUtil_GetCpuLoad( th->cpuLoadMeasurer ) ));

        /* Check if we should throttle, or unthrottle :P */
        cpuTimeNow = th->callbackCpuTime;
        cpuTimeElapsed = cpuTimeNow - cpuTimeThen;
        cpuTimeThen = cpuTimeNow;

        timeNow = PaUtil_GetTime();
        timeElapsed = timeNow - timeThen;
        timeThen = timeNow;
        cpuLoad = cpuTimeElapsed / timeElapsed;
        avgCpuLoad = avgCpuLoad * lowpassCoeff + cpuLoad * lowpassCoeff1;
        /*
        if( throttled )
            PA_DEBUG(( "Watchdog: CPU load: %g, %g\n", avgCpuLoad, cpuTimeElapsed ));
            */
        if( PaUtil_GetCpuLoad( th->cpuLoadMeasurer ) > .925 )
        {
            static int policy;
            static struct sched_param spm = { 0 };
            static const struct sched_param defaultSpm = { 0 };
            PA_DEBUG(( "%s: Throttling audio thread, priority %d\n", __FUNCTION__, spm.sched_priority ));

            pthread_getschedparam( th->callbackThread, &policy, &spm );
            if( !pthread_setschedparam( th->callbackThread, SCHED_OTHER, &defaultSpm ) )
            {
                throttled = 1;
            }
            else
                PA_DEBUG(( "Watchdog: Couldn't lower priority of audio thread: %s\n", strerror( errno ) ));

            /* Give other processes a go, before raising priority again */
            PA_DEBUG(( "%s: Watchdog sleeping for %lu msecs before unthrottling\n", __FUNCTION__, th->throttledSleepTime ));
            Pa_Sleep( th->throttledSleepTime );

            /* Reset callback priority */
            if( pthread_setschedparam( th->callbackThread, SCHED_FIFO, &spm ) != 0 )
            {
                PA_DEBUG(( "%s: Couldn't raise priority of audio thread: %s\n", __FUNCTION__, strerror( errno ) ));
            }

            if( PaUtil_GetCpuLoad( th->cpuLoadMeasurer ) >= .99 )
                intervalMsec = 50;
            else
                intervalMsec = 100;

            /*
            lowpassCoeff = .97;
            lowpassCoeff1 = .99999 - lowpassCoeff;
            */
        }
        else if( throttled && avgCpuLoad < .8 )
        {
            intervalMsec = 500;
            throttled = 0;

            /*
            lowpassCoeff = .9;
            lowpassCoeff1 = .99999 - lowpassCoeff;
            */
        }
    }

    pthread_cleanup_pop( 1 );   /* Execute cleanup on exit */

error:
    /* Shouldn't get here in the normal case */

    /* Pass on error code */
    pres = malloc( sizeof (PaError) );
    *pres = result;

    pthread_exit( pres );
}
Exemple #7
0
static void *open_output( void *ptr )
{
    obe_output_params_t *output_params = ptr;
    obe_t *h = output_params->h;
    struct ip_status status;
    hnd_t ip_handle = NULL;
    int num_muxed_data = 0;
    AVBufferRef **muxed_data;
    obe_udp_opts_t udp_opts;

    struct sched_param param = {0};
    param.sched_priority = 99;
    pthread_setschedparam( pthread_self(), SCHED_FIFO, &param );

    status.output_params = output_params;
    status.ip_handle = &ip_handle;
    pthread_cleanup_push( close_output, (void*)&status );

    udp_populate_opts( &udp_opts, output_params->output_opts.target );

    if( output_params->output_opts.output == OUTPUT_RTP )
    {
        if( rtp_open( &ip_handle, &udp_opts ) < 0 )
            return NULL;
    }
    else
    {
        if( udp_open( &ip_handle, &udp_opts ) < 0 )
        {
            fprintf( stderr, "[udp] Could not create udp output" );
            return NULL;
        }
    }

    while( 1 )
    {
        pthread_mutex_lock( &h->output_queue.mutex );
        while( !h->output_queue.size && !h->cancel_output_thread )
        {
            /* Often this cond_wait is not because of an underflow */
            pthread_cond_wait( &h->output_queue.in_cv, &h->output_queue.mutex );
        }

        if( h->cancel_output_thread )
        {
            pthread_mutex_unlock( &h->output_queue.mutex );
            break;
        }

        num_muxed_data = h->output_queue.size;

        muxed_data = malloc( num_muxed_data * sizeof(*muxed_data) );
        if( !muxed_data )
        {
            pthread_mutex_unlock( &h->output_queue.mutex );
            syslog( LOG_ERR, "Malloc failed\n" );
            return NULL;
        }
        memcpy( muxed_data, h->output_queue.queue, num_muxed_data * sizeof(*muxed_data) );
        pthread_mutex_unlock( &h->output_queue.mutex );

//        printf("\n START %i \n", num_muxed_data );

        for( int i = 0; i < num_muxed_data; i++ )
        {
            if( output_params->output_opts.output == OUTPUT_RTP )
            {
                if( write_rtp_pkt( ip_handle, &muxed_data[i]->data[7*sizeof(int64_t)], TS_PACKETS_SIZE, AV_RN64( muxed_data[i]->data ) ) < 0 )
                    syslog( LOG_ERR, "[rtp] Failed to write RTP packet\n" );
            }
            else
            {
                if( udp_write( ip_handle, &muxed_data[i]->data[7*sizeof(int64_t)], TS_PACKETS_SIZE ) < 0 )
                    syslog( LOG_ERR, "[udp] Failed to write UDP packet\n" );
            }

            remove_from_queue( &h->output_queue );
            av_buffer_unref( &muxed_data[i] );
        }

        free( muxed_data );
        muxed_data = NULL;
    }

    pthread_cleanup_pop( 1 );

    return NULL;
}
Exemple #8
0
static void *
tpool_worker(void *arg)
{
	tpool_t *tpool = (tpool_t *)arg;
	int elapsed;
	tpool_job_t *job;
	void (*func)(void *);
	tpool_active_t active;

	sig_mutex_lock(&tpool->tp_mutex);
	pthread_cleanup_push(worker_cleanup, tpool);

	/*
	 * This is the worker's main loop.
	 * It will only be left if a timeout or an error has occured.
	 */
	active.tpa_tid = pthread_self();
	for (;;) {
		elapsed = 0;
		tpool->tp_idle++;
		if (tpool->tp_flags & TP_WAIT)
			notify_waiters(tpool);
		while ((tpool->tp_head == NULL ||
		    (tpool->tp_flags & TP_SUSPEND)) &&
		    !(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))) {
			if (tpool->tp_current <= tpool->tp_minimum ||
			    tpool->tp_linger == 0) {
				(void) sig_cond_wait(&tpool->tp_workcv,
				    &tpool->tp_mutex);
			} else {
				timestruc_t timeout;

				timeout.tv_sec = tpool->tp_linger;
				timeout.tv_nsec = 0;
				if (sig_cond_reltimedwait(&tpool->tp_workcv,
				    &tpool->tp_mutex, &timeout) != 0) {
					elapsed = 1;
					break;
				}
			}
		}
		tpool->tp_idle--;
		if (tpool->tp_flags & TP_DESTROY)
			break;
		if (tpool->tp_flags & TP_ABANDON) {
			/* can't abandon a suspended pool */
			if (tpool->tp_flags & TP_SUSPEND) {
				tpool->tp_flags &= ~TP_SUSPEND;
				(void) cond_broadcast(&tpool->tp_workcv);
			}
			if (tpool->tp_head == NULL)
				break;
		}
		if ((job = tpool->tp_head) != NULL &&
		    !(tpool->tp_flags & TP_SUSPEND)) {
			elapsed = 0;
			func = job->tpj_func;
			arg = job->tpj_arg;
			tpool->tp_head = job->tpj_next;
			if (job == tpool->tp_tail)
				tpool->tp_tail = NULL;
			tpool->tp_njobs--;
			active.tpa_next = tpool->tp_active;
			tpool->tp_active = &active;
			sig_mutex_unlock(&tpool->tp_mutex);
			pthread_cleanup_push(job_cleanup, tpool);
			lfree(job, sizeof (*job));
			/*
			 * Call the specified function.
			 */
			func(arg);
			/*
			 * We don't know what this thread has been doing,
			 * so we reset its signal mask and cancellation
			 * state back to the initial values.
			 */
			(void) pthread_sigmask(SIG_SETMASK, &maskset, NULL);
			(void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,
			    NULL);
			(void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,
			    NULL);
			pthread_cleanup_pop(1);
		}
		if (elapsed && tpool->tp_current > tpool->tp_minimum) {
			/*
			 * We timed out and there is no work to be done
			 * and the number of workers exceeds the minimum.
			 * Exit now to reduce the size of the pool.
			 */
			break;
		}
	}
	pthread_cleanup_pop(1);
	return (arg);
}
void *control_handler(struct ControlProgram *control_program)
{
   int tid,i,r=-1,c=-1,status,rc,tmp;
   struct pollfd pfd;
   char command;
   int sockflag,poll_err_count,retval,socket,oldv,socket_err,length=sizeof(int);
   int32_t current_freq,radar=0,channel=0;
   struct timeval tv,current_time,last_report,t_get_data_start,t_get_data_end;
   struct ROSMsg msg; 
   struct DriverMsg dmsg; 
   struct DataPRM control_data; 
   struct ControlPRM control_parameters; 
   struct SiteSettings settings;
   struct TSGbuf *pulseseq;
   struct SeqPRM tprm;
   int data_int;
   pthread_t thread,threads[10];
   struct timeval t0,t1,t2,t3,t4;
   unsigned long elapsed;
   unsigned long ultemp;
   int32_t data_length;
   char entry_type,entry_name[80];
   int return_type,entry_exists;
   char *temp_strp;
   int32_t temp_int32;
   double temp_double;
/*
*  Init the Control Program state
*/
   r=control_program->radarinfo->radar-1;
   c=control_program->radarinfo->channel-1;
   pthread_mutex_lock(&exit_lock);
   pthread_mutex_lock(&controlprogram_list_lock);

   setbuf(stdout, 0);
   setbuf(stderr, 0);
   tid = pthread_self();
/* set the cancellation parameters --
   - Enable thread cancellation 
   - Defer the action of the cancellation 
*/
   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
   pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
   pthread_cleanup_push((void *)&controlprogram_exit,(void *)control_program);
     if(control_program!=NULL) {
       socket=control_program->state->socket;
     }
   pthread_mutex_unlock(&controlprogram_list_lock);
   pthread_mutex_unlock(&exit_lock);

   poll_err_count=0;
   gettimeofday(&last_report,NULL);
   while (1) {
      if(control_program==NULL) {
        fprintf(stderr,"Client Error: cp is null: %p\n",control_program);
        fflush(stderr);
        break;
      }
      retval=getsockopt(socket, SOL_SOCKET, SO_ERROR, &socket_err, &length);
      if ((retval!=0) || (socket_err!=0)) {
            fprintf(stderr,"Client Error: socket error: %d : %d %d : %p\n",socket,retval,socket_err,control_program);
            fflush(stderr);
        break;
      }
      /* poll the socket and check for waiting messages */
      pfd.fd = socket;
      pfd.events = POLLIN | POLLHUP | POLLRDNORM ;
      pfd.revents = 0;
      sockflag=0;
      retval=poll(&pfd, 1, 1000);
      if (retval > 0) {
        if(pfd.revents & POLLHUP) {
          fprintf(stderr,"Client: poll socket: %d cp: %p retval: %d poll_revents: %d :: %d %d %d\n",socket,control_program,retval,
          pfd.revents,POLLHUP,POLLIN,POLLRDNORM);
          break;
        } else {

          char buffer[32];
          if (recv(socket, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) > 0) {
            sockflag=1;
            poll_err_count=0;      
          } else {
            fprintf(stdout,"Client: poll socket: %d cp: %p poll_revents: %d :: No recv que'd\n",socket,control_program,pfd.revents);
            fflush(stdout);
            poll_err_count++;      
          }
        } 
      } else {
        if (retval < 0 ) {
           perror("poll()");
           break; 
        }
        if (retval == 0 ){
          fprintf(stdout,"Client: poll socket: %d cp: %p retval: %d :: timeout\n",socket,control_program,retval);
          fflush(stdout);
          poll_err_count++;      
        }
      }
      if (poll_err_count > 3 ) {
            break;    
      }
/* sockflag: socket looks good, time to  read from it */
      if(sockflag) {
        r=control_program->radarinfo->radar-1;
        c=control_program->radarinfo->channel-1;
        pthread_mutex_lock(&controlprogram_list_lock);
        r=control_program->radarinfo->radar-1;
        c=control_program->radarinfo->channel-1;
        if ((r<0) || (c<0)) control_program->data->status=-1;
 
       /* Read controlprogram msg */
        recv_data(socket, &msg, sizeof(struct ROSMsg));
        gettimeofday(&current_time,NULL);
        if((current_time.tv_sec-last_report.tv_sec)>5) {
          system("date -t > /tmp/server_cmd_time");
          last_report=current_time;
        }
        control_program->state->thread->last_seen=current_time;
        pthread_mutex_unlock(&controlprogram_list_lock);

        /* Process controlprogram msg */
        switch(msg.type) {
          case PING:
            //printf("PING: START\n");
            gettimeofday(&t0,NULL);
            msg.status=1;
            send_data(socket, &msg, sizeof(struct ROSMsg));
            //printf("PING: END\n");
            break;
          case SET_INACTIVE:
            //printf("SET_RADAR_INACTIVE\n");
            gettimeofday(&t0,NULL);
            if (verbose > 1 ) fprintf(stderr,"Client: Set INACTIVE: %ld %ld :: %d %d\n",(long)t0.tv_sec,(long)t0.tv_usec,r,c);
            if ( (r < 0) || (c < 0)) {
              msg.status=-1;
              send_data(socket, &msg, sizeof(struct ROSMsg));
            } else {
              pthread_mutex_lock(&controlprogram_list_lock);
              if(control_program->active!=0) {
                control_program->active=-1;
                control_program->state->ready=0;
                pthread_mutex_lock(&coord_lock);
                rc = pthread_create(&thread, NULL, (void *)&coordination_handler,(void *)
control_program);
                pthread_join(thread,NULL);
                pthread_mutex_unlock(&coord_lock);
              }
              pthread_mutex_unlock(&controlprogram_list_lock);
              msg.status=1;
              send_data(socket, &msg, sizeof(struct ROSMsg));
            }
            gettimeofday(&t1,NULL);
            if (verbose > 1 ) fprintf(stderr,"Client: End INACTIVE: %ld %ld :: %d %d\n",(long)t1.tv_sec,(long)t1.tv_usec,r,c);
            //printf("end SET_RADAR_INACTIVE\n");
            break;
          case SET_ACTIVE:
            gettimeofday(&t0,NULL);
            if (verbose > 1 ) fprintf(stderr,"Client: Set ACTIVE: %ld %ld :: %d %d\n",(long)t0.tv_sec,(long)t0.tv_usec,r,c);
            //printf("SET_RADAR_ACTIVE\n");
            gettimeofday(&t0,NULL);
            if ( (r < 0) || (c < 0)) {
              msg.status=-1;
              send_data(socket, &msg, sizeof(struct ROSMsg));
            } else {
              pthread_mutex_lock(&controlprogram_list_lock);
              if(control_program->active!=0) {
                control_program->active=1;
                control_program->state->ready=0;
/*  JDS : Do not need to run coordinator when setting active
                pthread_mutex_lock(&coord_lock);
                rc = pthread_create(&thread, NULL, (void *)&coordination_handler,(void *)
control_program);
                pthread_join(thread,NULL);
                pthread_mutex_unlock(&coord_lock);
*/
              }
              pthread_mutex_unlock(&controlprogram_list_lock);
              msg.status=1;
              send_data(socket, &msg, sizeof(struct ROSMsg));
            }
            gettimeofday(&t1,NULL);
            if (verbose > 1 ) fprintf(stderr,"Client: End ACTIVE: %ld %ld :: %d %d\n",(long)t1.tv_sec,(long)t1.tv_usec,r,c);
            //printf("end SET_RADAR_ACTIVE\n");
            break;
/*
          case UPDATE_SITE_SETTINGS:
            gettimeofday(&t0,NULL);
            SettingsInit(&settings);
            recv_data(socket, &settings, sizeof(struct SiteSettings));
            msg.status=-1;
            send_data(socket, &msg, sizeof(struct ROSMsg));
            SettingsCpy(&settings,&site_settings);
            rc = pthread_create(&thread, NULL, (void *)&settings_rxfe_update_rf,(void *)&site_settings.rf_settings);
            pthread_join(thread,NULL);
            rc = pthread_create(&thread, NULL, (void *)&settings_rxfe_update_if,(void *)&site_settings.if_settings);
            pthread_join(thread,NULL);
            break;
*/
          case QUERY_INI_SETTING:
            //fprintf(stdout,"start QUERY_INI_SETTING\n");
            recv_data(socket, &data_length, sizeof(int32_t));
            recv_data(socket, &entry_name, data_length*sizeof(char));
            recv_data(socket, &entry_type, sizeof(char));
            entry_exists=iniparser_find_entry(Site_INI,entry_name);
            msg.status=entry_exists;
            switch(entry_type) {
              case 'i':
                //fprintf(stdout,"  entry type: i\n");
                return_type='i';
                temp_int32=iniparser_getint(Site_INI,entry_name,-1);
                send_data(socket, &return_type, sizeof(char));
                data_length=1;
                send_data(socket, &data_length, sizeof(int32_t));
                send_data(socket, &temp_int32, data_length*sizeof(int32_t));
                break;
              case 'b':
                //fprintf(stdout,"  entry type: b\n");
                return_type='b';
                temp_int32=iniparser_getboolean(Site_INI,entry_name,-1);
                send_data(socket, &return_type, sizeof(char));
                data_length=1;
                send_data(socket, &data_length, sizeof(int32_t));
                send_data(socket, &temp_int32, data_length*sizeof(int32_t));
                break;
              case 's':
                //fprintf(stdout,"  entry type: s\n");
                return_type='s';
                temp_strp=iniparser_getstring(Site_INI,entry_name,NULL);
                send_data(socket, &return_type, sizeof(char));
                data_length=strlen(temp_strp);
                send_data(socket, &data_length, sizeof(int32_t));
                send_data(socket, temp_strp, data_length*sizeof(char));
              default:
                return_type=' ';
                send_data(socket, &return_type, sizeof(char));
                data_length=0;
                send_data(socket, &data_length, sizeof(int32_t));
                send_data(socket, temp_strp, data_length*sizeof(char));
            }
            send_data(socket, &msg, sizeof(struct ROSMsg));
            //fprintf(stdout,"end QUERY_INI_SETTING\n");
            break;
          case GET_SITE_SETTINGS:
            gettimeofday(&t0,NULL);
            settings=site_settings;
            send_data(socket, &settings, sizeof(struct SiteSettings));
            msg.status=-1;
            send_data(socket, &msg, sizeof(struct ROSMsg));
            break;
          case SET_SITE_IFMODE:
            gettimeofday(&t0,NULL);
            settings=site_settings;
            recv_data(socket, &settings.ifmode, sizeof(settings.ifmode));
            msg.status=-1;
            send_data(socket, &msg, sizeof(struct ROSMsg));
            break;
          case SET_RADAR_CHAN:
            gettimeofday(&t0,NULL);
            fprintf(stdout,"SET_RADAR_CHAN: %d.%d\n",(int)t0.tv_sec,(int)t0.tv_usec);
            fflush(stdout);
              msg.status=1;
              recv_data(socket, &radar, sizeof(int32_t)); //requested radar
              recv_data(socket, &channel, sizeof(int32_t)); //requested channel
            fprintf(stdout,"  Radar: %d Chan: %d\n",radar,channel);
            fflush(stdout);
              pthread_mutex_lock(&controlprogram_list_lock);
              status=register_radar_channel(control_program,radar,channel);
              if (status) {
              }
              else {
                if (verbose>-1) fprintf(stderr,"Control Program thread %p Bad status %d no radar channel registered\n", tid,status);
              }
              msg.status=status;
              pthread_mutex_unlock(&controlprogram_list_lock);
              send_data(socket, &msg, sizeof(struct ROSMsg));
              //printf(" END SET_RADAR_CHAN\n");
            break;
          case LINK_RADAR_CHAN:
            gettimeofday(&t0,NULL);
            msg.status=1;
            recv_data(socket, &r, sizeof(r)); //requested radar
            recv_data(socket, &c, sizeof(c)); //requested channel
            pthread_mutex_lock(&controlprogram_list_lock);
            control_program->state->linked_program=find_registered_controlprogram_by_radar_channel(r,c);
            control_program->state->linked=1;
            if (control_program->state->linked_program!=NULL) {
              status=1;
            }
            else {
              status=0;
            }
            msg.status=status;
            pthread_mutex_unlock(&controlprogram_list_lock);
            send_data(socket, &msg, sizeof(struct ROSMsg));
            break;
          case GET_PARAMETERS:
            //fprintf(stdout,"GET_PARAMETERS: START\n");
            //fflush(stdout);
            gettimeofday(&t0,NULL);
            if ( (r < 0) || (c < 0)) {
              send_data(socket, &control_parameters, sizeof(struct ControlPRM));
              msg.status=-1;
              send_data(socket, &msg, sizeof(struct ROSMsg));
            } else {
              pthread_mutex_lock(&controlprogram_list_lock);
              msg.status=status;
              control_parameters=controlprogram_fill_parameters(control_program);
              pthread_mutex_unlock(&controlprogram_list_lock);
              send_data(socket, &control_parameters, sizeof(struct ControlPRM));
              send_data(socket, &msg, sizeof(struct ROSMsg));
            }
            //fprintf(stdout,"GET_PARAMETERS: END\n");
            //fflush(stdout);
            break;
          case GET_DATA:
            //printf("GET_DATA: START\n");
            //printf("GET_DATA: Event :: sec: %d nsec: %d\n",control_program->data->event_secs,control_program->data->event_nsecs);
            //printf("GET_DATA: bad_transmit_times:: length %d \n",bad_transmit_times.length);
            //for(i=0;i<bad_transmit_times.length;i++) {
            //  printf("GET_DATA: bad_transmit_times:: %d : %d %d\n",i,bad_transmit_times.start_usec[i],bad_transmit_times.duration_usec[i]);
            //}
            gettimeofday(&t0,NULL);
            gettimeofday(&t_get_data_start,NULL);
            if (control_program->active != 1) { 
              control_program->data->status=-1;
              send_data(socket, control_program->data, sizeof(struct DataPRM));
              msg.status=-1;
              send_data(socket, &msg, sizeof(struct ROSMsg));
            } else {
              if ( (r < 0) || (c < 0)) {
                control_program->data->status=-1;
                send_data(socket, control_program->data, sizeof(struct DataPRM));
                msg.status=-1;
                send_data(socket, &msg, sizeof(struct ROSMsg));
              } else {
                msg.status=status;
                rc = pthread_create(&thread, NULL,(void *)&receiver_controlprogram_get_data,(void *) control_program);
                pthread_join(thread,NULL);
                send_data(socket, control_program->data, sizeof(struct DataPRM));
                if(control_program->data->status==0) {
                  //printf("GET_DATA: main: %d %d\n",sizeof(uint32_t),sizeof(uint32)*control_program->data->samples);
                  send_data(socket, control_program->main, sizeof(uint32_t)*control_program->data->samples);
                  send_data(socket, control_program->back, sizeof(uint32_t)*control_program->data->samples);
                  send_data(socket, &bad_transmit_times.length, sizeof(bad_transmit_times.length));
                  send_data(socket, bad_transmit_times.start_usec, sizeof(uint32_t)*bad_transmit_times.length);
                  send_data(socket, bad_transmit_times.duration_usec, sizeof(uint32_t)*bad_transmit_times.length);
                  tmp=MAX_TRANSMITTERS;
                  send_data(socket,&tmp,sizeof(int));
                  send_data(socket,&txstatus[r].AGC,sizeof(int)*tmp);
                  send_data(socket,&txstatus[r].LOWPWR,sizeof(int)*tmp);
                } else {
                  printf("GET_DATA: Bad status %d\n",control_program->data->status);
                } 
                send_data(socket, &msg, sizeof(struct ROSMsg));
              }
            }
            gettimeofday(&t1,NULL);
            if (verbose > 1) {
              elapsed=(t1.tv_sec-t0.tv_sec)*1E6;
              elapsed+=(t1.tv_usec-t0.tv_usec);
              if (verbose > 1 ) printf("Client:  Get Data Elapsed Microseconds: %ld\n",elapsed);
            }
            //printf("GET_DATA: END\n");
            gettimeofday(&t_get_data_end,NULL);
            if (verbose > 1) {
              elapsed=(t_get_data_end.tv_sec-t_pre_start.tv_sec)*1E6;
              elapsed+=(t_get_data_end.tv_usec-t_pre_start.tv_usec);
              fprintf(stderr,"Client %2d %2d:  From Pretrig start to Get Data end Elapsed Microseconds: %10ld  :: sec: %10d usec: %10d\n",r,c,elapsed,t_get_data_end.tv_sec,t_get_data_end.tv_usec);
              elapsed=(t_get_data_end.tv_sec-t_ready_first.tv_sec)*1E6;
              elapsed+=(t_get_data_end.tv_usec-t_ready_first.tv_usec);
              fprintf(stderr,"Client %2d %2d:  From Client Ready start to Get Data end Elapsed Microseconds: %10ld  :: sec: %10d usec: %10d\n",r,c,elapsed,t_get_data_end.tv_sec,t_get_data_end.tv_usec);
             fflush(stderr); 
            }
            break;
          case SET_PARAMETERS:
            //printf("SET_PARAMETERS: START\n");
            gettimeofday(&t0,NULL);
            if ( (r < 0) || (c < 0)) {
              recv_data(socket, control_program->parameters, sizeof(struct ControlPRM));
              msg.status=-1;
              send_data(socket, &msg, sizeof(struct ROSMsg));
            } else {
              msg.status=1;
              pthread_mutex_lock(&controlprogram_list_lock);
              recv_data(socket, control_program->parameters, sizeof(struct ControlPRM));
              if(control_program->parameters->rfreq<0) control_program->parameters->rfreq=control_program->parameters->tfreq;
              send_data(socket, &msg, sizeof(struct ROSMsg));
              pthread_mutex_unlock(&controlprogram_list_lock);
            }
            //printf("SET_PARAMETERS: END\n");
            break;
          case REGISTER_SEQ:
            gettimeofday(&t0,NULL);
            fprintf(stdout,"REGISTER_SEQ: r: %d c: %d  %d.%d\n",r,c,(int)t0.tv_sec,(int)t0.tv_usec);
            fflush(stdout);
            msg.status=1;
            recv_data(socket,&tprm, sizeof(struct SeqPRM)); // requested pulseseq
            pthread_mutex_lock(&controlprogram_list_lock);
            control_program->state->pulseseqs[tprm.index]=malloc(sizeof(struct TSGbuf));
            control_program->parameters->current_pulseseq_index=tprm.index;
            control_program->state->pulseseqs[tprm.index]->len=tprm.len;
            control_program->state->pulseseqs[tprm.index]->step=tprm.step;
            control_program->state->pulseseqs[tprm.index]->index=tprm.index;
            control_program->state->pulseseqs[tprm.index]->rep=
                malloc(sizeof(unsigned char)*control_program->state->pulseseqs[tprm.index]->len);
            control_program->state->pulseseqs[tprm.index]->code=
                malloc(sizeof(unsigned char)*control_program->state->pulseseqs[tprm.index]->len);
            recv_data(socket,control_program->state->pulseseqs[tprm.index]->rep, 
                sizeof(unsigned char)*control_program->state->pulseseqs[tprm.index]->len); // requested pulseseq
            recv_data(socket,control_program->state->pulseseqs[tprm.index]->code, 
                sizeof(unsigned char)*control_program->state->pulseseqs[tprm.index]->len); // requested pulseseq
            if ( (r < 0) || (c < 0)) {
              msg.status=-1;
            } else {
            //send on to timing socket
              rc = pthread_create(&threads[0], NULL, (void *)&timing_register_seq,(void *) control_program);
            //send on to dds socket
              rc = pthread_create(&threads[1], NULL, (void *)&dds_register_seq,(void *) control_program);
              //printf("Waiting on Timing Thread\n");
              pthread_join(threads[0],NULL);
              //printf("Waiting on DDS\n"); 
              pthread_join(threads[1],NULL);
            }
            pthread_mutex_unlock(&controlprogram_list_lock);
            //printf("REGISTER_SEQ: SEND ROSMsg\n");
            send_data(socket, &msg, sizeof(struct ROSMsg));
            gettimeofday(&t1,NULL);
            if (verbose > 1) {
              elapsed=(t1.tv_sec-t0.tv_sec)*1E6;
              elapsed+=(t1.tv_usec-t0.tv_usec);
              if (verbose > 1 ) printf("Client:  Reg Seq Elapsed Microseconds: %ld\n",elapsed);
            }
            //printf("REGISTER_SEQ: END\n");
            break;
          case SET_READY_FLAG:
            gettimeofday(&t0,NULL);
            if (verbose > 1 ) fprintf(stderr,"Client: Set READY: %ld %ld :: %d %d\n",(long)t0.tv_sec,(long)t0.tv_usec,r,c);
            if ( (r < 0) || (c < 0)) {
              msg.status=-1;
            } else {
              msg.status=0;
              pthread_mutex_lock(&controlprogram_list_lock);
              if (control_program->active!=0) { 
                control_program->active=1;
                control_program->state->ready=1;
              } 
              pthread_mutex_unlock(&controlprogram_list_lock);
              i=0;
              rc = pthread_create(&threads[i], NULL,(void *) &timing_wait, NULL);
              pthread_join(threads[0],NULL);
              pthread_mutex_lock(&controlprogram_list_lock);
              i=0;
              rc = pthread_create(&threads[i], NULL, (void *) &DIO_ready_controlprogram, control_program);
                pthread_join(threads[i],NULL);
              i++;
              rc = pthread_create(&threads[i], NULL, (void *) &timing_ready_controlprogram, control_program);
                pthread_join(threads[i],NULL);
              i++;
              rc = pthread_create(&threads[i], NULL, (void *) &dds_ready_controlprogram, control_program);
                pthread_join(threads[i],NULL);
              i++;
              rc = pthread_create(&threads[i], NULL, (void *) &receiver_ready_controlprogram, control_program);
                pthread_join(threads[i],NULL);
              for (;i>=0;i--) {
                gettimeofday(&t2,NULL);
                pthread_join(threads[i],NULL);
                gettimeofday(&t3,NULL);
                if (verbose > 1) {
                   elapsed=(t3.tv_sec-t2.tv_sec)*1E6;
                   elapsed+=(t3.tv_usec-t2.tv_usec);
                   if (verbose > 1 ) printf("Client:Set Ready: %d Elapsed Microseconds: %ld\n",i,elapsed);
                }
              }
              gettimeofday(&t2,NULL);
              pthread_mutex_lock(&coord_lock);
              rc = pthread_create(&thread, NULL, (void *)&coordination_handler,(void *) control_program);
              pthread_join(thread,NULL);
              pthread_mutex_unlock(&coord_lock);
              gettimeofday(&t3,NULL);
              if (verbose > 1) {
                   elapsed=(t3.tv_sec-t2.tv_sec)*1E6;
                   elapsed+=(t3.tv_usec-t2.tv_usec);
                   if (verbose > 1 ) printf("Client:Set Ready: Coord Elapsed Microseconds: %ld\n",elapsed);
              }
              pthread_mutex_unlock(&controlprogram_list_lock);
            }
            send_data(socket, &msg, sizeof(struct ROSMsg));
            gettimeofday(&t1,NULL);
            if (verbose > 1) {
              elapsed=(t1.tv_sec-t0.tv_sec)*1E6;
              elapsed+=(t1.tv_usec-t0.tv_usec);
              if (verbose > 1 ) printf("Client:  Set Ready Elapsed Microseconds: %ld\n",elapsed);
            }
            if (verbose > 1 ) fprintf(stderr,"Client: End READY: %ld %ld :: %d %d\n",(long)t1.tv_sec,(long)t1.tv_usec,r,c);
            break;

          case REQUEST_CLEAR_FREQ_SEARCH:
            gettimeofday(&t0,NULL);
            pthread_mutex_lock(&controlprogram_list_lock);
            recv_data(socket,&control_program->clrfreqsearch, sizeof(struct CLRFreqPRM)); // requested search parameters
            if (verbose > 1 )printf("Client: Requst CLRSearch: %d %d\n",control_program->clrfreqsearch.start,control_program->clrfreqsearch.end);
            if ( (r < 0) || (c < 0)) {
              msg.status=-1;
            } else {
              rc = pthread_create(&threads[0], NULL, (void *) &DIO_clrfreq,control_program);
              pthread_join(threads[0],NULL);
              rc = pthread_create(&threads[0], NULL, (void *) &receiver_clrfreq,control_program);
              pthread_join(threads[0],NULL);
              rc = pthread_create(&threads[0], NULL, (void *) &DIO_rxfe_reset,NULL);
              pthread_join(threads[0],NULL);
              msg.status=control_program->state->freq_change_needed;
            }
            send_data(socket, &msg, sizeof(struct ROSMsg));
            pthread_mutex_unlock(&controlprogram_list_lock);
            gettimeofday(&t1,NULL);
            if (verbose > 1) {
              elapsed=(t1.tv_sec-t0.tv_sec)*1E6;
              elapsed+=(t1.tv_usec-t0.tv_usec);
              if (verbose > 1 ) printf("Client:  CLR Elapsed Microseconds: %ld\n",elapsed);
            }
            break;
          case REQUEST_ASSIGNED_FREQ:
            gettimeofday(&t0,NULL);
            pthread_mutex_lock(&controlprogram_list_lock);
            if ( (r < 0) || (c < 0)) {
              msg.status=-1;
              control_program->state->current_assigned_freq=0;
              control_program->state->current_assigned_noise=0;
            } else {
              rc = pthread_create(&threads[0], NULL, (void *) &receiver_assign_frequency,(void *)  control_program);
              pthread_join(threads[0],NULL);
              msg.status=control_program->state->best_assigned_freq!=control_program->state->current_assigned_freq;
            }
            //control_program->state->current_assigned_noise=1;
            current_freq=control_program->state->current_assigned_freq; 
            send_data(socket, &current_freq, sizeof(int32_t));
            send_data(socket, &control_program->state->current_assigned_noise, sizeof(float));
            send_data(socket, &msg, sizeof(struct ROSMsg));
            pthread_mutex_unlock(&controlprogram_list_lock);
            gettimeofday(&t1,NULL);
            if (verbose > 1) {
              elapsed=(t1.tv_sec-t0.tv_sec)*1E6;
              elapsed+=(t1.tv_usec-t0.tv_usec);
              if (verbose > 1 ) printf("Client:  Request Freq Elapsed Microseconds: %ld\n",elapsed);
            }
            break;

          case QUIT:
            gettimeofday(&t0,NULL);
            fprintf(stdout,"Client QUIT:: %d.%06d \n",(int)t0.tv_sec,(int)t0.tv_usec);
            fflush(stdout);
            msg.status=0;
            send_data(socket, &msg, sizeof(struct ROSMsg));
            //controlprogram_exit(control_program);
            pthread_exit(NULL);
            break;
          default:
            msg.status=1;
            send_data(socket, &msg, sizeof(struct ROSMsg));
        }
          /* FD_ISSET(0, &rfds) will be true. */
      } //else printf("No data within five seconds.\n");
//        if (verbose>1) printf("Client: test cancel\n");
        
        pthread_testcancel();
   }
   fprintf(stdout,"Outside of socket while loop : %p\n",control_program);
   fflush(stdout);
   pthread_testcancel();
   pthread_cleanup_pop(0);
   controlprogram_exit(control_program);
   pthread_exit(NULL);
};
Exemple #10
0
size_t buffer_get_data (buf_t *buf, char *data, long nbytes)
{
  int write_amount;
  int orig_size;

  orig_size = nbytes;

  DEBUG("Enter buffer_get_data");

  pthread_cleanup_push(buffer_mutex_unlock, buf);

  LOCK_MUTEX(buf->mutex);

  /* Put the data into the buffer as space is made available */
  while (nbytes > 0) {

    if (buf->abort_write)
      break;

    DEBUG("Obtaining lock on buffer");
    /* Block until we can read something */
    if (buf->curfill == 0 && buf->eos)
      break; /* No more data to read */
      
    if (buf->curfill == 0 || (buf->prebuffering && !buf->eos)) {
      DEBUG("Waiting for more data to copy.");
      COND_WAIT(buf->playback_cond, buf->mutex);
    }

    if (buf->abort_write)
      break;

    /* Note: Even if curfill is still 0, nothing bad will happen here */
    
    /* For simplicity, the number of bytes played must satisfy
       the following three requirements:
       
       1. Do not copy more bytes than are stored in the buffer.
       2. Do not copy more bytes than the reqested data size.
       3. Do not run off the end of the buffer. */
    write_amount = compute_dequeue_size(buf, nbytes);

    UNLOCK_MUTEX(buf->mutex);
    execute_actions(buf, &buf->actions, buf->position);

    /* No need to lock mutex here because the other thread will
       NEVER reduce the number of bytes stored in the buffer */
    DEBUG1("Copying %d bytes from the buffer", write_amount);
    memcpy(data, buf->buffer + buf->start, write_amount);
    LOCK_MUTEX(buf->mutex);

    buf->curfill -= write_amount;
    data += write_amount;
    nbytes -= write_amount;
    buf->start = (buf->start + write_amount) % buf->size;
    DEBUG1("Updated buffer fill, curfill = %ld", buf->curfill);
    
    /* Signal a waiting decoder thread that they can put more
       audio into the buffer */
    DEBUG("Signal decoder thread that buffer space is available");
    COND_SIGNAL(buf->write_cond);
  }

  UNLOCK_MUTEX(buf->mutex);

  pthread_cleanup_pop(0);
  
  pthread_testcancel();

  DEBUG("Exit buffer_get_data");
   
  return orig_size - nbytes;
}
/******************************************************************************
Description.: this is the main worker thread
              it loops forever, grabs a fresh frame, decompressed the JPEG
              and displays the decoded data using SDL
Input Value.:
Return Value:
******************************************************************************/
void *worker_thread(void *arg)
{
    int frame_size = 0, firstrun = 1;

    SDL_Surface *screen = NULL, *image = NULL;
    decompressed_image rgbimage;

    /* initialze the buffer for the decompressed image */
    rgbimage.buffersize = 0;
    rgbimage.buffer = NULL;

    /* initialze the SDL video subsystem */
    if(SDL_Init(SDL_INIT_VIDEO) < 0) {
        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
        exit(EXIT_FAILURE);
    }

    /* just allocate a large buffer for the JPEGs */
    if((frame = malloc(4096 * 1024)) == NULL) {
        OPRINT("not enough memory for worker thread\n");
        exit(EXIT_FAILURE);
    }

    /* set cleanup handler to cleanup allocated ressources */
    pthread_cleanup_push(worker_cleanup, NULL);

    while(!pglobal->stop) {
        DBG("waiting for fresh frame\n");
        pthread_cond_wait(&pglobal->db_update, &pglobal->db);

        /* read buffer */
        frame_size = pglobal->size;
        memcpy(frame, pglobal->buf, frame_size);

        pthread_mutex_unlock(&pglobal->db);

        /* decompress the JPEG and store results in memory */
        if(decompress_jpeg(frame, frame_size, &rgbimage)) {
            DBG("could not properly decompress JPEG data\n");
            continue;
        }

        if(firstrun) {
            /* create the primary surface (the visible window) */
            screen = SDL_SetVideoMode(rgbimage.width, rgbimage.height, 0, SDL_ANYFORMAT | SDL_HWSURFACE);
            SDL_WM_SetCaption("MJPG-Streamer Viewer", NULL);

            /* create a SDL surface to display the data */
            image = SDL_AllocSurface(SDL_SWSURFACE, rgbimage.width, rgbimage.height, 24,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
                                     0x0000FF, 0x00FF00, 0xFF0000,
#else
                                     0xFF0000, 0x00FF00, 0x0000FF,
#endif
                                     0);

            /* copy the decoded data across */
            memcpy(image->pixels, rgbimage.buffer, rgbimage.width * rgbimage.height * 3);
            free(rgbimage.buffer);

            /* now, that we know the dimensions, we can directly copy to the right surface */
            rgbimage.buffer = image->pixels;
            rgbimage.buffersize = rgbimage.width * rgbimage.height * 3;

            firstrun = 0;
        }

        /* copy the image to the primary surface */
        SDL_BlitSurface(image, NULL, screen, NULL);

        /* redraw the whole surface */
        SDL_Flip(screen);
    }

    pthread_cleanup_pop(1);

    /* get rid of the image */
    SDL_FreeSurface(image);

    return NULL;
}
Exemple #12
0
void submit_data_chunk (buf_t *buf, char *data, size_t size)
{
  long   buf_write_pos; /* offset of first available write location */
  size_t write_size;

  DEBUG1("Enter submit_data_chunk, size %d", size);

  pthread_cleanup_push(buffer_mutex_unlock, buf);

  /* Put the data into the buffer as space is made available */
  while (size > 0 && !buf->abort_write) {
    
    /* Section 1: Write a chunk of data */
    DEBUG("Obtaining lock on buffer");
    LOCK_MUTEX(buf->mutex);
    if (buf->size - buf->curfill > 0) {
      
      /* Figure how much we can write into the buffer.  Requirements:
	 1. Don't write more data than we have.
	 2. Don't write more data than we have room for.
	 3. Don't write past the end of the buffer. */
      buf_write_pos = (buf->start + buf->curfill) % buf->size;
      write_size = MIN3(size, buf->size - buf->curfill,
			buf->size - buf_write_pos);
      
      memcpy(buf->buffer + buf_write_pos, data, write_size);
      buf->curfill += write_size;
      data += write_size;
      size -= write_size;
      buf->position_end += write_size;
      DEBUG1("writing chunk into buffer, curfill = %ld", buf->curfill);
    }
    else {

      /* No room for more data, wait until there is */
      DEBUG("No room for data in buffer.  Waiting.");
      COND_WAIT(buf->write_cond, buf->mutex);
    }
      
    /* Section 2: signal if we are not prebuffering, done
       prebuffering, or paused */
    if (buf->prebuffering && (buf->prebuffer_size <= buf->curfill)) {

      DEBUG("prebuffering done")
	buf->prebuffering = 0; /* done prebuffering */
    }

    if (!buf->prebuffering && !buf->paused) {

      DEBUG("Signalling playback thread that more data is available.");
      COND_SIGNAL(buf->playback_cond);      
    } else
      DEBUG("Not signalling playback thread since prebuffering or paused.");
      
    UNLOCK_MUTEX(buf->mutex);
  }

  pthread_cleanup_pop(0);

  DEBUG("Exit submit_data_chunk");
}
Exemple #13
0
void *buffer_thread_func (void *arg)
{
  buf_t *buf = (buf_t*) arg;
  size_t write_amount;
  
  DEBUG("Enter buffer_thread_func");
  
  buffer_thread_init(buf);

  pthread_cleanup_push(buffer_thread_cleanup, buf);
  
  DEBUG("Start main play loop");
  
  /* This test is safe since curfill will never decrease and eos will
     never be unset. */
  while ( !(buf->eos && buf->curfill == 0)) {

    if (buf->cancel_flag || sig_request.cancel)
      break;
    
    DEBUG("Check for something to play");
    /* Block until we can play something */
    LOCK_MUTEX (buf->mutex);
    if (buf->prebuffering || 
	buf->paused || 
	(buf->curfill < buf->audio_chunk_size && !buf->eos)) {

      DEBUG("Waiting for more data to play.");
      COND_WAIT(buf->playback_cond, buf->mutex);
    }
    
    DEBUG("Ready to play");
    
    UNLOCK_MUTEX(buf->mutex);

    if (buf->cancel_flag || sig_request.cancel)
      break;

    /* Don't need to lock buffer while running actions since position
       won't change.  We clear out any actions before we compute the
       dequeue size so we don't consider actions that need to
       run right now.  */
    execute_actions(buf, &buf->actions, buf->position);

    LOCK_MUTEX(buf->mutex);

    /* Need to be locked while we check things. */
    write_amount = compute_dequeue_size(buf, buf->audio_chunk_size);

    UNLOCK_MUTEX(buf->mutex);
 
    /* No need to lock mutex here because the other thread will
       NEVER reduce the number of bytes stored in the buffer */
    DEBUG1("Sending %d bytes to the audio device", write_amount);
    write_amount = buf->write_func(buf->buffer + buf->start, write_amount,
		    /* Only set EOS if this is the last chunk */
		    write_amount == buf->curfill ? buf->eos : 0,
		    buf->write_arg);
      
    LOCK_MUTEX(buf->mutex);

    buf->curfill -= write_amount;
    buf->position += write_amount;
    buf->start = (buf->start + write_amount) % buf->size;
    DEBUG1("Updated buffer fill, curfill = %ld", buf->curfill);

    /* If we've essentially emptied the buffer and prebuffering is enabled,
       we need to do another prebuffering session */
    if (!buf->eos && (buf->curfill < buf->audio_chunk_size))
      buf->prebuffering = buf->prebuffer_size > 0;
    
    /* Signal a waiting decoder thread that they can put more audio into the
       buffer */
    DEBUG("Signal decoder thread that buffer space is available");
    COND_SIGNAL(buf->write_cond);
    
    UNLOCK_MUTEX(buf->mutex);
  }
  
  pthread_cleanup_pop(1);
  DEBUG("exiting buffer_thread_func");

  return 0;
}
static void* ngx_http_monitor_send_mainloop(void* args) {
    ngx_http_monitor_sender_t* sender = (ngx_http_monitor_sender_t*)args;

    pthread_cleanup_push(ngx_http_monitor_destory_sender, sender);

    ngx_http_monitor_server_t* uscfp = sender->servers->elts;

    int totalfd = sender->servers->nelts;
    int maxfd = 0;
    int i;

    u_char* sendp;
    ngx_int_t sendlen;

    struct epoll_event event;
    struct epoll_event events[totalfd];

    //since linux 2.6.8, the size arg is unused, but must be > 0
//  int epollfd = epoll_create1(0); // won't compile
    int epollfd = epoll_create(1024);
    if (epollfd == -1) {
        // error
        return NULL;
    }

    for (i = 0; i < totalfd; i++) {
        int sockfd = uscfp[i].sockfd;

        event.events = EPOLLOUT | EPOLLET;
        event.data.fd = sockfd;
        epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &event);

        if (sockfd > maxfd) {
            maxfd = sockfd;
        }
    }

    while (!ngx_quit && !ngx_terminate) {
        ngx_http_monitor_str_t* str = ngx_http_monitor_pull_queue( sender->queue );

        ngx_uint_t leftfd = totalfd;

        // FIXME:
        while (leftfd > 0) {
            int nfds = epoll_wait(epollfd, events, maxfd + 1, 1000);

            if (nfds <= 0) {
                // error
                continue;
            }

            for (i = 0; i < nfds; i++) {
                struct sockaddr_in* addr = uscfp[i].sockaddr;
                socklen_t socklen = uscfp[i].socklen;
                int sockfd = uscfp[i].sockfd;

                sendp = str->buf;
                sendlen = str->buflen;

                while (sendlen > 0) {
                    int ret = sendto ( sockfd, sendp, sendlen, 0, addr, socklen );
                    if (ret == -1) {
                        if (EAGAIN == errno) {
                            continue;
                        }

                        ngx_log_error ( NGX_LOG_ERR, sender->log, 0, "Failed to send messege to peer:%s %d, %s",
                                        addr->sin_addr.s_addr,addr->sin_port, strerror(errno));
                    }

                    sendp += ret;
                    sendlen -= ret;
                }

                event.events = EPOLLOUT | EPOLLET;
                event.data.fd = sockfd;
                epoll_ctl(epollfd, EPOLL_CTL_DEL, sockfd, &event);
            }

            leftfd -= nfds;
        }

        free(str->buf);
        free(str);

        for (i = 0; i < totalfd; i++) {
            int sockfd = uscfp[i].sockfd;

            event.events = EPOLLOUT | EPOLLET;
            event.data.fd = sockfd;
            epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &event);
        }
    }

    pthread_cleanup_pop(0);

    return NULL;
}
Exemple #15
0
/**
 * WaitForMultipleObjectsEx:
 * @numobjects: The number of objects in @handles. The maximum allowed
 * is %MAXIMUM_WAIT_OBJECTS.
 * @handles: An array of object handles.  Duplicates are not allowed.
 * @waitall: If %TRUE, this function waits until all of the handles
 * are signalled.  If %FALSE, this function returns when any object is
 * signalled.
 * @timeout: The maximum time in milliseconds to wait for.
 * @alertable: if TRUE, the wait can be interrupted by an APC call
 * 
 * This function returns when either one or more of @handles is
 * signalled, or @timeout ms elapses.  If @timeout is zero, the state
 * of each item of @handles is tested and the function returns
 * immediately.  If @timeout is %INFINITE, the function waits forever.
 *
 * Return value: %WAIT_OBJECT_0 to %WAIT_OBJECT_0 + @numobjects - 1 -
 * if @waitall is %TRUE, indicates that all objects are signalled.  If
 * @waitall is %FALSE, the return value minus %WAIT_OBJECT_0 indicates
 * the first index into @handles of the objects that are signalled.
 * %WAIT_ABANDONED_0 to %WAIT_ABANDONED_0 + @numobjects - 1 - if
 * @waitall is %TRUE, indicates that all objects are signalled, and at
 * least one object is an abandoned mutex object (See
 * WaitForSingleObject() for a description of abandoned mutexes.)  If
 * @waitall is %FALSE, the return value minus %WAIT_ABANDONED_0
 * indicates the first index into @handles of an abandoned mutex.
 * %WAIT_TIMEOUT - The @timeout interval elapsed and no objects in
 * @handles are signalled.  %WAIT_FAILED - an error occurred.
 * %WAIT_IO_COMPLETION - the wait was ended by an APC.
 */
guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
				 gboolean waitall, guint32 timeout,
				 gboolean alertable)
{
	GHashTable *dups;
	gboolean duplicate = FALSE, bogustype = FALSE, done;
	guint32 count, lowest;
	struct timespec abstime;
	guint i;
	guint32 ret;
	int thr_ret;
	gpointer current_thread = _wapi_thread_handle_from_id (pthread_self ());
	guint32 retval;
	gboolean poll;
	
	if (current_thread == NULL) {
		SetLastError (ERROR_INVALID_HANDLE);
		return(WAIT_FAILED);
	}
	
	if (numobjects > MAXIMUM_WAIT_OBJECTS) {
#ifdef DEBUG
		g_message ("%s: Too many handles: %d", __func__, numobjects);
#endif

		return(WAIT_FAILED);
	}
	
	if (numobjects == 1) {
		return WaitForSingleObjectEx (handles [0], timeout, alertable);
	}

	/* Check for duplicates */
	dups = g_hash_table_new (g_direct_hash, g_direct_equal);
	for (i = 0; i < numobjects; i++) {
		gpointer exists;

		if (handles[i] == _WAPI_THREAD_CURRENT) {
			handles[i] = _wapi_thread_handle_from_id (pthread_self ());
			
			if (handles[i] == NULL) {
#ifdef DEBUG
				g_message ("%s: Handle %d bogus", __func__, i);
#endif

				bogustype = TRUE;
				break;
			}
		}

		if ((GPOINTER_TO_UINT (handles[i]) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
#ifdef DEBUG
			g_message ("%s: Handle %d pseudo process", __func__,
				   i);
#endif

			bogustype = TRUE;
			break;
		}
		
		exists = g_hash_table_lookup (dups, handles[i]);
		if (exists != NULL) {
#ifdef DEBUG
			g_message ("%s: Handle %p duplicated", __func__,
				   handles[i]);
#endif

			duplicate = TRUE;
			break;
		}

		if (_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_WAIT) == FALSE) {
#ifdef DEBUG
			g_message ("%s: Handle %p can't be waited for",
				   __func__, handles[i]);
#endif

			bogustype = TRUE;
			break;
		}

		g_hash_table_insert (dups, handles[i], handles[i]);
		_wapi_handle_ops_prewait (handles[i]);
	}
	g_hash_table_destroy (dups);

	if (duplicate == TRUE) {
#ifdef DEBUG
		g_message ("%s: Returning due to duplicates", __func__);
#endif

		return(WAIT_FAILED);
	}

	if (bogustype == TRUE) {
#ifdef DEBUG
		g_message ("%s: Returning due to bogus type", __func__);
#endif

		return(WAIT_FAILED);
	}

	poll = FALSE;
	for (i = 0; i < numobjects; ++i)
		if (_wapi_handle_type (handles [i]) == WAPI_HANDLE_PROCESS)
			/* Can't wait for a process handle + another handle without polling */
			poll = TRUE;

	done = test_and_own (numobjects, handles, waitall, &count, &lowest);
	if (done == TRUE) {
		return(WAIT_OBJECT_0+lowest);
	}
	
	if (timeout == 0) {
		return WAIT_TIMEOUT;
	}
	/* Have to wait for some or all handles to become signalled
	 */

	if(timeout!=INFINITE) {
		_wapi_calc_timeout (&abstime, timeout);
	}

	if (alertable && _wapi_thread_apc_pending (current_thread)) {
		_wapi_thread_dispatch_apc_queue (current_thread);
		return WAIT_IO_COMPLETION;
	}
	
	for (i = 0; i < numobjects; i++) {
		/* Add a reference, as we need to ensure the handle wont
		 * disappear from under us while we're waiting in the loop
		 * (not lock, as we don't want exclusive access here)
		 */
		_wapi_handle_ref (handles[i]);
	}

	while(1) {
		/* Prod all handles with prewait methods and
		 * special-wait handles that aren't already signalled
		 */
		for (i = 0; i < numobjects; i++) {
			_wapi_handle_ops_prewait (handles[i]);
		
			if (_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE && _wapi_handle_issignalled (handles[i]) == FALSE) {
				_wapi_handle_ops_special_wait (handles[i], 0);
			}
		}
		
#ifdef DEBUG
		g_message ("%s: locking signal mutex", __func__);
#endif

		pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_signal_mutex, NULL);
		thr_ret = _wapi_handle_lock_signal_mutex ();
		g_assert (thr_ret == 0);

		/* Check the signalled state of handles inside the critical section */
		if (waitall) {
			done = TRUE;
			for (i = 0; i < numobjects; i++)
				if (!_wapi_handle_issignalled (handles [i]))
					done = FALSE;
		} else {
			done = FALSE;
			for (i = 0; i < numobjects; i++)
				if (_wapi_handle_issignalled (handles [i]))
					done = TRUE;
		}
		
		if (!done) {
			/* Enter the wait */
			if (timeout == INFINITE) {
				ret = _wapi_handle_wait_signal (poll);
			} else {
				ret = _wapi_handle_timedwait_signal (&abstime, poll);
			}
		} else {
			/* No need to wait */
			ret = 0;
		}

#ifdef DEBUG
		g_message ("%s: unlocking signal mutex", __func__);
#endif

		thr_ret = _wapi_handle_unlock_signal_mutex (NULL);
		g_assert (thr_ret == 0);
		pthread_cleanup_pop (0);
		
		if (alertable && _wapi_thread_apc_pending (current_thread)) {
			_wapi_thread_dispatch_apc_queue (current_thread);
			retval = WAIT_IO_COMPLETION;
			break;
		}
	
		/* Check if everything is signalled, as we can't
		 * guarantee to notice a shared signal even if the
		 * wait timed out
		 */
		done = test_and_own (numobjects, handles, waitall,
				     &count, &lowest);
		if (done == TRUE) {
			retval = WAIT_OBJECT_0+lowest;
			break;
		} else if (ret != 0) {
			/* Didn't get all handles, and there was a
			 * timeout or other error
			 */
#ifdef DEBUG
			g_message ("%s: wait returned error: %s", __func__,
				   strerror (ret));
#endif

			if(ret==ETIMEDOUT) {
				retval = WAIT_TIMEOUT;
			} else {
				retval = WAIT_FAILED;
			}
			break;
		}
	}

	for (i = 0; i < numobjects; i++) {
		/* Unref everything we reffed above */
		_wapi_handle_unref (handles[i]);
	}

	return retval;
}
Exemple #16
0
/******************************************************************************
Description.: this is the main worker thread
              it loops forever, grabs a fresh frame and stores it to file
Input Value.:
Return Value:
******************************************************************************/
void *worker_thread(void *arg)
{
    int ok = 1, frame_size = 0, rc = 0;
    char buffer1[1024] = {0};
    unsigned char *tmp_framebuffer = NULL;

    /* set cleanup handler to cleanup allocated ressources */
    pthread_cleanup_push(worker_cleanup, NULL);

    // set UDP server data structures ---------------------------
    if(port <= 0) {
        OPRINT("a valid UDP port must be provided\n");
        return NULL;
    }
    struct sockaddr_in addr;
    int sd;
    int bytes;
    unsigned int addr_len = sizeof(addr);
    char udpbuffer[1024] = {0};
    sd = socket(PF_INET, SOCK_DGRAM, 0);
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);
    if(bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0)
        perror("bind");
    // -----------------------------------------------------------

    while(ok >= 0 && !pglobal->stop) {
        DBG("waiting for a UDP message\n");

        // UDP receive ---------------------------------------------
        memset(udpbuffer, 0, sizeof(udpbuffer));
        bytes = recvfrom(sd, udpbuffer, sizeof(udpbuffer), 0, (struct sockaddr*)&addr, &addr_len);
        // ---------------------------------------------------------



        DBG("waiting for fresh frame\n");
        pthread_cond_wait(&pglobal->in[input_number].db_update, &pglobal->in[input_number].db);

        /* read buffer */
        frame_size = pglobal->in[input_number].size;

        /* check if buffer for frame is large enough, increase it if necessary */
        if(frame_size > max_frame_size) {
            DBG("increasing buffer size to %d\n", frame_size);

            max_frame_size = frame_size + (1 << 16);
            if((tmp_framebuffer = realloc(frame, max_frame_size)) == NULL) {
                pthread_mutex_unlock(&pglobal->in[input_number].db);
                LOG("not enough memory\n");
                return NULL;
            }

            frame = tmp_framebuffer;
        }

        /* copy frame to our local buffer now */
        memcpy(frame, pglobal->in[input_number].buf, frame_size);

        /* allow others to access the global buffer again */
        pthread_mutex_unlock(&pglobal->in[input_number].db);

        /* only save a file if a name came in with the UDP message */
        if(strlen(udpbuffer) > 0) {
            DBG("writing file: %s\n", udpbuffer);

            /* open file for write. Path must pre-exist */
            if((fd = open(udpbuffer, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
                OPRINT("could not open the file %s\n", udpbuffer);
                return NULL;
            }

            /* save picture to file */
            if(write(fd, frame, frame_size) < 0) {
                OPRINT("could not write to file %s\n", udpbuffer);
                perror("write()");
                close(fd);
                return NULL;
            }

            close(fd);
        }

        // send back client's message that came in udpbuffer
        sendto(sd, udpbuffer, bytes, 0, (struct sockaddr*)&addr, sizeof(addr));

        /* call the command if user specified one, pass current filename as argument */
        if(command != NULL) {
            memset(buffer1, 0, sizeof(buffer1));

            /* udpbuffer still contains the filename, pass it to the command as parameter */
            snprintf(buffer1, sizeof(buffer1), "%s \"%s\"", command, udpbuffer);
            DBG("calling command %s", buffer1);

            /* in addition provide the filename as environment variable */
            if((rc = setenv("MJPG_FILE", udpbuffer, 1)) != 0) {
                LOG("setenv failed (return value %d)\n", rc);
            }

            /* execute the command now */
            if((rc = system(buffer1)) != 0) {
                LOG("command failed (return value %d)\n", rc);
            }
        }

        /* if specified, wait now */
        if(delay > 0) {
            usleep(1000 * delay);
        }
    }

    // close UDP port
    if(port > 0)
        close(sd);

    /* cleanup now */
    pthread_cleanup_pop(1);

    return NULL;
}
Exemple #17
0
/**
 * WaitForSingleObjectEx:
 * @handle: an object to wait for
 * @timeout: the maximum time in milliseconds to wait for
 * @alertable: if TRUE, the wait can be interrupted by an APC call
 *
 * This function returns when either @handle is signalled, or @timeout
 * ms elapses.  If @timeout is zero, the object's state is tested and
 * the function returns immediately.  If @timeout is %INFINITE, the
 * function waits forever.
 *
 * Return value: %WAIT_ABANDONED - @handle is a mutex that was not
 * released by the owning thread when it exited.  Ownership of the
 * mutex object is granted to the calling thread and the mutex is set
 * to nonsignalled.  %WAIT_OBJECT_0 - The state of @handle is
 * signalled.  %WAIT_TIMEOUT - The @timeout interval elapsed and
 * @handle's state is still not signalled.  %WAIT_FAILED - an error
 * occurred. %WAIT_IO_COMPLETION - the wait was ended by an APC.
 */
guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
			      gboolean alertable)
{
	guint32 ret, waited;
	struct timespec abstime;
	int thr_ret;
	gboolean apc_pending = FALSE;
	gpointer current_thread = _wapi_thread_handle_from_id (pthread_self ());
	
	if (current_thread == NULL) {
		SetLastError (ERROR_INVALID_HANDLE);
		return(WAIT_FAILED);
	}

	if (handle == _WAPI_THREAD_CURRENT) {
		handle = _wapi_thread_handle_from_id (pthread_self ());
		if (handle == NULL) {
			SetLastError (ERROR_INVALID_HANDLE);
			return(WAIT_FAILED);
		}
	}

	if ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
		SetLastError (ERROR_INVALID_HANDLE);
		return(WAIT_FAILED);
	}
	
	if (_wapi_handle_test_capabilities (handle,
					    WAPI_HANDLE_CAP_WAIT) == FALSE) {
#ifdef DEBUG
		g_message ("%s: handle %p can't be waited for", __func__,
			   handle);
#endif

		return(WAIT_FAILED);
	}

	_wapi_handle_ops_prewait (handle);
	
	if (_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE) {
#ifdef DEBUG
		g_message ("%s: handle %p has special wait", __func__, handle);
#endif

		ret = _wapi_handle_ops_special_wait (handle, timeout);
	
		if (alertable && _wapi_thread_apc_pending (current_thread)) {
			apc_pending = TRUE;
			ret = WAIT_IO_COMPLETION;
		}

		goto check_pending;
	}
	
	
#ifdef DEBUG
	g_message ("%s: locking handle %p", __func__, handle);
#endif

	pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
			      handle);
	thr_ret = _wapi_handle_lock_handle (handle);
	g_assert (thr_ret == 0);

	if (_wapi_handle_test_capabilities (handle,
					    WAPI_HANDLE_CAP_OWN) == TRUE) {
		if (own_if_owned (handle) == TRUE) {
#ifdef DEBUG
			g_message ("%s: handle %p already owned", __func__,
				   handle);
#endif
			ret = WAIT_OBJECT_0;
			goto done;
		}
	}
	
	if (alertable && _wapi_thread_apc_pending (current_thread)) {
		apc_pending = TRUE;
		ret = WAIT_IO_COMPLETION;
		goto done;
	}
	
	if (own_if_signalled (handle) == TRUE) {
#ifdef DEBUG
		g_message ("%s: handle %p already signalled", __func__,
			   handle);
#endif

		ret=WAIT_OBJECT_0;
		goto done;
	}

	if (timeout == 0) {
		ret = WAIT_TIMEOUT;
		goto done;
	}
	/* Have to wait for it */
	if (timeout != INFINITE) {
		_wapi_calc_timeout (&abstime, timeout);
	}
	
	do {
		/* Check before waiting on the condition, just in case
		 */
		_wapi_handle_ops_prewait (handle);

		if (own_if_signalled (handle)) {
#ifdef DEBUG
			g_message ("%s: handle %p signalled", __func__,
				   handle);
#endif

			ret = WAIT_OBJECT_0;
			goto done;
		}
			
		if (timeout == INFINITE) {
			waited = _wapi_handle_wait_signal_handle (handle, alertable);
		} else {
			waited = _wapi_handle_timedwait_signal_handle (handle, &abstime, alertable, FALSE);
		}
	
		if (alertable)
			apc_pending = _wapi_thread_apc_pending (current_thread);

		if(waited==0 && !apc_pending) {
			/* Condition was signalled, so hopefully
			 * handle is signalled now.  (It might not be
			 * if someone else got in before us.)
			 */
			if (own_if_signalled (handle)) {
#ifdef DEBUG
				g_message ("%s: handle %p signalled", __func__,
					   handle);
#endif

				ret=WAIT_OBJECT_0;
				goto done;
			}
		
			/* Better luck next time */
		}
	} while(waited == 0 && !apc_pending);

	/* Timeout or other error */
#ifdef DEBUG
	g_message ("%s: wait on handle %p error: %s", __func__, handle,
		   strerror (waited));
#endif

	ret = WAIT_TIMEOUT;
	
done:

#ifdef DEBUG
	g_message ("%s: unlocking handle %p", __func__, handle);
#endif
	
	thr_ret = _wapi_handle_unlock_handle (handle);
	g_assert (thr_ret == 0);
	pthread_cleanup_pop (0);
	
check_pending:
	if (apc_pending) {
		_wapi_thread_dispatch_apc_queue (current_thread);
		ret = WAIT_IO_COMPLETION;
	}
		
	return(ret);
}
Exemple #18
0
void* fctThreadClavier(void* param)
{
   param = NULL;
   //printf("--Thread clavier\n");
   pthread_cleanup_push(fctThreadClavierFin, 0);
   int token;
   while(1)
      {
         token = ReadChar();
         switch (token)
            {
            case KEY_UP :
               //printf("KEY_UP\n");
               //haut++;
               //pthread_mutex_lock(&mutexPause);
               //while(threadPause == 1)
                 // pthread_cond_wait(&condPause, &mutexPause);
               //pthread_mutex_unlock(&mutexPause);
               pthread_mutex_lock(&mutexEvent);
               haut = 19;
               pthread_mutex_unlock(&mutexEvent);
               pthread_cond_signal(&condEvent);
               break;
            case KEY_DOWN :
               //printf("KEY_DOWN\n");
            //    pthread_mutex_lock(&mutexPause);
             //  while(threadPause == 1)
              //    pthread_cond_wait(&condPause, &mutexPause);
              // pthread_mutex_unlock(&mutexPause);
               
               pthread_mutex_lock(&mutexEvent);
               rotation++;
               pthread_mutex_unlock(&mutexEvent);
               pthread_cond_signal(&condEvent);
               break;
            case KEY_LEFT :
               //printf("KEY_LEFT\n");
            //   pthread_mutex_lock(&mutexPause);
             //  while(threadPause == 1)
               //   pthread_cond_wait(&condPause, &mutexPause);
             //  pthread_mutex_unlock(&mutexPause);
               
               pthread_mutex_lock(&mutexEvent);
               gauche++;
               pthread_mutex_unlock(&mutexEvent);
               pthread_cond_signal(&condEvent);        
               break;
            case KEY_RIGHT :
               //printf("KEY_RIGHT\n");
             //   pthread_mutex_lock(&mutexPause);
             //  while(threadPause == 1)
               //   pthread_cond_wait(&condPause, &mutexPause);
              // pthread_mutex_unlock(&mutexPause);
             
               pthread_mutex_lock(&mutexEvent);
               droite++;
               pthread_mutex_unlock(&mutexEvent);
               pthread_cond_signal(&condEvent);
               break;
            case 'p':
               //printf("Jeu en pause ...\n");
               
               pthread_mutex_lock(&mutexPause);
               if(threadPause == 1)
                  {
                     AffChaine("                ", 10, 4, 0);
                     threadPause = 0;
                     pthread_cond_signal(&condPause);
                     pthread_cond_signal(&condPause);
                     pthread_cond_signal(&condPause);
                     pthread_cond_signal(&condPause);
                     pthread_cond_signal(&condPause);
                     pthread_cond_signal(&condPause);
                     pthread_cond_signal(&condPause);
                  }
               else
                  {
                     AffChaine("Jeu en pause ...", 10, 4, 0);
                     threadPause = 1;
                  }
               pthread_mutex_unlock(&mutexPause);

               break;
            }
         if(partieEnCours == 0)
            break;
      }
   pthread_cleanup_pop(1);
   pthread_exit(NULL);
}
Exemple #19
0
static void *worker(void UNUSED(*arg))
{
  MYLDAP_SESSION *session;
  int csock;
  int j;
  struct sockaddr_storage addr;
  socklen_t alen;
  fd_set fds;
  struct timeval tv;
  /* create a new LDAP session */
  session = myldap_create_session();
  /* clean up the session if we're done */
  pthread_cleanup_push(worker_cleanup, session);
  /* start waiting for incoming connections */
  while (1)
  {
    /* time out connection to LDAP server if needed */
    myldap_session_check(session);
    /* set up the set of fds to wait on */
    FD_ZERO(&fds);
    FD_SET(nslcd_serversocket, &fds);
    /* set up our timeout value */
    tv.tv_sec = nslcd_cfg->idle_timelimit;
    tv.tv_usec = 0;
    /* wait for a new connection */
    j = select(nslcd_serversocket + 1, &fds, NULL, NULL,
               nslcd_cfg->idle_timelimit > 0 ? &tv : NULL);
    /* check result of select() */
    if (j < 0)
    {
      if (errno == EINTR)
        log_log(LOG_DEBUG, "select() failed (ignored): %s", strerror(errno));
      else
        log_log(LOG_ERR, "select() failed: %s", strerror(errno));
      continue;
    }
    /* see if our file descriptor is actually ready */
    if (!FD_ISSET(nslcd_serversocket, &fds))
      continue;
    /* wait for a new connection */
    alen = (socklen_t)sizeof(struct sockaddr_storage);
    csock = accept(nslcd_serversocket, (struct sockaddr *)&addr, &alen);
    if (csock < 0)
    {
      if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
        log_log(LOG_DEBUG, "accept() failed (ignored): %s", strerror(errno));
      else
        log_log(LOG_ERR, "accept() failed: %s", strerror(errno));
      continue;
    }
    /* make sure O_NONBLOCK is not inherited */
    if ((j = fcntl(csock, F_GETFL, 0)) < 0)
    {
      log_log(LOG_ERR, "fctnl(F_GETFL) failed: %s", strerror(errno));
      if (close(csock))
        log_log(LOG_WARNING, "problem closing socket: %s", strerror(errno));
      continue;
    }
    if (fcntl(csock, F_SETFL, j & ~O_NONBLOCK) < 0)
    {
      log_log(LOG_ERR, "fctnl(F_SETFL,~O_NONBLOCK) failed: %s", strerror(errno));
      if (close(csock))
        log_log(LOG_WARNING, "problem closing socket: %s", strerror(errno));
      continue;
    }
    /* indicate new connection to logging module (generates unique id) */
    log_newsession();
    /* handle the connection */
    handleconnection(csock, session);
    /* indicate end of session in log messages */
    log_clearsession();
  }
  pthread_cleanup_pop(1);
  return NULL;
}
Exemple #20
0
void thread_protect(void (*run)(void *), void *runarg, void (*finish)(void *), void *finisharg)
{
    pthread_cleanup_push(finish, finisharg);
    run(runarg);
    pthread_cleanup_pop(true);
}
Exemple #21
0
static int	
WebServletRun(struct http_servlet *servlet,
                         struct http_request *req, struct http_response *resp)
{
    FILE *f;
    const char *path;
    const char *query;
    int priv = 0;
    
    if (Enabled(&gWeb.options, WEB_AUTH)) {
	const char *username;
	const char *password;
	ConsoleUser		u;
	struct console_user	iu;

	/* Get username and password */
	if ((username = http_request_get_username(req)) == NULL)
    	    username = "";
	if ((password = http_request_get_password(req)) == NULL)
    	    password = "";

	strlcpy(iu.username, username, sizeof(iu.username));
	RWLOCK_RDLOCK(gUsersLock);
	u = ghash_get(gUsers, &iu);
	RWLOCK_UNLOCK(gUsersLock);

	if ((u == NULL) || strcmp(u->password, password)) {
		http_response_send_basic_auth(resp, "Access Restricted");
		return (1);
	}
	priv = u->priv;
    }

    if (!(f = http_response_get_output(resp, 1))) {
	return 0;
    }
    if (!(path = http_request_get_path(req)))
	return 0;
    if (!(query = http_request_get_query_string(req)))
	return 0;

    if (!strcmp(path,"/mpd.css")) {
	http_response_set_header(resp, 0, "Content-Type", "text/css");
	WebShowCSS(f);
    } else if (!strcmp(path,"/bincmd")) {
	http_response_set_header(resp, 0, "Content-Type", "text/plain");
	http_response_set_header(resp, 1, "Pragma", "no-cache");
	http_response_set_header(resp, 1, "Cache-Control", "no-cache, must-revalidate");
	
	pthread_cleanup_push(WebServletRunCleanup, NULL);
	GIANT_MUTEX_LOCK();
	WebRunBinCmd(f, query, priv);
	GIANT_MUTEX_UNLOCK();
	pthread_cleanup_pop(0);
    } else if (!strcmp(path,"/") || !strcmp(path,"/cmd")) {
	http_response_set_header(resp, 0, "Content-Type", "text/html");
	http_response_set_header(resp, 1, "Pragma", "no-cache");
	http_response_set_header(resp, 1, "Cache-Control", "no-cache, must-revalidate");
	
	pthread_cleanup_push(WebServletRunCleanup, NULL);
	GIANT_MUTEX_LOCK();
	fprintf(f, "<!DOCTYPE HTML "
	    "PUBLIC \"-//W3C//DTD HTML 4.01//EN\" "
	    "\"http://www.w3.org/TR/html4/strict.dtd\">\n");
	fprintf(f, "<HTML>\n");
	fprintf(f, "<HEAD><TITLE>Multi-link PPP Daemon for FreeBSD (mpd)</TITLE>\n");
	fprintf(f, "<LINK rel='stylesheet' href='/mpd.css' type='text/css'>\n");
	fprintf(f, "</HEAD>\n<BODY>\n");
	fprintf(f, "<H1>Multi-link PPP Daemon for FreeBSD</H1>\n");
    
	if (!strcmp(path,"/"))
	    WebShowSummary(f, priv);
	else if (!strcmp(path,"/cmd"))
	    WebRunCmd(f, query, priv);
	    
	GIANT_MUTEX_UNLOCK();
	pthread_cleanup_pop(0);
	
	fprintf(f, "</BODY>\n</HTML>\n");
    } else {
	http_response_send_error(resp, 404, NULL);
    }
    return 1;
}
Exemple #22
0
static void *
player_worker (kk_player_t *player)
{
  const int max_retries = 3;

  pthread_cleanup_push ((void (*)(void *)) player_worker_cleanup, player);

  for (;;) {
    int d = 0;

    for (;;) {
      int s = 0;
      int e = 0;

      kk_frame_t frame;

      /**
       * We lock our mutex and check if the input field is NULL. If it is,
       * we call pthread_cond_wait (with mutex still locked). Every call of
       * pthread_cond_wait releases the mutex and locks our thread on the
       * condition variable. Thus other threads are able to aquire the mutex.
       * These other threads hopefully assign something to input and wake us
       * with a pthread_cond_signal call. This call causes pthread_cond_wait
       * to return with mutex locked. Then we try to read a frame from input
       * and write it to the output device. Releasing the mutex before writing
       * our frame to the input device allows other threads to change input
       * in the meantime.
       */
      pthread_mutex_lock (&player->mutex);
      while ((player->input == NULL) || (player->pause)) {
        pthread_cond_wait (&player->cond, &player->mutex);
      }

      /**
       * Done decoding a frame. This should work on the first try,
       * but sometimes it doesn't. In this case the loop handles these
       * errors pretty well and the user won't notice them at all. Unless
       * something is very wrong and we give up.
       */
      pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);

      for (e = 0; e < max_retries; e++) {
        if ((s = kk_input_get_frame (player->input, &frame)) >= 0)
          break;
        kk_log (KK_LOG_WARNING,
            "Error while reading and decoding frame (%d). " \
            "Trying to recover.", s);
      }
      pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
      pthread_mutex_unlock (&player->mutex);

      /* No data read? Stop */
      if (s == 0)
        break;

      /**
       * Now if this happened we really failed reading and decoding another
       * frame.
       */
      if (e == max_retries) {
        kk_log (KK_LOG_WARNING,
            "Reading frame failed %d times. I'm giving up now.", max_retries);
        break;
      }

      /* Don't send this event too often */
      if ((++d & 0x7f) == 0)
        kk_player_event_progress (player->events, frame.prog);

      kk_device_write (player->device, &frame);
    }

    kk_player_next (player);
  }

  /* Basically unreachable, yes */
  pthread_cleanup_pop (0);
  return NULL;
}
int
pthread_rwlock_wrlock (pthread_rwlock_t * rwlock)
{
  int result;
  pthread_rwlock_t rwl;

  if (rwlock == NULL || *rwlock == NULL)
    {
      return EINVAL;
    }

  /*
   * We do a quick check to see if we need to do more work
   * to initialise a static rwlock. We check
   * again inside the guarded section of ptw32_rwlock_check_need_init()
   * to avoid race conditions.
   */
  if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
    {
      result = ptw32_rwlock_check_need_init (rwlock);

      if (result != 0 && result != EBUSY)
	{
	  return result;
	}
    }

  rwl = *rwlock;

  if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
    {
      return EINVAL;
    }

  if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
    {
      return result;
    }

  if ((result = pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
    {
      (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
      return result;
    }

  if (rwl->nExclusiveAccessCount == 0)
    {
      if (rwl->nCompletedSharedAccessCount > 0)
	{
	  rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
	  rwl->nCompletedSharedAccessCount = 0;
	}

      if (rwl->nSharedAccessCount > 0)
	{
	  rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;

	  /*
	   * This routine may be a cancellation point
	   * according to POSIX 1003.1j section 18.1.2.
	   */
#if defined(PTW32_CONFIG_MSVC7)
#pragma inline_depth(0)
#endif
	  pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl);

	  do
	    {
	      result = pthread_cond_wait (&(rwl->cndSharedAccessCompleted),
					  &(rwl->mtxSharedAccessCompleted));
	    }
	  while (result == 0 && rwl->nCompletedSharedAccessCount < 0);

	  pthread_cleanup_pop ((result != 0) ? 1 : 0);
#if defined(PTW32_CONFIG_MSVC7)
#pragma inline_depth()
#endif

	  if (result == 0)
	    {
	      rwl->nSharedAccessCount = 0;
	    }
	}
    }

  if (result == 0)
    {
      rwl->nExclusiveAccessCount++;
    }

  return result;
}
Exemple #24
0
// Run method for the thread
// It is meant to do the following:
// (1) Initialize status buffer
// (2) Set up network parameters and socket
// (3) Start main loop
//     (3a) Receive packet on socket
//     (3b) Error check packet (packet size, etc)
//     (3c) Call process_packet on received packet
// (4) Terminate thread cleanly
static void *run(hashpipe_thread_args_t * args) {

    fprintf(stdout, "N_INPUTS = %d\n", N_INPUTS);
    fprintf(stdout, "N_CHAN = %d\n", N_CHAN);
    fprintf(stdout, "N_CHAN_PER_X = %d\n", N_CHAN_PER_X);
    fprintf(stdout, "N_CHAN_PER_PACKET = %d\n", N_CHAN_PER_PACKET);
    fprintf(stdout, "N_TIME_PER_PACKET = %d\n", N_TIME_PER_PACKET);
    fprintf(stdout, "N_TIME_PER_BLOCK = %d\n", N_TIME_PER_BLOCK);
    fprintf(stdout, "N_BYTES_PER_BLOCK = %d\n", N_BYTES_PER_BLOCK);
    fprintf(stdout, "N_BYTES_PER_PACKET = %d\n", N_BYTES_PER_PACKET);
    fprintf(stdout, "N_PACKETS_PER_BLOCK = %d\n", N_PACKETS_PER_BLOCK);
    fprintf(stdout, "N_COR_MATRIX = %d\n", N_COR_MATRIX);

    // Local aliases to shorten access to args fields
    // Our output buffer happens to be a paper_input_databuf
    flag_input_databuf_t *db = (flag_input_databuf_t *)args->obuf;
    hashpipe_status_t st = args->st;
    const char * status_key = args->thread_desc->skey;

    st_p = &st;	// allow global (this source file) access to the status buffer

    /* Read network params */
    fprintf(stdout, "Setting up network parameters\n");
    struct hashpipe_udp_params up = {
	.bindhost = "0.0.0.0",
	.bindport = 8511,
	.packet_size = 8008
    };

    hashpipe_status_lock_safe(&st);
    	// Get info from status buffer if present (no change if not present)
    	hgets(st.buf, "BINDHOST", 80, up.bindhost);
    	hgeti4(st.buf, "BINDPORT", &up.bindport);
    
    	// Store bind host/port info etc in status buffer
    	hputs(st.buf, "BINDHOST", up.bindhost);
    	hputi4(st.buf, "BINDPORT", up.bindport);
    	hputu4(st.buf, "MISSEDFE", 0);
    	hputu4(st.buf, "MISSEDPK", 0);
    	hputs(st.buf, status_key, "running");
    hashpipe_status_unlock_safe(&st);

    struct hashpipe_udp_packet p;

    /* Give all the threads a chance to start before opening network socket */
    int netready = 0;
    int corready = 0;
    int checkready = 0;
    while (!netready) {
        sleep(1);
        // Check the correlator to see if it's ready yet
        hashpipe_status_lock_safe(&st);
        hgeti4(st.buf, "CORREADY",  &corready);
        hgeti4(st.buf, "SAVEREADY", &checkready);
        hashpipe_status_unlock_safe(&st);
        if (!corready) {
            continue;
        }
        //if (!checkready) {
        //    continue;
        //}

        // Check the other threads to see if they're ready yet
        // TBD

        // If we get here, then all threads are initialized
        netready = 1;
    }
    sleep(3);

    /* Set up UDP socket */
    fprintf(stderr, "NET: BINDHOST = %s\n", up.bindhost);
    fprintf(stderr, "NET: BINDPORT = %d\n", up.bindport);
    int rv = hashpipe_udp_init(&up);
    
    if (rv!=HASHPIPE_OK) {
        hashpipe_error("paper_net_thread",
                "Error opening UDP socket.");
        pthread_exit(NULL);
    }
    pthread_cleanup_push((void *)hashpipe_udp_close, &up);


    // Initialize first few blocks in the buffer
    int i;
    for (i = 0; i < 2; i++) {
        // Wait until block semaphore is free
        if (flag_input_databuf_wait_free(db, i) != HASHPIPE_OK) {
            if (errno == EINTR) { // Interrupt occurred
                hashpipe_error(__FUNCTION__, "waiting for free block interrupted\n");
                pthread_exit(NULL);
            } else {
                hashpipe_error(__FUNCTION__, "error waiting for free block\n");
                pthread_exit(NULL);
            }
        }
        initialize_block(db, i*Nm);
    }


    // Set correlator to "start" state
    hashpipe_status_lock_safe(&st);
    hputs(st.buf, "INTSTAT", "start");
    hashpipe_status_unlock_safe(&st);

    /* Main loop */
    uint64_t packet_count = 0;

    fprintf(stdout, "Net: Starting Thread!\n");
    
    while (run_threads()) {
        // Get packet
	do {
	    p.packet_size = recv(up.sock, p.data, HASHPIPE_MAX_PACKET_SIZE, 0);
	} while (p.packet_size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && run_threads());
	if(!run_threads()) break;
        
        if (up.packet_size != p.packet_size && up.packet_size != p.packet_size-8) {
	    // If an error was returned instead of a valid packet size
            if (p.packet_size == -1) {
                fprintf(stderr, "uh oh!\n");
		// Log error and exit
                hashpipe_error("paper_net_thread",
                        "hashpipe_udp_recv returned error");
                perror("hashpipe_udp_recv");
                pthread_exit(NULL);
            } else {
		// Log warning and ignore wrongly sized packet
                hashpipe_warn("paper_net_thread", "Incorrect pkt size (%d)", p.packet_size);
                continue;
            }
	}
	packet_count++;
        process_packet(db, &p);

        /* Will exit if thread has been cancelled */
        pthread_testcancel();
    }

    pthread_cleanup_pop(1); /* Closes push(hashpipe_udp_close) */

    hashpipe_status_lock_busywait_safe(&st);
    hputs(st.buf, status_key, "terminated");
    hashpipe_status_unlock_safe(&st);
    return NULL;
}


static hashpipe_thread_desc_t net_thread = {
    name: "flag_net_thread",
    skey: "NETSTAT",
    init: NULL,
    run:  run,
    ibuf_desc: {NULL},
void *wxThreadInternal::PthreadStart(wxThread *thread)
{
    wxThreadInternal *pthread = thread->m_internal;

    wxLogTrace(TRACE_THREADS, _T("Thread %ld started."), THR_ID(pthread));

    // associate the thread pointer with the newly created thread so that
    // wxThread::This() will work
    int rc = pthread_setspecific(gs_keySelf, thread);
    if ( rc != 0 )
    {
        wxLogSysError(rc, _("Cannot start thread: error writing TLS"));

        return (void *)-1;
    }

    // have to declare this before pthread_cleanup_push() which defines a
    // block!
    bool dontRunAtAll;

#ifdef wxHAVE_PTHREAD_CLEANUP
    // install the cleanup handler which will be called if the thread is
    // cancelled
    pthread_cleanup_push(wxPthreadCleanup, thread);
#endif // wxHAVE_PTHREAD_CLEANUP

    // wait for the semaphore to be posted from Run()
    pthread->m_semRun.Wait();

    // test whether we should run the run at all - may be it was deleted
    // before it started to Run()?
    {
        wxCriticalSectionLocker lock(thread->m_critsect);

        dontRunAtAll = pthread->GetState() == STATE_NEW &&
                       pthread->WasCancelled();
    }

    if ( !dontRunAtAll )
    {
        // call the main entry
        wxLogTrace(TRACE_THREADS,
                   _T("Thread %ld about to enter its Entry()."),
                   THR_ID(pthread));

        pthread->m_exitcode = thread->Entry();

        wxLogTrace(TRACE_THREADS,
                   _T("Thread %ld Entry() returned %lu."),
                   THR_ID(pthread), (unsigned long)pthread->m_exitcode);

        {
            wxCriticalSectionLocker lock(thread->m_critsect);

            // change the state of the thread to "exited" so that
            // wxPthreadCleanup handler won't do anything from now (if it's
            // called before we do pthread_cleanup_pop below)
            pthread->SetState(STATE_EXITED);
        }
    }

    // NB: at least under Linux, pthread_cleanup_push/pop are macros and pop
    //     contains the matching '}' for the '{' in push, so they must be used
    //     in the same block!
#ifdef wxHAVE_PTHREAD_CLEANUP
    // remove the cleanup handler without executing it
    pthread_cleanup_pop(FALSE);
#endif // wxHAVE_PTHREAD_CLEANUP

    if ( dontRunAtAll )
    {
        // FIXME: deleting a possibly joinable thread here???
        delete thread;

        return EXITCODE_CANCELLED;
    }
    else
    {
        // terminate the thread
        thread->Exit(pthread->m_exitcode);

        wxFAIL_MSG(wxT("wxThread::Exit() can't return."));

        return NULL;
    }
}
void vegas_null_thread(void *_args) {

    int rv;
    /* Set cpu affinity */
    cpu_set_t cpuset, cpuset_orig;
    sched_getaffinity(0, sizeof(cpu_set_t), &cpuset_orig);
    CPU_ZERO(&cpuset);
    CPU_SET(6, &cpuset);
    rv = sched_setaffinity(0, sizeof(cpu_set_t), &cpuset);
    if (rv<0) { 
        vegas_error("vegas_null_thread", "Error setting cpu affinity.");
        perror("sched_setaffinity");
    }

    /* Set priority */
    rv = setpriority(PRIO_PROCESS, 0, 0);
    if (rv<0) {
        vegas_error("vegas_null_thread", "Error setting priority level.");
        perror("set_priority");
    }

    /* Get args */
    struct vegas_thread_args *args = (struct vegas_thread_args *)_args;

    /* get instance_id */
    int instance_id = args->instance_id;

    /* Attach to status shared mem area */
    struct vegas_status st;
    rv = vegas_status_attach(instance_id, &st);
    if (rv!=VEGAS_OK) {
        vegas_error("vegas_null_thread", 
                "Error attaching to status shared memory.");
        pthread_exit(NULL);
    }
    pthread_cleanup_push((void *)vegas_status_detach, &st);
    pthread_cleanup_push((void *)set_exit_status, &st);

    /* Init status */
    vegas_status_lock_safe(&st);
    hputs(st.buf, STATUS_KEY, "init");
    vegas_status_unlock_safe(&st);

    /* Attach to databuf shared mem */
    struct vegas_databuf *db;
    db = vegas_databuf_attach(instance_id, args->input_buffer);
    if (db==NULL) {
        vegas_error("vegas_null_thread",
                "Error attaching to databuf shared memory.");
        pthread_exit(NULL);
    }
    pthread_cleanup_push((void *)vegas_databuf_detach, db);

    /* Loop */
    char *ptr;
    struct vegas_params gp;
#if FITS_TYPE == PSRFITS
    struct psrfits pf;
    pf.sub.dat_freqs = NULL;
    pf.sub.dat_weights = NULL;
    pf.sub.dat_offsets = NULL;
    pf.sub.dat_scales = NULL;
    pthread_cleanup_push((void *)vegas_free_psrfits, &pf);
#else
    struct sdfits pf;
    pthread_cleanup_push((void *)vegas_free_sdfits, &pf);
#endif
    int curblock=0;
    signal(SIGINT,cc);
    while (run) {

        /* Note waiting status */
        vegas_status_lock_safe(&st);
        hputs(st.buf, STATUS_KEY, "waiting");
        vegas_status_unlock_safe(&st);

        /* Wait for buf to have data */
        rv = vegas_databuf_wait_filled(db, curblock);
        if (rv!=0) {
            //sleep(1);
            continue;
        }

        /* Note waiting status, current block */
        vegas_status_lock_safe(&st);
        hputs(st.buf, STATUS_KEY, "discarding");
        hputi4(st.buf, "DSKBLKIN", curblock);
        vegas_status_unlock_safe(&st);

        /* Get params */
        ptr = vegas_databuf_header(db, curblock);
        vegas_read_obs_params(ptr, &gp, &pf);

        /* Output if data was lost */
#if FITS_TYPE == PSRFITS
        if (gp.n_dropped!=0 && 
                (gp.packetindex==0 || strcmp(pf.hdr.obs_mode,"SEARCH"))) {
            printf("Block beginning with pktidx=%lld dropped %d packets\n",
                    gp.packetindex, gp.n_dropped);
            fflush(stdout);
        }
#else
        if (gp.num_pkts_dropped!=0 && gp.num_pkts_rcvd!=0) {
            printf("Block received %d packets and dropped %d packets\n",
                    gp.num_pkts_rcvd, gp.num_pkts_dropped);
            fflush(stdout);
        }
#endif

        /* Mark as free */
        vegas_databuf_set_free(db, curblock);

        /* Go to next block */
        curblock = (curblock + 1) % db->n_block;

        /* Check for cancel */
        pthread_testcancel();

    }

    pthread_exit(NULL);

    pthread_cleanup_pop(0); /* Closes set_exit_status */
    pthread_cleanup_pop(0); /* Closes vegas_free_psrfits */
    pthread_cleanup_pop(0); /* Closes vegas_status_detach */
    pthread_cleanup_pop(0); /* Closes vegas_databuf_detach */

}
    /******************************************************************************
    Description.: this thread worker grabs a frame and copies it to the global buffer
    Input Value.: unused
    Return Value: unused, always NULL
     ******************************************************************************/
    void *cam_thread(void *arg) {
        
        g_settings.init();
        setCameraExposure();
        
        CVideoFrame* pFrame = NULL;

#ifndef TEST_USE_JPEGS_NOT_CAMERA 
        int width = VIEW_PIXEL_X_WIDTH;
        int height = VIEW_PIXEL_Y_HEIGHT;
        IplImage * img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); // obraz OpenCV
#endif

        frameGrinder.init();

#ifdef TEST_USE_JPEGS_NOT_CAMERA 
        std::string sBasePath = "/home/";
        sBasePath += HOME_NAME;
        std::string sPath = sBasePath;
        sPath += "/0243-20150125-22-21-46.jpg";
        //sPath += "/0007-20150125-22-36-25.jpg";  
        cv::Mat frame1 = cv::imread(sPath.c_str(), CV_LOAD_IMAGE_COLOR);
        if (frame1.empty()) {
            dbgMsg_s("Failed to read image data from a file1\n");
        }

        sPath = sBasePath;
        sPath += "/0243-20150125-22-21-46.jpg";
        //sPath += "/0007-20150125-22-36-25.jpg";  
        cv::Mat frame2 = cv::imread(sPath.c_str(), CV_LOAD_IMAGE_COLOR);
        if (frame2.empty()) {
            dbgMsg_s("Failed to read image data from a file2\n");
        }
        bool toggle = false;
#endif

        context *pcontext = (context*) arg;
        pglobal = pcontext->pglobal;

        /* set cleanup handler to cleanup allocated ressources */
        pthread_cleanup_push(cam_cleanup, pcontext);

        while (!pglobal->stop) {
            while (pcontext->videoIn->streamingState == STREAMING_PAUSED) {
                usleep(1); // maybe not the best way so FIXME
            }

#ifdef TEST_USE_JPEGS_NOT_CAMERA 
            if (frameGrinder.safeGetFreeFrame(&pFrame)) {
                if (toggle) {
                    pFrame->m_frame = frame1;
                } else {
                    pFrame->m_frame = frame2;
                }
                toggle = (!toggle);
                if (!pFrame->m_frame.empty()) {
                    frameGrinder.safeAddTail(pFrame, CVideoFrame::FRAME_QUEUE_WAIT_FOR_BLOB_DETECT);
                } else {
                    dbgMsg_s("Frame is empty\n");
                    frameGrinder.safeAddTail(pFrame, CVideoFrame::FRAME_QUEUE_FREE);
                }
                frameGrinder.m_testMonitor.m_nTasksDone[CTestMonitor::TASK_DONE_CAMERA]++;
            }

#else
            /* grab a frame */
            if (uvcGrab(pcontext->videoIn) < 0) {
                IPRINT("Error grabbing frames\n");
                exit(EXIT_FAILURE);
            }

            DBG("received frame of size: %d from plugin: %d\n", pcontext->videoIn->buf.bytesused, pcontext->id);

            /*
             * Workaround for broken, corrupted frames:
             * Under low light conditions corrupted frames may get captured.
             * The good thing is such frames are quite small compared to the regular pictures.
             * For example a VGA (640x480) webcam picture is normally >= 8kByte large,
             * corrupted frames are smaller.
             */
            if (pcontext->videoIn->buf.bytesused < minimum_size) {
                DBG("dropping too small frame, assuming it as broken\n");
                continue;
            }

            if (g_settings.isDynamicSettingsEnabled())
            {
                g_settings.getValueFromFile(CSetting::SETTING_EXPOSURE);
            }
            if(g_settings.isValueChanged(CSetting::SETTING_EXPOSURE))
            {
                setCameraExposure();
            }

#ifdef NO_CV_JUST_STREAM_THE_CAMERA

            /* copy JPG picture to global buffer */
            pthread_mutex_lock(&pglobal->in[pcontext->id].db);

            /*
             * If capturing in YUV mode convert to JPEG now.
             * This compression requires many CPU cycles, so try to avoid YUV format.
             * Getting JPEGs straight from the webcam, is one of the major advantages of
             * Linux-UVC compatible devices.
             */
            if (pcontext->videoIn->formatIn == V4L2_PIX_FMT_YUYV) {
                DBG("compressing frame from input: %d\n", (int) pcontext->id);
                pglobal->in[pcontext->id].size = compress_yuyv_to_jpeg(pcontext->videoIn, pglobal->in[pcontext->id].buf, pcontext->videoIn->framesizeIn, gquality);
            } else {
                DBG("copying frame from input: %d\n", (int) pcontext->id);
                pglobal->in[pcontext->id].size = memcpy_picture(pglobal->in[pcontext->id].buf, pcontext->videoIn->tmpbuffer, pcontext->videoIn->buf.bytesused);
            }

            /* copy this frame's timestamp to user space */
            pglobal->in[pcontext->id].timestamp = pcontext->videoIn->buf.timestamp;

            /* signal fresh_frame */
            pthread_cond_broadcast(&pglobal->in[pcontext->id].db_update);
            pthread_mutex_unlock(&pglobal->in[pcontext->id].db);


#else // #ifndef NO_CV_JUST_STREAM_THE_CAMERA

            if (frameGrinder.safeGetFreeFrame(&pFrame)) {
                std::vector<uchar> vectordata(pcontext->videoIn->tmpbuffer, pcontext->videoIn->tmpbuffer + (height * width));
                cv::Mat data_mat(vectordata, false);
                cv::Mat image(cv::imdecode(data_mat, 1)); //put 0 if you want greyscale
                pFrame->m_frame = image;
                if (!pFrame->m_frame.empty()) {
                    frameGrinder.safeAddTail(pFrame, CVideoFrame::FRAME_QUEUE_WAIT_FOR_BLOB_DETECT);
                } else {
                    dbgMsg_s("Frame is empty\n");
                    frameGrinder.safeAddTail(pFrame, CVideoFrame::FRAME_QUEUE_FREE);
                }
                frameGrinder.m_testMonitor.m_nTasksDone[CTestMonitor::TASK_DONE_CAMERA]++;
            }

#endif  // #ifndef NO_CV_JUST_STREAM_THE_CAMERA

#endif   // TEST_USE_JPEGS_NOT_CAMERA
        }

        DBG("leaving input thread, calling cleanup function now\n");
        pthread_cleanup_pop(1);

        return NULL;
    }
Exemple #28
0
/* the single writer thread */
void *worker_thread( void *arg ) {
  char buffer[1<<16];
  int file;
  size_t filesize = 0;
  struct stat stats;

  /* set cleanup handler to cleanup allocated ressources */
  pthread_cleanup_push(worker_cleanup, NULL);

  while( !pglobal->stop ) {

    /* wait for new frame, read will block until something happens */
    rc = read(fd, ev, size);
    if ( rc == -1 ) {
      perror("reading inotify events failed");
      break;
    }

    /* sanity check */
    if ( wd != ev->wd ) {
      fprintf(stderr, "This event is not for the watched directory (%d != %d)\n", wd, ev->wd);
      continue;
    }

    if ( ev->mask & (IN_IGNORED|IN_Q_OVERFLOW|IN_UNMOUNT) ) {
      fprintf(stderr, "event mask suggests to stop\n");
      break;
    }

    /* prepare filename */
    snprintf(buffer, sizeof(buffer), "%s%s", folder, ev->name);

    /* check if the filename matches specified parameter (if given) */
    if ( (filename != NULL) && (strcmp(filename, ev->name) != 0) ) {
      DBG("ignoring this change (specified filename does not match)\n");
      continue;
    }
    DBG("new file detected: %s\n", buffer);

    /* open file for reading */
    rc = file = open(buffer, O_RDONLY);
    if ( rc == -1 ) {
      perror("could not open file for reading");
      break;
    }

    /* approximate size of file */
    rc = fstat(file, &stats);
    if ( rc == -1 ) {
      perror("could not read statistics of file");
      close(file);
      break;
    }

    filesize = stats.st_size;

    /* copy frame from file to global buffer */
    pthread_mutex_lock( &pglobal->db );

    /* allocate memory for frame */
    if ( pglobal->buf != NULL ) free(pglobal->buf);
    pglobal->buf = malloc(filesize + (1<<16));
    if (pglobal->buf == NULL) {
      fprintf(stderr, "could not allocate memory\n");
      break;
    }

    if ( (pglobal->size = read(file, pglobal->buf, filesize)) == -1) {
      perror("could not read from file");
      free(pglobal->buf); pglobal->buf = NULL; pglobal->size = 0;
      pthread_mutex_unlock( &pglobal->db );
      close(file);
      break;
    }

    DBG("new frame copied (size: %d)\n", pglobal->size);

    /* signal fresh_frame */
    pthread_cond_broadcast(&pglobal->db_update);
    pthread_mutex_unlock( &pglobal->db );

    close(file);

    /* delete file if necessary */
    if (rm) {
      rc = unlink(buffer);
      if ( rc == -1 ) {
        perror("could not remove/delete file");
      }
    }

    if (delay != 0) usleep(1000*delay);
  }

  DBG("leaving input thread, calling cleanup function now\n");
  /* call cleanup handler, signal with the parameter */
  pthread_cleanup_pop(1);

  return NULL;
}
Exemple #29
0
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
{
	int bytes_read = -1;

#if 0
	int transferred;
	int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000);
	LOG("transferred: %d\n", transferred);
	return transferred;
#endif

	pthread_mutex_lock(&dev->mutex);
	pthread_cleanup_push(&cleanup_mutex, dev);

	/* There's an input report queued up. Return it. */
	if (dev->input_reports) {
		/* Return the first one */
		bytes_read = return_data(dev, data, length);
		goto ret;
	}

	if (dev->shutdown_thread) {
		/* This means the device has been disconnected.
		   An error code of -1 should be returned. */
		bytes_read = -1;
		goto ret;
	}

	if (milliseconds == -1) {
		/* Blocking */
		while (!dev->input_reports && !dev->shutdown_thread) {
			pthread_cond_wait(&dev->condition, &dev->mutex);
		}
		if (dev->input_reports) {
			bytes_read = return_data(dev, data, length);
		}
	}
	else if (milliseconds > 0) {
		/* Non-blocking, but called with timeout. */
		int res;
		struct timespec ts;
		clock_gettime(CLOCK_REALTIME, &ts);
		ts.tv_sec += milliseconds / 1000;
		ts.tv_nsec += (milliseconds % 1000) * 1000000;
		if (ts.tv_nsec >= 1000000000L) {
			ts.tv_sec++;
			ts.tv_nsec -= 1000000000L;
		}

		while (!dev->input_reports && !dev->shutdown_thread) {
			res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts);
			if (res == 0) {
				if (dev->input_reports) {
					bytes_read = return_data(dev, data, length);
					break;
				}

				/* If we're here, there was a spurious wake up
				   or the read thread was shutdown. Run the
				   loop again (ie: don't break). */
			}
			else if (res == ETIMEDOUT) {
				/* Timed out. */
				bytes_read = 0;
				break;
			}
			else {
				/* Error. */
				bytes_read = -1;
				break;
			}
		}
	}
	else {
		/* Purely non-blocking */
		bytes_read = 0;
	}

ret:
	pthread_mutex_unlock(&dev->mutex);
	pthread_cleanup_pop(0);

	return bytes_read;
}
Exemple #30
0
static void
__vsyslogex_chk(int pri, int flag, pid_t cpid, pid_t ctid, const char *fmt, va_list ap) {
    struct tm now_tm;
    time_t now;
    int fd;
    FILE *f;
    char *buf = 0;
    size_t bufsize = 0;
    size_t prioff, msgoff;
#ifndef NO_SIGPIPE
    struct sigaction action, oldaction;
    int sigpipe;
#endif
    int saved_errno = errno;
    char failbuf[3 * sizeof (pid_t) + sizeof "out of memory []"];
    const int LogMask = setlogmask(0);

#ifdef _DEBUGFLAGS_H_
    {
        static unsigned int registered = 0;
        if (unlikely(0 == registered)) {
            registered = 1; /* dirty work around to avoid deadlock: syslogex->register->syslogex */
            registered = (registerLibraryDebugFlags(&debugFlags) == EXIT_SUCCESS);
        }
    }
#endif /*_DEBUGFLAGS_H_*/

#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
    /* Check for invalid bits. */
    if (unlikely(pri & ~(LOG_PRIMASK | LOG_FACMASK))) {
        /*syslog(INTERNALLOG,
               "syslog: unknown facility/priority: %x", pri);*/
        WARNING_MSG("unknown facility/priority: %x", pri);
        pri &= LOG_PRIMASK | LOG_FACMASK;
    }

    /* Check priority against setlogmask values. */
    if (unlikely((LOG_MASK(LOG_PRI(pri)) & LogMask) == 0))
        return;

    /* Set default facility if none specified. */
    if (unlikely((pri & LOG_FACMASK) == 0))
        pri |= LogFacility;

    /* Build the message in a memory-buffer stream.  */
    f = open_memstream(&buf, &bufsize);
    if (unlikely(f == NULL)) {
        /* We cannot get a stream.  There is not much we can do but
           emitting an error messages with the Process ID.  */
        char numbuf[3 * sizeof (pid_t)];
        char *nump;
        char *endp = __stpcpy(failbuf, "out of memory [");
        pid_t pid = getpid();

        nump = numbuf + sizeof (numbuf);
        /* The PID can never be zero.  */
        do {
            *--nump = '0' + pid % 10;
        } while ((pid /= 10) != 0);

        endp = mempcpy((void*) endp, (const void*) nump, (size_t) ((numbuf + sizeof (numbuf)) - nump));
        *endp++ = ']';
        *endp = '\0';
        buf = failbuf;
        bufsize = endp - failbuf;
        msgoff = 0;
    } else {
        __fsetlocking(f, FSETLOCKING_BYCALLER);
        prioff = fprintf(f, "<%d>", pri);
        (void) time(&now);
        f->_IO_write_ptr += strftime(f->_IO_write_ptr,
                f->_IO_write_end - f->_IO_write_ptr,
                "%h %e %T ",
                localtime_r(&now, &now_tm));
        /*f->_IO_write_ptr += strftime_l (f->_IO_write_ptr,
                                          f->_IO_write_end - f->_IO_write_ptr,
                                          "%h %e %T ",
                                          localtime_r (&now, &now_tm));*/
        msgoff = ftell(f);
        if (LogTag == NULL)
            LogTag = __progname;
        if (LogTag != NULL)
            fputs_unlocked(LogTag, f);
        if (LogStat & LOG_PID) {
            const pid_t pid = ((0 == cpid) ? getpid() : cpid);
            if (LogStat & LOG_TID) {
                const pid_t tid = ((0 == ctid) ? gettid() : ctid);
                fprintf(f, "[%d:%d]", (int) pid, (int) tid);
            } else {
                fprintf(f, "[%d]", (int) pid);
            }
        }

        if (LogStat & LOG_RDTSC) {
            const unsigned long long int t = rdtsc();
            fprintf(f, "(%llu)", t);
        } /* (LogStat & LOG_RDTSC) */

        if (LogStat & LOG_CLOCK) {
            #if HAVE_CLOCK_GETTIME
                struct timespec timeStamp;
                if (clock_gettime(CLOCK_MONOTONIC,&timeStamp) == 0) {
                    fprintf(f,"(%lu.%.9d)",timeStamp.tv_sec,timeStamp.tv_nsec);
                } else {
                    const int error = errno;
                    ERROR_MSG("clock_gettime CLOCK_MONOTONIC error %d (%m)",error);
            }
            #else
                static unsigned int alreadyPrinted = 0;
                if (unlikely(0 == alreadyPrinted)) {
                    ERROR_MSG("clock_gettime  not available on this system");
                    alreadyPrinted = 1;
                }
            #endif
        }  /* (LogStat & LOG_CLOCK) */

        if (LogStat & LOG_LEVEL) {
            switch (LOG_PRI(pri)) {
                case LOG_EMERG:
                    fprintf(f, "[EMERG]");
                    break;
                case LOG_ALERT:
                    fprintf(f, "[ALERT]");
                    break;
                case LOG_CRIT:
                    fprintf(f, "[CRIT]");
                    break;
                case LOG_ERR:
                    fprintf(f, "[ERROR]");
                    break;
                case LOG_WARNING:
                    fprintf(f, "[WARNING]");
                    break;
                case LOG_NOTICE:
                    fprintf(f, "[NOTICE]");
                    break;
                case LOG_INFO:
                    fprintf(f, "[INFO]");
                    break;
                case LOG_DEBUG:
                    fprintf(f, "[DEBUG]");
                    break;
            } /* switch(LOG_PRI(pri))*/
        } /* (LogStat & LOG_LEVEL) */

        if (LogTag != NULL) {
            putc_unlocked(':', f);
            putc_unlocked(' ', f);
        }

        /* Restore errno for %m format.  */
        __set_errno(saved_errno);

        /* We have the header.  Print the user's format into the
         buffer.  */
        if (flag == -1) {
            vfprintf(f, fmt, ap);
        } else {
            __vfprintf_chk(f, flag, fmt, ap);
        }

        /* Close the memory stream; this will finalize the data
           into a malloc'd buffer in BUF.  */
        fclose(f);
    }

    /* Output to stderr if requested. */
    if (LogStat & LOG_PERROR) {
        struct iovec iov[2];
        register struct iovec *v = iov;

        v->iov_base = buf + msgoff;
        v->iov_len = bufsize - msgoff;
        /* Append a newline if necessary.  */
        if (buf[bufsize - 1] != '\n') {
            ++v;
            v->iov_base = (char *) "\n";
            v->iov_len = 1;
        }

        pthread_cleanup_push(free, buf == failbuf ? NULL : buf);

        /* writev is a cancellation point.  */
        (void) writev(STDERR_FILENO, iov, v - iov + 1);

        pthread_cleanup_pop(0);
    }

    /* Prepare for multiple users.  We have to take care: open and
  write are cancellation points.  */
    struct cleanup_arg clarg;
    clarg.buf = buf;
    clarg.oldaction = NULL;
    pthread_cleanup_push(cancel_handler, &clarg);
    pthread_mutex_lock(&syslogex_lock);

#ifndef NO_SIGPIPE
    /* Prepare for a broken connection.  */
    memset(&action, 0, sizeof (action));
    action.sa_handler = sigpipe_handler;
    sigemptyset(&action.sa_mask);
    sigpipe = __sigaction(SIGPIPE, &action, &oldaction);
    if (sigpipe == 0)
        clarg.oldaction = &oldaction;
#endif

    /* Get connected, output the message to the local logger. */
    if (!connected) {
        openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
    }

    /* If we have a SOCK_STREAM connection, also send ASCII NUL as
  a record terminator.  */
    if (LogType == SOCK_STREAM) {
        ++bufsize;
    }

    if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0) {
        if (connected) {
            /* Try to reopen the syslog connection.  Maybe it went
          down.  */
            closelog_internal();
            openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
        }

        if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0) {
            closelog_internal(); /* attempt re-open next time */
            /*
             * Output the message to the console; don't worry
             * about blocking, if console blocks everything will.
             * Make sure the error reported is the one from the
             * syslogd failure.
             */
            if (LogStat & LOG_CONS &&
                    (fd = __open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY, 0)) >= 0) {
                dprintf(fd, "%s\r\n", buf + msgoff);
                (void) __close(fd);
            }
        }
    }

#ifndef NO_SIGPIPE
    if (sigpipe == 0)
        __sigaction(SIGPIPE, &oldaction, (struct sigaction *) NULL);
#endif

    /* End of critical section.  */
    pthread_cleanup_pop(0);
    pthread_mutex_unlock(&syslogex_lock);

    if (buf != failbuf) {
        free(buf);
    }
}