コード例 #1
1
ファイル: alarma_thread.c プロジェクト: viccuad/c-examples
/*
 * Rutina inicial del thread.
 */
void *alarma_thread (void *arg)
{
	alarma_t *alarma;
	struct timespec cond_tiempo;
	time_t ahora;
	int estado, expirado;


	/*
	 * Bloquea (lock) el mutex
	 * al principio -- se desbloqueara (unlocked) durante las
	 * esperas de condicion, de modo que el thread principal
	 * podra insertar nuevas alarmas.
	 */
	if ((estado = pthread_mutex_lock(&alarma_mutex)) != 0)
		err_abort(estado, "Lock hilo gestor\n");

	/*
	 * Itera continuamente procesando solicitudes. El thread
	 * desaparecera cuando el proceso termine.
	 */
	while (1) {
		if (fin_solicitado == 1 && alarma_lista == NULL) {
			pthread_exit(NULL);
		}

		/*
		 * Si la lista de alarmas esta vacia, espera a que se inserte
		 * una nueva. Al poner alarma_actual a 0 se informa a la rutina
		 * alarma_inserta() que alarma_thread no esta ocupado.
		 */
		while (alarma_lista == NULL && fin_solicitado != 1) { // no hay alarmas y no se haya solicitado salir
			alarma_actual = 0;
			if ((estado = pthread_cond_wait(&alarma_cond, &alarma_mutex)) != 0) // asi que permite que thread ppal se ejecute
				err_abort(estado, "Pthread_cond_wait hilo gestor\n");
		}

		/*
		 * Toma la primera alarma;
		 * Si hay que procesarla prepara una espera condicional con
		 * temporizacion de la que saldra
		 *   a) por tiempo expirado => informa de alarma cumplida
		 *   b) por señal de nueva alarma mas corta => reinsertar en la lista
		 */
		if (alarma_lista != NULL) {
			alarma = alarma_lista; // me cojo la primera
			alarma_lista = alarma_lista->enlace; // retiro la primera de la lista
			alarma_actual = alarma->tiempo;
			cond_tiempo.tv_sec = alarma_actual;
			cond_tiempo.tv_nsec = 0;
			ahora = time(NULL);
			if (alarma_actual - ahora <= 0) { // expirada (no hay que procesarla)
				cond_tiempo.tv_sec = 0;
				expirado = 1;
			}
			else { // hay que procesarla
				expirado = 0;
				estado = -1;
				while (estado != ETIMEDOUT && estado != 0) // vencida o alarma mas temprana (insertada por el principio)
					estado = pthread_cond_timedwait(&alarma_cond, &alarma_mutex, &cond_tiempo); // asi permite que thread ppal se ejecute
				switch (estado) {
					case 0: // se ha insertado una alarma mas corta
						alarma_inserta(alarma); // se reinserta
						break;
					case ETIMEDOUT: // se ha completado la espera
						expirado = 1;
						break;
					default:
						err_abort(estado, "Pthread_cond_timed_wait hilo gestor\n");
						break;
				}
			}

			if (expirado == 1) {
				printf("(%d) %s\n", alarma->segundos, alarma->mensaje);
				free (alarma);
			}
		}

		/* NOTA:
		 * Incluir como salida de depuracion los valores de la alarma
		 * que va a ser atendida
		 */
		#ifdef DEBUG
			fprintf(stderr, "%d(%d)[\"%s\"] ", (int)alarma->tiempo,
				(int)(alarma->tiempo - time(NULL)), alarma->mensaje);
			fprintf (stderr, "\n");
		#endif

	}
}
コード例 #2
0
static void *worker_function( void *ptr ) 
{
	Worker *worker = (Worker *)ptr;

		/* Our new thread should grab the big mutex before starting.
		 * We will then
		 * release it and let other threads run when we would otherwise
		 * block.
		 */
	amazon_gahp_grab_big_mutex();

	if( !worker ) {
		dprintf (D_ALWAYS, "Ooops!! No input Data in worker thread\n");
		amazon_gahp_release_big_mutex();
		return NULL;
	}

	// Pop Request 
	Request *new_request = NULL;
	struct timespec ts;
	struct timeval tp;

	while(1) {

//		pthread_mutex_lock(&worker->m_mutex);

		worker->m_is_doing = false;
		worker->m_is_waiting = false;

		if( worker->m_can_use == false ) {
			// Need to die
//			pthread_mutex_unlock(&worker->m_mutex);
			worker_exit(worker, true);
		}

		while( (new_request = popRequest(worker)) == NULL ) {

			worker->m_is_waiting = true;

			// Get Current Time
			gettimeofday(&tp, NULL);

			/* Convert from timeval to timespec */
			ts.tv_sec = tp.tv_sec;
			ts.tv_nsec = tp.tv_usec * 1000;
			ts.tv_sec += WORKER_MANAGER_TIMER_INTERVAL;

			if( ioprocess ) {
				if( ioprocess->numOfPendingRequest() > 0 ) {
					continue;
				}
			}

			//dprintf(D_FULLDEBUG, "Thread(%d) is calling cond_wait\n", 
			//		worker->m_id);

			// The pthread_cond_timedwait will block until signalled
			// with more work from our main thread; so we MUST release
			// the big fat mutex here or we will deadlock.	
//			amazon_gahp_release_big_mutex();
			int retval = pthread_cond_timedwait(&worker->m_cond, 
					&global_big_mutex, &ts);
//			amazon_gahp_grab_big_mutex();

			if( worker->m_can_use == false ) {
				// Need to die
				worker->m_is_waiting = false;	

//				pthread_mutex_unlock(&worker->m_mutex);
				worker_exit(worker, true);
			}else {
				// If timeout happends, need to check m_must_be_alive
				if( retval == ETIMEDOUT ) {
					//dprintf(D_FULLDEBUG, "Thread(%d) Wait timed out !\n", 
					//		worker->m_id);

					if( ioprocess ) {
						if( ioprocess->numOfPendingRequest() > 0 ) {
							continue;
						}
					}

					if( !worker->m_must_be_alive ) {
						// Need to die according to the min number of workers

						worker->m_is_waiting = false;	
						worker->m_can_use = false;

//						pthread_mutex_unlock(&worker->m_mutex);
						worker_exit(worker, false);
					}else {
						dprintf(D_FULLDEBUG, "Thread(%d) must be alive for "
								"another request\n", worker->m_id);
					}
				}
			}
		}

		worker->m_is_doing = true;
		worker->m_is_waiting = false;
		worker->m_must_be_alive = false;

//		pthread_mutex_unlock(&worker->m_mutex);

		if(!handle_gahp_command(new_request) ) {
			dprintf(D_ALWAYS, "ERROR (io_loop) processing %s\n", 
					new_request->m_raw_cmd.c_str());
		}else {
			dprintf(D_FULLDEBUG, "CMD(\"%s\") is done with result %s", 
					new_request->m_raw_cmd.c_str(),
					new_request->m_result.c_str());
		}

		// Now we processed one request 
		delete new_request;
		new_request = NULL;

	}

	amazon_gahp_release_big_mutex();
	return NULL;
}
コード例 #3
0
ファイル: DBSpool.cpp プロジェクト: KingsleyYau/AdmirerSender
int DBSpool::ExecuteSQL(const string& strSQL, MYSQL_RES** res, short& shIdentifier, int& iRelt, unsigned long long* iInsertId)
{
    if (m_pDBConnection == NULL){
        return SQL_TYPE_UNKNOW;
    }
    int i = -1, iState = 0;
    timespec tTime;
    timeval tNow;
    while (i == -1){
        gettimeofday(&tNow, NULL);
        tTime.tv_sec = tNow.tv_sec + 1;
        tTime.tv_nsec = 0;
        //lock idle list
        Lock(&m_thExecMutex);
        if (m_IdleList.size() < 1){
            Unlock(&m_thExecMutex);
            //lock condition
            Lock(&m_thIdleMutex);
            iState = pthread_cond_timedwait(&m_thCond, &m_thIdleMutex, &tTime);
            Unlock(&m_thIdleMutex);
            if (iState == 0){
                //lock idle list
                Lock(&m_thExecMutex);
                if (m_IdleList.size() > 0){
                    i = m_IdleList.front();
                    m_IdleList.pop_front();
                    Unlock(&m_thExecMutex);
                    break;
                }else{
                    Unlock(&m_thExecMutex);
                    continue;
                }
            }else if(iState == ETIMEDOUT){
                return SQL_TYPE_UNKNOW;
            }
        }else{
            i = m_IdleList.front();
            m_IdleList.pop_front();
            Unlock(&m_thExecMutex);
        }
    }

    if (i >= 0){
        m_pDBConnection[i].Lock();
        int iRet = m_pDBConnection[i].ExecuteSQL(strSQL, res, iRelt, iInsertId);
        int iSize = 0;

        switch (iRet){
            case SQL_TYPE_SELECT:
                shIdentifier = i + 1;
                break;
            case SQL_TYPE_INSERT:
            case SQL_TYPE_UPDATE:
            case SQL_TYPE_DELETE:
            default:
                shIdentifier = 0;
                m_pDBConnection[i].Unlock();
                //lock idle list
                Lock(&m_thExecMutex);
                m_IdleList.push_back(i);
                iSize = m_IdleList.size();
                Unlock(&m_thExecMutex);
                //broadcast condition
                if (iSize == 1){
                    Lock(&m_thIdleMutex);
                    pthread_cond_broadcast(&m_thCond);
                    Unlock(&m_thIdleMutex);
                }
        }
        return iRet;
    }
    return SQL_TYPE_UNKNOW;
}
コード例 #4
0
ファイル: state_save.c プロジェクト: IFCA/slurm
/*
 * Run as pthread to keep saving slurmctld state information as needed,
 * Use schedule_job_save(),  schedule_node_save(), and schedule_part_save()
 * to queue state save of each data structure
 * no_data IN - unused
 * RET - NULL
 */
extern void *slurmctld_state_save(void *no_data)
{
	time_t last_save = 0, now;
	double save_delay;
	bool run_save;
	int save_count;

	while (1) {
		/* wait for work to perform */
		slurm_mutex_lock(&state_save_lock);
		while (1) {
			save_count = save_jobs + save_nodes + save_parts +
				     save_front_end + save_resv +
				     save_triggers;
			now = time(NULL);
			save_delay = difftime(now, last_save);
			if (save_count &&
			    (!run_save_thread ||
			     (save_delay >= SAVE_MAX_WAIT))) {
				last_save = now;
				break;		/* do the work */
			} else if (!run_save_thread) {
				run_save_thread = true;
				slurm_mutex_unlock(&state_save_lock);
				return NULL;	/* shutdown */
			} else if (save_count) { /* wait for a timeout */
				struct timespec ts = {0, 0};
				ts.tv_sec = now + 1;
				pthread_cond_timedwait(&state_save_cond,
				           	       &state_save_lock, &ts);
			} else {		/* wait for more work */
				pthread_cond_wait(&state_save_cond,
				           	  &state_save_lock);
			}
		}

		/* save front_end node info if necessary */
		run_save = false;
		/* slurm_mutex_lock(&state_save_lock); done above */
		if (save_front_end) {
			run_save = true;
			save_front_end = 0;
		}
		slurm_mutex_unlock(&state_save_lock);
		if (run_save)
			(void)dump_all_front_end_state();

		/* save job info if necessary */
		run_save = false;
		slurm_mutex_lock(&state_save_lock);
		if (save_jobs) {
			run_save = true;
			save_jobs = 0;
		}
		slurm_mutex_unlock(&state_save_lock);
		if (run_save)
			(void)dump_all_job_state();

		/* save node info if necessary */
		run_save = false;
		slurm_mutex_lock(&state_save_lock);
		if (save_nodes) {
			run_save = true;
			save_nodes = 0;
		}
		slurm_mutex_unlock(&state_save_lock);
		if (run_save)
			(void)dump_all_node_state();

		/* save partition info if necessary */
		run_save = false;
		slurm_mutex_lock(&state_save_lock);
		if (save_parts) {
			run_save = true;
			save_parts = 0;
		}
		slurm_mutex_unlock(&state_save_lock);
		if (run_save)
			(void)dump_all_part_state();

		/* save reservation info if necessary */
		run_save = false;
		slurm_mutex_lock(&state_save_lock);
		if (save_resv) {
			run_save = true;
			save_resv = 0;
		}
		slurm_mutex_unlock(&state_save_lock);
		if (run_save)
			(void)dump_all_resv_state();

		/* save trigger info if necessary */
		run_save = false;
		slurm_mutex_lock(&state_save_lock);
		if (save_triggers) {
			run_save = true;
			save_triggers = 0;
		}
		slurm_mutex_unlock(&state_save_lock);
		if (run_save)
			(void)trigger_state_save();
	}
}
コード例 #5
0
ファイル: adventure.c プロジェクト: ASalesman/ECE391-MP2
/*
 * status_thread
 *   DESCRIPTION: Function executed by status message helper thread.
 *                Waits for a message to be displayed, then shows the
 *                message for 1.5 seconds before deleting it.  If a
 *                new message has appeared in the meantime, restarts the
 *                clock and tries again.
 *   INPUTS: none (ignored)
 *   OUTPUTS: none
 *   RETURN VALUE: NULL
 *   SIDE EFFECTS: Changes the status message to an empty string.
 */
static void*
status_thread (void* ignore)
{
	struct timespec ts; /* absolute wake-up time */

	while (1) {

		/*
		 * Wait for a message to appear.  Note that we must check the
		 * condition after acquiring the lock, and that pthread_cond_wait
		 * yields the lock, then reacquires the lock before returning.
		 */
		(void)pthread_mutex_lock (&msg_lock);
		while ('\0' == status_msg[0]) {
			print_status_text(room_name(game_info.where), STATUS_ROOM_COLOR,
			                  STATUS_BG_COLOR, ALIGN_LEFT, 1);
			print_status_text(get_typed_command(), STATUS_COMMAND_COLOR,
			                  STATUS_BG_COLOR, ALIGN_RIGHT, 0);
			pthread_cond_wait (&msg_cv, &msg_lock);
		}

		/*
		 * A message is present: if we stop before the timeout
		 * passes, assume that a new one has been posted; if the
		 * timeout passes, clear the message and wait for a new one.
		 */
		do {
			/* Get the current time. */
			clock_gettime (CLOCK_REALTIME, &ts);
			const char *command = get_typed_command();
			int alignment = ALIGN_CENTER;
			if (command[0] != '\0') {
				alignment = ALIGN_LEFT;
			}
			print_status_text(status_msg, STATUS_FG_COLOR, STATUS_BG_COLOR,
			                  alignment, 1);
			print_status_text(command, STATUS_COMMAND_COLOR, STATUS_BG_COLOR,
			                  ALIGN_RIGHT, 0);

			/* Add 1.5 seconds to it. */
			if (500000000 <= ts.tv_nsec) {
				ts.tv_sec += 2;
				ts.tv_nsec -= 500000000;
			} else {
				ts.tv_sec += 1;
				ts.tv_nsec += 500000000;
			}

			/*
			 * And go to sleep.  If we wake up due to anything but a
			 * timeout, we assume (possibly incorrectly) that a new
			 * message has appeared and try to wait 1.5 seconds again.
			 */
		} while (ETIMEDOUT !=
		         pthread_cond_timedwait (&msg_cv, &msg_lock, &ts));

		/*
		 * Clear the message, then release the lock (remember that
		 * pthread_cond_timedwait reacquires the lock before returning).
		 */
		status_msg[0] = '\0';
		(void)pthread_mutex_unlock (&msg_lock);
	}

	/* This code never executes--the thread should always be cancelled. */
	return NULL;
}
コード例 #6
0
ファイル: amsd.c プロジェクト: NASAHackTO/ion-dtn
static void	*csHeartbeat(void *parm)
{
	CsState		*csState = (CsState *) parm;
	pthread_mutex_t	mutex;
	pthread_cond_t	cv;
	int		cycleCount = 6;
	int		i;
	Venture		*venture;
	int		j;
	Unit		*unit;
	Cell		*cell;
	int		result;
	struct timeval	workTime;
	struct timespec	deadline;

	CHKNULL(csState);
	if (pthread_mutex_init(&mutex, NULL))
	{
		putSysErrmsg("Can't start heartbeat, mutex init failed", NULL);
		return NULL;
	}

	if (pthread_cond_init(&cv, NULL))
	{
		pthread_mutex_destroy(&mutex);
		putSysErrmsg("Can't start heartbeat, cond init failed", NULL);
		return NULL;
	}
#ifndef mingw
	sigset_t	signals;

	sigfillset(&signals);
	pthread_sigmask(SIG_BLOCK, &signals, NULL);
#endif
	while (1)
	{
		lockMib();
		if (cycleCount > 5)	/*	Every N5_INTERVAL sec.	*/
		{
			cycleCount = 0;
			stopOtherConfigServers(csState);
		}

		for (i = 1; i <= MAX_VENTURE_NBR; i++)
		{
			venture = (_mib(NULL))->ventures[i];
			if (venture == NULL) continue;
			for (j = 0; j <= MAX_UNIT_NBR; j++)
			{
				unit = venture->units[j];
				if (unit == NULL
				|| (cell = unit->cell)->mamsEndpoint.ept
						== NULL)
				{
					continue;
				}

				if (cell->heartbeatsMissed == 3)
				{
					clearMamsEndpoint
						(&(cell->mamsEndpoint));
				}
				else if (cell->heartbeatsMissed < 3)
				{
					if (sendMamsMsg (&cell->mamsEndpoint,
						&csState->tsif, heartbeat,
						0, 0, NULL) < 0)
					{
						putErrmsg("Can't send \
heartbeat.", NULL);
					}
				}

				cell->heartbeatsMissed++;
			}
		}

		/*	Now sleep for N3_INTERVAL seconds.		*/

		unlockMib();
		getCurrentTime(&workTime);
		deadline.tv_sec = workTime.tv_sec + N3_INTERVAL;
		deadline.tv_nsec = workTime.tv_usec * 1000;
		pthread_mutex_lock(&mutex);
		result = pthread_cond_timedwait(&cv, &mutex, &deadline);
		pthread_mutex_unlock(&mutex);
		if (result)
		{
			errno = result;
			if (errno != ETIMEDOUT)
			{
				putSysErrmsg("Heartbeat failure", NULL);
				break;
			}
		}

		cycleCount++;
	}
コード例 #7
0
int ui_wait_key_with_repeat()
{
    int key = -1;

    // Loop to wait for more keys.
    do {
        int timeouts = UI_WAIT_KEY_TIMEOUT_SEC;
        int rc = 0;
        struct timeval now;
        struct timespec timeout;
        pthread_mutex_lock(&key_queue_mutex);
        while (key_queue_len == 0 && timeouts > 0) {
            gettimeofday(&now, NULL);
            timeout.tv_sec = now.tv_sec;
            timeout.tv_nsec = now.tv_usec * 1000;
            timeout.tv_sec += REFRESH_TIME_USB_INTERVAL;

            rc = 0;
            while (key_queue_len == 0 && rc != ETIMEDOUT) {
                rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex,
                                            &timeout);
                if (volumes_changed()) {
                    pthread_mutex_unlock(&key_queue_mutex);
                    return REFRESH;
                }
            }
            timeouts -= REFRESH_TIME_USB_INTERVAL;
        }
        pthread_mutex_unlock(&key_queue_mutex);

        if (rc == ETIMEDOUT && !usb_connected()) {
            return -1;
        }

        // Loop to wait wait for more keys, or repeated keys to be ready.
        while (1) {
            unsigned long now_msec;

            gettimeofday(&now, NULL);
            now_msec = (now.tv_sec * 1000) + (now.tv_usec / 1000);

            pthread_mutex_lock(&key_queue_mutex);

            // Replacement for the while conditional, so we don't have to lock the entire
            // loop, because that prevents the input system from touching the variables while
            // the loop is running which causes problems.
            if (key_queue_len == 0) {
                pthread_mutex_unlock(&key_queue_mutex);
                break;
            }

            key = key_queue[0];
            memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);

            // sanity check the returned key.
            if (key < 0) {
                pthread_mutex_unlock(&key_queue_mutex);
                return key;
            }

            // Check for already released keys and drop them if they've repeated.
            if (!key_pressed[key] && key_last_repeat[key] > 0) {
                pthread_mutex_unlock(&key_queue_mutex);
                continue;
            }

            if (key_can_repeat(key)) {
                // Re-add the key if a repeat is expected, since we just popped it. The
                // if below will determine when the key is actually repeated (returned)
                // in the mean time, the key will be passed through the queue over and
                // over and re-evaluated each time.
                if (key_pressed[key]) {
                    key_queue[key_queue_len] = key;
                    key_queue_len++;
                }
                if ((now_msec > key_press_time[key] + UI_KEY_WAIT_REPEAT && now_msec > key_last_repeat[key] + UI_KEY_REPEAT_INTERVAL) ||
                        key_last_repeat[key] == 0) {
                    key_last_repeat[key] = now_msec;
                } else {
                    // Not ready
                    pthread_mutex_unlock(&key_queue_mutex);
                    continue;
                }
            }
            pthread_mutex_unlock(&key_queue_mutex);
            return key;
        }
    } while (1);

    return key;
}
コード例 #8
0
ファイル: thread-sema.c プロジェクト: Sunmonds/gcc
int32
runtime_semasleep (int64 ns)
{
  M *m;
  struct go_sem *sem;
  int r;

  m = runtime_m ();
  sem = (struct go_sem *) m->waitsema;
  if (ns >= 0)
    {
      int64 abs;
      struct timespec ts;
      int err;

      abs = ns + runtime_nanotime ();
      ts.tv_sec = abs / 1000000000LL;
      ts.tv_nsec = abs % 1000000000LL;

      err = 0;

#ifdef HAVE_SEM_TIMEDWAIT
      r = sem_timedwait (&sem->sem, &ts);
      if (r != 0)
	err = errno;
#else
      if (pthread_mutex_lock (&sem->mutex) != 0)
	runtime_throw ("pthread_mutex_lock");

      while ((r = sem_trywait (&sem->sem)) != 0)
	{
	  r = pthread_cond_timedwait (&sem->cond, &sem->mutex, &ts);
	  if (r != 0)
	    {
	      err = r;
	      break;
	    }
	}

      if (pthread_mutex_unlock (&sem->mutex) != 0)
	runtime_throw ("pthread_mutex_unlock");
#endif

      if (err != 0)
	{
	  if (err == ETIMEDOUT || err == EAGAIN || err == EINTR)
	    return -1;
	  runtime_throw ("sema_timedwait");
	}
      return 0;
    }

  while (sem_wait (&sem->sem) != 0)
    {
      if (errno == EINTR)
	continue;
      runtime_throw ("sem_wait");
    }

  return 0;
}
コード例 #9
0
int
pthread_rwlock_timedwrlock (pthread_rwlock_t * rwlock,
			    const struct timespec *abstime)
{
  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_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0)
    {
      return result;
    }

  if ((result =
       pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted),
				abstime)) != 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 cancelation point
	   * according to POSIX 1003.1j section 18.1.2.
	   */
#if defined(_MSC_VER) && _MSC_VER < 800
#pragma inline_depth(0)
#endif
	  pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl);

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

	  pthread_cleanup_pop ((result != 0) ? 1 : 0);
#if defined(_MSC_VER) && _MSC_VER < 800
#pragma inline_depth()
#endif

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

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

  return result;
}
コード例 #10
0
ファイル: ct_main.c プロジェクト: ElPetros/contech
void* __ctBackgroundThreadWriter(void* d)
{
    FILE* serialFile;
    char* fname = getenv("CONTECH_FE_FILE");
    unsigned int wpos = 0;
    unsigned int maxBuffersAlloc = 0, memLimitBufCount = 0;
    size_t totalWritten = 0;
    pct_serial_buffer memLimitQueue = NULL;
    pct_serial_buffer memLimitQueueTail = NULL;
    unsigned long long totalLimitTime = 0, startLimitTime, endLimitTime;
    int mpiRank = __ctGetMPIRank();
    int mpiPresent = __ctIsMPIPresent();
    // TODO: Create MPI event
    // TODO: Modify filename with MPI rank
    // TODO: Only do the above when MPI is present
    
    if (fname == NULL)
    {
        if (mpiPresent != 0)
        {
            char* fnameMPI = strdup("/tmp/contech_fe      ");
            fnameMPI[15] = '.';
            snprintf(fnameMPI + 16, 5, "%d", mpiRank);
            serialFile = fopen(fnameMPI, "wb");
            free(fnameMPI);
        }
        else
        {
            serialFile = fopen("/tmp/contech_fe", "wb");
        }
    }
    else
    {
        serialFile = fopen(fname, "wb");
    }

    if (serialFile == NULL)
    {
        fprintf(stderr, "Failure to open front-end stream for writing.\n");
        if (fname == NULL) { fprintf(stderr, "\tCONTECH_FE_FILE unspecified\n");}
        else {fprintf(stderr, "\tAttempted on %s\n", fname);}
        exit(-1);
    }
    
    {
        unsigned int id = 0;
        ct_event_id ty = ct_event_version;
        unsigned int version = CONTECH_EVENT_VERSION;
        uint8_t* bb_info = _binary_contech_bin_start;
        
        fwrite(&id, sizeof(unsigned int), 1, serialFile); 
        fwrite(&ty, sizeof(unsigned int), 1, serialFile);
        fwrite(&version, sizeof(unsigned int), 1, serialFile);
        fwrite(bb_info, sizeof(unsigned int), 1, serialFile);
        totalWritten += 4 * sizeof(unsigned int);
        
        {
            size_t tl, wl;
            unsigned int buf[2];
            buf[0] = ct_event_rank;
            buf[1] = mpiRank;
            
            tl = 0;
            do
            {
                wl = fwrite(&buf + tl, sizeof(unsigned int), 2 - tl, serialFile);
                //if (wl > 0)
                // wl is 0 on error, so it is safe to still add
                tl += wl;
            } while  (tl < 2);
            
            totalWritten += 2 * sizeof(unsigned int);
        }
        
        bb_info += 4; // skip the basic block count
        while (bb_info != _binary_contech_bin_end)
        {
            // id, len, memop_0, ... memop_len-1
            // Contech pass lays out the events in appropriate format
            size_t tl = fwrite(bb_info, sizeof(char), _binary_contech_bin_end - bb_info, serialFile);
            bb_info += tl;
            totalWritten += tl;
        }
    }
    
    // Main loop
    //   Write queued buffer to disk until program terminates
    pthread_mutex_lock(&__ctQueueBufferLock);
    do {
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        ts.tv_sec += 30;
        int condRetVal = 0;
        
        // Check for queued buffer, i.e. is the program generating events
        while (__ctQueuedBuffers == NULL && condRetVal == 0)
        {
            condRetVal = pthread_cond_timedwait(&__ctQueueSignal, &__ctQueueBufferLock, &ts);
        }
        if (condRetVal == 0)
        {
            pthread_mutex_unlock(&__ctQueueBufferLock);
        }
    
        // The thread writer will likely sit in this loop except when the memory limit is triggered
        while (__ctQueuedBuffers != NULL)
        {
            // Write buffer to file
            size_t tl = 0;
            size_t wl = 0;
            pct_serial_buffer qb = __ctQueuedBuffers;
            
            // First craft the marker event that indicates a new buffer in the event list
            //   This event tells eventLib which contech created the next set of bytes
            {
                unsigned int buf[3];
                buf[0] = ct_event_buffer;
                buf[1] = __ctQueuedBuffers->id;
                buf[2] = __ctQueuedBuffers->basePos;
                //fprintf(stderr, "%d, %llx, %d\n", __ctQueuedBuffers->id, totalWritten, __ctQueuedBuffers->pos);
                do
                {
                    wl = fwrite(&buf + tl, sizeof(unsigned int), 3 - tl, serialFile);
                    //if (wl > 0)
                    // wl is 0 on error, so it is safe to still add
                    tl += wl;
                } while  (tl < 3);

                totalWritten += 3 * sizeof(unsigned int);
                
            }
            
            // TODO: fully integrate into debug framework
            #if DEBUG
            if (totalWritten < 256)
            {
                int i;
                for (i = 0; i < 256; i ++)
                {
                    fprintf(stderr, "%x ", __ctQueuedBuffers->data[i]);
                }
            }
            #endif
            
            // Now write the bytes out of the buffer, until all have been written
            tl = 0;
            wl = 0;
            if (qb->pos > SERIAL_BUFFER_SIZE)
            {
                fprintf(stderr, "Illegal buffer size - %d\n", qb->pos);
            }
            while (tl < __ctQueuedBuffers->pos)
            {
                wl = fwrite(__ctQueuedBuffers->data + tl, 
                            sizeof(char), 
                            (__ctQueuedBuffers->pos) - tl, 
                            serialFile);
                // if (wl < 0)
                // {
                //     continue;
                // }
                tl += wl;
                if (qb != __ctQueuedBuffers)
                {
                    fprintf(stderr, "Tampering with __ctQueuedBuffers!\n");
                }
            }
            if (tl != __ctQueuedBuffers->pos)
            {
                fprintf(stderr, "Write quantity(%lu) is not bytes in buffer(%d)\n", tl, __ctQueuedBuffers->pos);
            }
            totalWritten += tl;
            
            // "Free" buffer
            // First move the queue pointer, as we implicitly held the first element
            // Then switch locks and put this processed buffer onto the free list
            pthread_mutex_lock(&__ctQueueBufferLock);
            {
                pct_serial_buffer t = __ctQueuedBuffers;
                __ctQueuedBuffers = __ctQueuedBuffers->next;
                if (__ctQueuedBuffers == NULL) __ctQueuedBufferTail = NULL;
                pthread_mutex_unlock(&__ctQueueBufferLock);
                
                if (t->length < SERIAL_BUFFER_SIZE)
                {
                    free(t);
                    // After the unlock is end of while loop, 
                    //  so as the buffer was free() rather than put on the list
                    //  we continue
                    continue;
                }
                //continue; // HACK: LEAK!
                
                // Switching locks, "t" is now only held locally
                pthread_mutex_lock(&__ctFreeBufferLock);
#ifdef DEBUG
                pthread_mutex_lock(&__ctPrintLock);
                fprintf(stderr, "f,%p,%d\n", t, t->id);
                fflush(stderr);
                pthread_mutex_unlock(&__ctPrintLock);
#endif
                
                if (__ctCurrentBuffers == __ctMaxBuffers)
                {
                    if (__ctQueuedBuffers == NULL)
                    {
                        // memlimit end
                        struct timeb tp;
                        ftime(&tp);
                        endLimitTime = tp.time*1000 + tp.millitm;
                        totalLimitTime += (endLimitTime - startLimitTime);
                        memLimitQueueTail->next = t;
                        t->next = __ctFreeBuffers;
                        __ctFreeBuffers = memLimitQueue;
                        maxBuffersAlloc = __ctCurrentBuffers;
                        
                        // N.B. It is possible that thread X is holding a lock L
                        //   and then attempts to queue and allocate a new buffer.
                        //   And that thread Y blocks on lock L, whereby its buffer
                        //   will not be in the queue and therefore the count should
                        //   be greater than 0.
                        __ctCurrentBuffers = __ctMaxBuffers - (memLimitBufCount + 1);
                        memLimitQueue = NULL;
                        memLimitQueueTail = NULL;
                        pthread_cond_broadcast(&__ctFreeSignal);
                    }
                    else
                    {
                        if (memLimitQueueTail == NULL)
                        {
                            memLimitBufCount = 1;
                            memLimitQueue = t;
                            memLimitQueueTail = t;
                            t->next = NULL;
                            // memlimit start
                            struct timeb tp;
                            ftime(&tp);
                            startLimitTime = tp.time*1000 + tp.millitm;
                        }
                        else
                        {
                            memLimitBufCount ++;
                            memLimitQueueTail->next = t;
                            t->next = NULL;
                            memLimitQueueTail = t;
                        }
                    }
                }
                else
                {
                    t->next = __ctFreeBuffers;
                    __ctFreeBuffers = t;
                    if (__ctCurrentBuffers > maxBuffersAlloc)
                    {
                        maxBuffersAlloc = __ctCurrentBuffers;
                    }
                    assert(__ctCurrentBuffers > 0);
                    __ctCurrentBuffers --;
#if DEBUG
                    if (__ctCurrentBuffers < 2)
                    {
                        printf("%p\n", &t->data);
                    }
#endif
                }
            }
            pthread_mutex_unlock(&__ctFreeBufferLock);
        }
        
        // Exit condition is # of threads exited = # of threads
        // N.B. Main is part of this count
        pthread_mutex_lock(&__ctQueueBufferLock);
        if (__ctThreadExitNumber == __ctThreadGlobalNumber && 
            __ctQueuedBuffers == NULL) 
        { 
            // destroy mutex, cond variable
            // TODO: free freedBuffers
            {
                struct timeb tp;
                ftime(&tp);
                printf("CT_COMP: %d.%03d\n", (unsigned int)tp.time, tp.millitm);
                printf("CT_LIMIT: %llu.%03llu\n", totalLimitTime / 1000, totalLimitTime % 1000);
            }
            printf("Total Contexts: %u\n", __ctThreadGlobalNumber);
            printf("Total Uncomp Written: %ld\n", totalWritten);
            printf("Max Buffers Alloc: %u of %lu\n", maxBuffersAlloc, sizeof(ct_serial_buffer_sized));
            {
                struct rusage use;
                if (0 == getrusage(RUSAGE_SELF, &use))
                {
                    printf("Max RSS: %ld\n", use.ru_maxrss);
                }
            }
            printQueueStats();
            fflush(stdout);
            
            fflush(serialFile);
            fclose(serialFile);
            
            pthread_mutex_unlock(&__ctQueueBufferLock);
            pthread_exit(NULL);            
        }
    } while (1);
}
コード例 #11
0
ファイル: OMXCore.cpp プロジェクト: BenRomberg/omxplayer
// timeout in milliseconds
OMX_ERRORTYPE COMXCoreComponent::WaitForEvent(OMX_EVENTTYPE eventType, long timeout)
{
#ifdef OMX_DEBUG_EVENTS
  CLog::Log(LOGDEBUG, "COMXCoreComponent::WaitForEvent %s wait event 0x%08x\n",
      m_componentName.c_str(), (int)eventType);
#endif

  pthread_mutex_lock(&m_omx_event_mutex);
  struct timespec endtime;
  clock_gettime(CLOCK_REALTIME, &endtime);
  add_timespecs(endtime, timeout);
  while(true) 
  {
    for (std::vector<omx_event>::iterator it = m_omx_events.begin(); it != m_omx_events.end(); it++) 
    {
      omx_event event = *it;

#ifdef OMX_DEBUG_EVENTS
      CLog::Log(LOGDEBUG, "COMXCoreComponent::WaitForEvent %s inlist event event.eEvent 0x%08x event.nData1 0x%08x event.nData2 %d\n",
          m_componentName.c_str(), (int)event.eEvent, (int)event.nData1, (int)event.nData2);
#endif


      if(event.eEvent == OMX_EventError && event.nData1 == (OMX_U32)OMX_ErrorSameState && event.nData2 == 1)
      {
#ifdef OMX_DEBUG_EVENTS
        CLog::Log(LOGDEBUG, "COMXCoreComponent::WaitForEvent %s remove event event.eEvent 0x%08x event.nData1 0x%08x event.nData2 %d\n",
          m_componentName.c_str(), (int)event.eEvent, (int)event.nData1, (int)event.nData2);
#endif
        m_omx_events.erase(it);
        pthread_mutex_unlock(&m_omx_event_mutex);
        return OMX_ErrorNone;
      }
      else if(event.eEvent == OMX_EventError) 
      {
        m_omx_events.erase(it);
        pthread_mutex_unlock(&m_omx_event_mutex);
        return (OMX_ERRORTYPE)event.nData1;
      }
      else if(event.eEvent == eventType) 
      {
#ifdef OMX_DEBUG_EVENTS
        CLog::Log(LOGDEBUG, "COMXCoreComponent::WaitForEvent %s remove event event.eEvent 0x%08x event.nData1 0x%08x event.nData2 %d\n",
          m_componentName.c_str(), (int)event.eEvent, (int)event.nData1, (int)event.nData2);
#endif

        m_omx_events.erase(it);
        pthread_mutex_unlock(&m_omx_event_mutex);
        return OMX_ErrorNone;
      }
    }

    int retcode = pthread_cond_timedwait(&m_omx_event_cond, &m_omx_event_mutex, &endtime);
    if (retcode != 0) 
    {
      if (timeout > 0)
        CLog::Log(LOGERROR, "COMXCoreComponent::WaitForEvent %s wait event 0x%08x timeout %ld\n",
                          m_componentName.c_str(), (int)eventType, timeout);
      pthread_mutex_unlock(&m_omx_event_mutex);
      return OMX_ErrorMax;
    }
  }
  pthread_mutex_unlock(&m_omx_event_mutex);
  return OMX_ErrorNone;
}
コード例 #12
0
ファイル: thumbnailer.c プロジェクト: HEAlex/vlc-android
/**
 * Thumbnailer main function.
 * return null if the thumbail generation failed.
 **/
jbyteArray Java_org_videolan_libvlc_LibVLC_getThumbnail(JNIEnv *env, jobject thiz,
                                                        jlong instance, jstring filePath,
                                                        const jint frameWidth, const jint frameHeight)
{
    libvlc_instance_t *libvlc = (libvlc_instance_t *)(intptr_t)instance;
    jbyteArray byteArray = NULL;

    /* Create the thumbnailer data structure */
    thumbnailer_sys_t *sys = calloc(1, sizeof(thumbnailer_sys_t));
    if (sys == NULL)
    {
        LOGE("Could not create the thumbnailer data structure!");
        goto enomem;
    }

    /* Initialize the barrier. */
    pthread_mutex_init(&sys->doneMutex, NULL);
    pthread_cond_init(&sys->doneCondVar, NULL);

    /* Create a media player playing environment */
    libvlc_media_player_t *mp = libvlc_media_player_new(libvlc);
    libvlc_media_player_set_video_title_display(mp, libvlc_position_disable, 0);

    libvlc_media_t *m = new_media(instance, env, thiz, filePath, true, false);
    if (m == NULL)
    {
        LOGE("Could not create the media to play!");
        goto end;
    }

    /* Fast and no options */
    libvlc_media_add_option( m, ":no-audio" );
    libvlc_media_add_option( m, ":no-spu" );
    libvlc_media_add_option( m, ":no-osd" );

    libvlc_media_player_set_media(mp, m);

    /* Get the size of the video with the tracks information of the media. */
    libvlc_media_track_t **tracks;
    libvlc_media_parse(m);
    int nbTracks = libvlc_media_tracks_get(m, &tracks);
    libvlc_media_release(m);

    /* Parse the results */
    unsigned videoWidth = 0, videoHeight = 0;
    bool hasVideoTrack = false;
    for (unsigned i = 0; i < nbTracks; ++i)
        if (tracks[i]->i_type == libvlc_track_video)
        {
            videoWidth = tracks[i]->video->i_width;
            videoHeight = tracks[i]->video->i_height;
            hasVideoTrack = true;
            break;
        }

    libvlc_media_tracks_release(tracks, nbTracks);

    /* Abort if we have not found a video track. */
    if (!hasVideoTrack)
    {
        LOGE("Could not find any video track in this file.\n");
        goto end;
    }

    LOGD("Video dimensions: %ix%i.\n", videoWidth, videoHeight );

    /* VLC could not tell us the size */
    if( videoWidth == 0 || videoHeight == 0 )
    {
        LOGE("Could not find the video dimensions.\n");
        goto end;
    }

    if( videoWidth < 32 || videoHeight < 32 || videoWidth > 2048 || videoWidth > 2048 )
    {
        LOGE("Wrong video dimensions.\n");
        goto end;
    }

    /* Compute the size parameters of the frame to generate. */
    unsigned thumbWidth  = frameWidth;
    unsigned thumbHeight = frameHeight;
    const float inputAR = (float)videoWidth / videoHeight;
    const float screenAR = (float)frameWidth / frameHeight;

    /* Most of the cases, video is wider than tall */
    if (screenAR < inputAR)
    {
        thumbHeight = (float)frameWidth / inputAR + 1;
        sys->blackBorders = ( (frameHeight - thumbHeight) / 2 ) * frameWidth;
    }
    else
    {
        LOGD("Weird aspect Ratio.\n");
        thumbWidth = (float)frameHeight * inputAR;
        sys->blackBorders = (frameWidth - thumbWidth) / 2;
    }

    sys->thumbPitch  = thumbWidth * PIXEL_SIZE;
    sys->thumbHeight = thumbHeight;
    sys->frameWidth  = frameWidth;

    /* Allocate the memory to store the frames. */
    size_t thumbSize = sys->thumbPitch * (sys->thumbHeight+1);
    sys->thumbData = malloc(thumbSize);
    if (sys->thumbData == NULL)
    {
        LOGE("Could not allocate the memory to store the frame!");
        goto end;
    }

    /* Allocate the memory to store the thumbnail. */
    unsigned frameSize = frameWidth * frameHeight * PIXEL_SIZE;
    sys->frameData = calloc(frameSize, 1);
    if (sys->frameData == NULL)
    {
        LOGE("Could not allocate the memory to store the thumbnail!");
        goto end;
    }

    /* Set the video format and the callbacks. */
    libvlc_video_set_format(mp, "RGBA", thumbWidth, thumbHeight, sys->thumbPitch);
    libvlc_video_set_callbacks(mp, thumbnailer_lock, thumbnailer_unlock,
                               NULL, (void*)sys);
    sys->state = THUMB_SEEKING;

    /* Play the media. */
    libvlc_media_player_play(mp);
    libvlc_media_player_set_position(mp, THUMBNAIL_POSITION);

    const int wait_time = 50000;
    const int max_attempts = 100;
    for (int i = 0; i < max_attempts; ++i) {
        if (libvlc_media_player_is_playing(mp) && libvlc_media_player_get_position(mp) >= THUMBNAIL_POSITION)
            break;
        usleep(wait_time);
    }

    /* Wait for the thumbnail to be generated. */
    pthread_mutex_lock(&sys->doneMutex);
    sys->state = THUMB_SEEKED;
    struct timespec deadline;
    clock_gettime(CLOCK_REALTIME, &deadline);
    deadline.tv_sec += 10; /* amount of seconds before we abort thumbnailer */
    do {
        int ret = pthread_cond_timedwait(&sys->doneCondVar, &sys->doneMutex, &deadline);
        if (ret == ETIMEDOUT)
            break;
    } while (sys->state != THUMB_DONE);
    pthread_mutex_unlock(&sys->doneMutex);

    /* Stop and release the media player. */
    libvlc_media_player_stop(mp);
    libvlc_media_player_release(mp);

    if (sys->state == THUMB_DONE) {
        /* Create the Java byte array to return the create thumbnail. */
        byteArray = (*env)->NewByteArray(env, frameSize);
        if (byteArray == NULL)
        {
            LOGE("Could not allocate the Java byte array to store the frame!");
            goto end;
        }

        (*env)->SetByteArrayRegion(env, byteArray, 0, frameSize,
                (jbyte *)sys->frameData);
    }

end:
    pthread_mutex_destroy(&sys->doneMutex);
    pthread_cond_destroy(&sys->doneCondVar);
    free(sys->frameData);
    free(sys->thumbData);
    free(sys);
enomem:
    return byteArray;
}
コード例 #13
0
ファイル: threads.c プロジェクト: NeoAxis/SDK
int alcnd_timedwait(alcnd_t *cond, almtx_t *mtx, const struct timespec *time_point)
{
    if(pthread_cond_timedwait(cond, mtx, time_point) == 0)
        return althrd_success;
    return althrd_error;
}
コード例 #14
0
ファイル: daemon.c プロジェクト: CurlyMoo/Splash
void *update_progress(void *param) {
	pthread_mutex_lock(&progress_lock);
	int last_percentage = 0;
	int new_percentage = -1;
	int n = 0;

	while(main_loop) {
		int target_width = 0;
		int x = 0, y = 0;

		if(percentage == 100 || percentage == -1 || percentage == 0) {
			target_width = (int)progress.background_w;
		} else {
			target_width = (int)(progress.background_w * (((double)percentage/100)));
		}

		if(draw_loop) {
			while(draw_loop) {
				pthread_mutex_lock(&progress_lock);
				if(target_width > 0 && nodaemon == 0 && black == 0) {
					if(progress_active == 0) {
						if(strcmp(progress.active_start_e, "jpg") == 0) {
							draw_jpg(progress.background_x, progress.background_y, progress.background_z, progress.active_start_img);
						} else if(strcmp(progress.active_start_e, "png") == 0) {
							draw_png(progress.background_x, progress.background_y, progress.background_z, progress.active_start_img);
						}
					} else {
						if(strcmp(progress.inactive_start_e, "jpg") == 0) {
							draw_jpg(progress.background_x, progress.background_y, progress.background_z, progress.inactive_start_img);
						} else if(strcmp(progress.inactive_start_e, "png") == 0) {
							draw_png(progress.background_x, progress.background_y, progress.background_z, progress.inactive_start_img);
						}
					}
				}
				if(progress_active == 0) {
					x += progress.active_start_w;
				} else {
					x += progress.inactive_start_w;
				}

				if(progress_active == 0) {
					if(target_width >= (progress.background_w-progress.active_end_w)) {
						y = (int)(progress.background_w-progress.inactive_end_w);
					} else {
						y = (int)target_width;
					}
				} else {
					if(target_width >= (progress.background_w-progress.inactive_end_w)) {
						y = (int)(progress.background_w-progress.inactive_end_w);
					} else {
						y = (int)target_width;
					}
				}

				if(x < y) {
					while(x < y) {
						if(nodaemon == 0 && black == 0) {
							if(progress_active == 0) {
								if(strcmp(progress.active_fill_e, "jpg") == 0) {
									draw_jpg(progress.background_x+x, progress.background_y, progress.background_z, progress.active_fill_img);
								} else if(strcmp(progress.active_fill_e, "png") == 0) {
									draw_png(progress.background_x+x, progress.background_y, progress.background_z, progress.active_fill_img);
								}
								if(percentage == -1) {
									usleep((__useconds_t)(speed*progress.active_fill_w));
								}
							} else {
								if(strcmp(progress.inactive_fill_e, "jpg") == 0) {
									draw_jpg(progress.background_x+x, progress.background_y, progress.background_z, progress.inactive_fill_img);
								} else if(strcmp(progress.inactive_fill_e, "png") == 0) {
									draw_png(progress.background_x+x, progress.background_y, progress.background_z, progress.inactive_fill_img);
								}
								if(percentage == -1) {
									usleep((__useconds_t)(speed*progress.inactive_fill_w));
								}
							}
						}
						x++;
					}
				}

				if(x < target_width) {
					if(nodaemon == 0 && black == 0) {
						if(progress_active == 0) {
							if(strcmp(progress.active_end_e, "jpg") == 0) {
								draw_jpg(progress.background_x+x, progress.background_y, progress.background_z, progress.active_end_img);
							} else if(strcmp(progress.active_end_e, "png") == 0) {
								draw_png(progress.background_x+x, progress.background_y, progress.background_z, progress.active_end_img);
							}
						} else {
							if(strcmp(progress.inactive_end_e, "jpg") == 0) {
								draw_jpg(progress.background_x+x, progress.background_y, progress.background_z, progress.inactive_end_img);
							} else if(strcmp(progress.inactive_end_e, "png") == 0) {
								draw_png(progress.background_x+x, progress.background_y, progress.background_z, progress.inactive_end_img);
							}
						}
						x = (int)target_width;
					}
				}
				if(x == progress.background_w) {
					progress_active ^= 1;
					x = 0;
				}
				if(infinite == 0) {
					if(new_percentage > -1) {
						percentage = new_percentage;
						new_percentage = -1;
						target_width = (int)(progress.background_w * (((double)percentage/100)));
						x = 0;
					} else if(percentage < last_percentage && last_percentage != 100) {
						new_percentage = percentage;
						target_width = (int)progress.background_w;
						x = 0;
					} else {
						draw_loop = 0;
					}
					last_percentage = percentage;
				}
				pthread_mutex_unlock(&progress_lock);
			}
		} else {
			if(percentage > 0 && percentage < 100) {
				struct timeval tp;
				struct timespec ts;

				gettimeofday(&tp, NULL);
				ts.tv_sec = tp.tv_sec;
				ts.tv_nsec = tp.tv_usec * 1000;
				ts.tv_sec += 1;

				n = pthread_cond_timedwait(&progress_signal, &progress_lock, &ts);
				if(n == ETIMEDOUT) {
					percentage++;
					draw_loop = 1;
				}
			} else {
				n = pthread_cond_wait(&progress_signal, &progress_lock);
			}
		}
	}
	return (void *)NULL;
}
コード例 #15
0
static void *timer_thread(void *thread_data)
{
    int ret = -ETIMEDOUT;
    struct timespec ts;
    struct timeval tv;
    timer_data* t = (timer_data*)thread_data;

    LOC_LOGD("%s:%d]: Enter. Delay = %d\n", __func__, __LINE__, t->time_msec);

    gettimeofday(&tv, NULL);
    clock_gettime(CLOCK_REALTIME, &ts);
    if(t->time_msec >= 1000) {
        ts.tv_sec += t->time_msec/1000;
        t->time_msec = t->time_msec % 1000;
    }
    if(t->time_msec)
        ts.tv_nsec += t->time_msec * 1000000;
    if(ts.tv_nsec > 999999999) {
        LOC_LOGD("%s:%d]: Large nanosecs\n", __func__, __LINE__);
        ts.tv_sec += 1;
        ts.tv_nsec -= 1000000000;
    }
    LOC_LOGD("%s:%d]: ts.tv_sec:%d; ts.tv_nsec:%d\n"
             "\t Current time: %d sec; %d nsec",
             __func__, __LINE__, (int)ts.tv_sec, (int)ts.tv_nsec,
             (int)tv.tv_sec, (int)tv.tv_usec*1000);

    pthread_mutex_lock(&(t->timer_mutex));
    if (READY == t->state) {
        t->state = WAITING;
        ret = pthread_cond_timedwait(&t->timer_cond, &t->timer_mutex, &ts);
        t->state = DONE;
    }
    pthread_mutex_unlock(&(t->timer_mutex));

    switch (ret) {
    case ETIMEDOUT:
        LOC_LOGV("%s:%d]: loc_timer timed out",  __func__, __LINE__);
        break;
    case 0:
        LOC_LOGV("%s:%d]: loc_timer stopped",  __func__, __LINE__);
        break;
    case -ETIMEDOUT:
        LOC_LOGV("%s:%d]: loc_timer cancelled",  __func__, __LINE__);
        break;
    default:
        LOC_LOGE("%s:%d]: Call to pthread timedwait failed; ret=%d\n",
                 __func__, __LINE__, ret);
        break;
    }

    if(ETIMEDOUT == ret)
        t->callback_func(t->user_data, ret);

    // A (should be rare) race condition is that, when the loc_time_stop is called
    // and acquired mutex, we reach here.  pthread_mutex_destroy will fail with
    // error code EBUSY.  We give it 6 tries in 5 seconds.  Should be eanough time
    // for loc_timer_stop to complete.  With the 7th try, we also perform unlock
    // prior to destroy.
    {
        int i;
        for (i = 0; EBUSY == pthread_mutex_destroy(&t->timer_mutex) && i <= 5; i++) {
            if (i < 5) {
                sleep(1);
            } else {
                // nah, forget it, something is seriously wrong.  Mutex has been
                // held too long.  Unlock the mutext here.
                pthread_mutex_unlock(&t->timer_mutex);
            }
        }
    }
    pthread_cond_destroy(&t->timer_cond);

    free(t);
    LOC_LOGD("%s:%d]: Exit\n", __func__, __LINE__);
    return NULL;
}
コード例 #16
0
ファイル: producer_decklink.cpp プロジェクト: gmarco/mlt-orig
    mlt_frame getFrame()
    {
        struct timeval now;
        struct timespec tm;
        double fps = mlt_producer_get_fps( getProducer() );
        mlt_position position = mlt_producer_position( getProducer() );
        mlt_frame frame = mlt_cache_get_frame( m_cache, position );

        // Allow the buffer to fill to the requested initial buffer level.
        if ( m_isBuffering )
        {
            int prefill = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "prefill" );
            int buffer = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "buffer" );

            m_isBuffering = false;
            prefill = prefill > buffer ? buffer : prefill;
            pthread_mutex_lock( &m_mutex );
            while ( mlt_deque_count( m_queue ) < prefill )
            {
                // Wait up to buffer/fps seconds
                gettimeofday( &now, NULL );
                long usec = now.tv_sec * 1000000 + now.tv_usec;
                usec += 1000000 * buffer / fps;
                tm.tv_sec = usec / 1000000;
                tm.tv_nsec = (usec % 1000000) * 1000;
                if ( pthread_cond_timedwait( &m_condition, &m_mutex, &tm ) )
                    break;
            }
            pthread_mutex_unlock( &m_mutex );
        }

        if ( !frame )
        {
            // Wait if queue is empty
            pthread_mutex_lock( &m_mutex );
            while ( mlt_deque_count( m_queue ) < 1 )
            {
                // Wait up to twice frame duration
                gettimeofday( &now, NULL );
                long usec = now.tv_sec * 1000000 + now.tv_usec;
                usec += 2000000 / fps;
                tm.tv_sec = usec / 1000000;
                tm.tv_nsec = (usec % 1000000) * 1000;
                if ( pthread_cond_timedwait( &m_condition, &m_mutex, &tm ) )
                    // Stop waiting if error (timed out)
                    break;
            }
            frame = ( mlt_frame ) mlt_deque_pop_front( m_queue );
            pthread_mutex_unlock( &m_mutex );

            // add to cache
            if ( frame )
            {
                mlt_frame_set_position( frame, position );
                mlt_cache_put_frame( m_cache, frame );
            }
        }

        // Set frame timestamp and properties
        if ( frame )
        {
            mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( getProducer() ) );
            mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
            mlt_properties_set_int( properties, "progressive", profile->progressive );
            mlt_properties_set_int( properties, "meta.media.progressive", profile->progressive );
            mlt_properties_set_int( properties, "top_field_first", m_topFieldFirst );
            mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
            mlt_properties_set_int( properties, "meta.media.sample_aspect_num", profile->sample_aspect_num );
            mlt_properties_set_int( properties, "meta.media.sample_aspect_den", profile->sample_aspect_den );
            mlt_properties_set_int( properties, "meta.media.frame_rate_num", profile->frame_rate_num );
            mlt_properties_set_int( properties, "meta.media.frame_rate_den", profile->frame_rate_den );
            mlt_properties_set_int( properties, "width", profile->width );
            mlt_properties_set_int( properties, "meta.media.width", profile->width );
            mlt_properties_set_int( properties, "height", profile->height );
            mlt_properties_set_int( properties, "meta.media.height", profile->height );
            mlt_properties_set_int( properties, "format", mlt_image_yuv422 );
            mlt_properties_set_int( properties, "colorspace", m_colorspace );
            mlt_properties_set_int( properties, "meta.media.colorspace", m_colorspace );
            mlt_properties_set_int( properties, "audio_frequency", 48000 );
            mlt_properties_set_int( properties, "audio_channels",
                                    mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "channels" ) );
        }
        else
            mlt_log_warning( getProducer(), "buffer underrun\n" );

        return frame;
    }
コード例 #17
0
ファイル: cpr_darwin_ipc.c プロジェクト: hibrium/Pale-Moon
/**
 * Retrieve a message from a particular message queue
 *
 * @param[in]  msgQueue    - msg queue from which to retrieve the message
 * @param[in]  waitForever - boolean to either wait forever (TRUE) or not
 *                           wait at all (FALSE) if the msg queue is empty.
 * @param[out] ppUserData  - pointer to a pointer to user defined data
 *
 * @return Retrieved message buffer or NULL if failure occurred or
 *         the waitForever flag was set to false and no messages were
 *         on the queue.
 *
 * @note   If ppUserData is defined, the value will be initialized to NULL
 */
void *
cprGetMessage (cprMsgQueue_t msgQueue, boolean waitForever, void **ppUserData)
{
    static const char fname[] = "cprGetMessage";

    void *buffer = 0;
    cpr_msg_queue_t *msgq;
    cpr_msgq_node_t *node;
    struct timespec timeout;
    struct timeval tv;
    // On the iPhone, there is a DarwinAlias problem with "timezone"
    struct _timezone {
        int     tz_minuteswest; /* of Greenwich */
        int     tz_dsttime;     /* type of dst correction to apply */
    } tz;

    /* Initialize ppUserData */
    if (ppUserData) {
        *ppUserData = NULL;
    }

    msgq = (cpr_msg_queue_t *) msgQueue;
    if (msgq == NULL) {
        /* Bad application! */
        CPR_ERROR("%s: Invalid input\n", fname);
        errno = EINVAL;
        return NULL;
    }

    /*
     * If waitForever is set, block on the message queue
     * until a message is received, else return after
     * 25msec of waiting
     */
    pthread_mutex_lock(&msgq->mutex);

    if (!waitForever)
    {
        // We'll wait till 25uSec from now
        gettimeofday(&tv, &tz);
        timeout.tv_nsec = (tv.tv_usec * 1000) + 25000;
        timeout.tv_sec = tv.tv_sec;

        pthread_cond_timedwait(&msgq->cond, &msgq->mutex, &timeout);

    }
    else
    {
        while(msgq->tail==NULL)
        {
            pthread_cond_wait(&msgq->cond, &msgq->mutex);
        }
    }

    // If there is a message on the queue, de-queue it
    if (msgq->tail)
    {
        node = msgq->tail;
        msgq->tail = node->prev;
        if (msgq->tail) {
            msgq->tail->next = NULL;
        }
        if (msgq->head == node) {
            msgq->head = NULL;
        }
        msgq->currentCount--;
        /*
         * Pull out the data
         */
        if (ppUserData) {
            *ppUserData = node->pUserData;
        }
        buffer = node->msg;

    }

    pthread_mutex_unlock(&msgq->mutex);

    return buffer;
}
コード例 #18
0
void SC_TerminalClient::commandLoop()
{
	bool haveNext = false;
	struct timespec nextAbsTime;

	lockSignal();

	while( shouldBeRunning() )
	{

		while ( mSignals ) {
			int sig = mSignals;

			unlockSignal();

			if (sig & sig_input) {
				//postfl("input\n");
				lockInput();
				interpretInput();
				// clear input signal, as we've processed anything signalled so far.
				lockSignal();
				mSignals &= ~sig_input;
				unlockSignal();
				unlockInput();
			}

			if (sig & sig_sched) {
				//postfl("tick\n");
				double secs;
				lock();
				haveNext = tickLocked( &secs );
				// clear scheduler signal, as we've processed all items scheduled up to this time.
				// and will enter the wait according to schedule.
				lockSignal();
				mSignals &= ~sig_sched;
				unlockSignal();
				unlock();

				flush();

				//postfl("tick -> next time = %f\n", haveNext ? secs : -1);
				ElapsedTimeToTimespec( secs, &nextAbsTime );
			}

			if (sig & sig_stop) {
				stopMain();
				lockSignal();
				mSignals &= ~sig_stop;
				unlockSignal();
			}

			if (sig & sig_recompile) {
				recompileLibrary();
				lockSignal();
				mSignals &= ~sig_recompile;
				unlockSignal();
			}

			lockSignal();
		}

		if( !shouldBeRunning() ) {
			break;
		}
		else if( haveNext ) {
			int result = pthread_cond_timedwait( &mCond, &mSignalMutex, &nextAbsTime );
			if( result == ETIMEDOUT ) mSignals |= sig_sched;
		}
		else {
			pthread_cond_wait( &mCond, &mSignalMutex );
		}
	}

	unlockSignal();
}
コード例 #19
0
ファイル: videostream.cpp プロジェクト: tidehc/media-server-1
/*******************************************
* SendVideo
*	Capturamos el video y lo mandamos
*******************************************/
int VideoStream::SendVideo()
{
	timeval prev;
	timeval lastFPU;
	
	DWORD num = 0;
	QWORD overslept = 0;

	Acumulator bitrateAcu(1000);
	Acumulator fpsAcu(1000);
	
	Log(">SendVideo [width:%d,size:%d,bitrate:%d,fps:%d,intra:%d]\n",videoGrabWidth,videoGrabHeight,videoBitrate,videoFPS,videoIntraPeriod);

	//Creamos el encoder
	VideoEncoder* videoEncoder = VideoCodecFactory::CreateEncoder(videoCodec,videoProperties);

	//Comprobamos que se haya creado correctamente
	if (videoEncoder == NULL)
		//error
		return Error("Can't create video encoder\n");

	//Comrpobamos que tengamos video de entrada
	if (videoInput == NULL)
		return Error("No video input");

	//Iniciamos el tama�o del video
	if (!videoInput->StartVideoCapture(videoGrabWidth,videoGrabHeight,videoFPS))
		return Error("Couldn't set video capture\n");

	//Start at 80%
	int current = videoBitrate*0.8;

	//Send at higher bitrate first frame, but skip frames after that so sending bitrate is kept
	videoEncoder->SetFrameRate(videoFPS,current*5,videoIntraPeriod);

	//No wait for first
	QWORD frameTime = 0;

	//Iniciamos el tamama�o del encoder
 	videoEncoder->SetSize(videoGrabWidth,videoGrabHeight);

	//The time of the previos one
	gettimeofday(&prev,NULL);

	//Fist FPU
	gettimeofday(&lastFPU,NULL);
	
	//Started
	Log("-Sending video\n");

	//Mientras tengamos que capturar
	while(sendingVideo)
	{
		//Nos quedamos con el puntero antes de que lo cambien
		BYTE *pic = videoInput->GrabFrame(frameTime/1000);

		//Check picture
		if (!pic)
			//Exit
			continue;

		//Check if we need to send intra
		if (sendFPU)
		{
			//Do not send anymore
			sendFPU = false;
			//Do not send if we just send one (100ms)
			if (getDifTime(&lastFPU)/1000>minFPUPeriod)
			{
				//Send at higher bitrate first frame, but skip frames after that so sending bitrate is kept
				videoEncoder->SetFrameRate(videoFPS,current*5,videoIntraPeriod);
				//Reste frametime so it is calcualted afterwards
				frameTime = 0;
				//Set it
				videoEncoder->FastPictureUpdate();
				//Update last FPU
				getUpdDifTime(&lastFPU);
			}
		}

		//Calculate target bitrate
		int target = current;

		//Check temporal limits for estimations
		if (bitrateAcu.IsInWindow())
		{
			//Get real sent bitrate during last second and convert to kbits 
			DWORD instant = bitrateAcu.GetInstantAvg()/1000;
			//If we are in quarentine
			if (videoBitrateLimitCount)
				//Limit sending bitrate
				target = videoBitrateLimit;
			//Check if sending below limits
			else if (instant<videoBitrate)
				//Increase a 8% each second or fps kbps
				target += (DWORD)(target*0.08/videoFPS)+1;
		}

		//Check target bitrate agains max conf bitrate
		if (target>videoBitrate*1.2)
			//Set limit to max bitrate allowing a 20% overflow so instant bitrate can get closer to target
			target = videoBitrate*1.2;

		//Check limits counter
		if (videoBitrateLimitCount>0)
			//One frame less of limit
			videoBitrateLimitCount--;

		//Check if we have a new bitrate
		if (target && target!=current)
		{
			//Reset bitrate
			videoEncoder->SetFrameRate(videoFPS,target,videoIntraPeriod);
			//Upate current
			current = target;
		}
		
		//Procesamos el frame
		VideoFrame *videoFrame = videoEncoder->EncodeFrame(pic,videoInput->GetBufferSize());

		//If was failed
		if (!videoFrame)
			//Next
			continue;
		
		//Increase frame counter
		fpsAcu.Update(getTime()/1000,1);
		
		//Check
		if (frameTime)
		{
			timespec ts;
			//Lock
			pthread_mutex_lock(&mutex);
			//Calculate slept time
			QWORD sleep = frameTime;
			//Remove extra sleep from prev
			if (overslept<sleep)
				//Remove it
				sleep -= overslept;
			else
				//Do not overflow
				sleep = 1;

			//Calculate timeout
			calcAbsTimeoutNS(&ts,&prev,sleep);
			//Wait next or stopped
			int canceled  = !pthread_cond_timedwait(&cond,&mutex,&ts);
			//Unlock
			pthread_mutex_unlock(&mutex);
			//Check if we have been canceled
			if (canceled)
				//Exit
				break;
			//Get differencence
			QWORD diff = getDifTime(&prev);
			//If it is biffer
			if (diff>frameTime)
				//Get what we have slept more
				overslept = diff-frameTime;
			else
				//No oversletp (shoulddn't be possible)
				overslept = 0;
		}

		//Increase frame counter
		fpsAcu.Update(getTime()/1000,1);
		
		//If first
		if (!frameTime)
		{
			//Set frame time, slower
			frameTime = 5*1000000/videoFPS;
			//Restore bitrate
			videoEncoder->SetFrameRate(videoFPS,current,videoIntraPeriod);
		} else {
			//Set frame time
			frameTime = 1000000/videoFPS;
		}
		
		//Add frame size in bits to bitrate calculator
		bitrateAcu.Update(getDifTime(&ini)/1000,videoFrame->GetLength()*8);

		//Set frame timestamp
		videoFrame->SetTimestamp(getDifTime(&ini)/1000);

		//Check if we have mediaListener
		if (mediaListener)
			//Call it
			mediaListener->onMediaFrame(*videoFrame);

		//Set sending time of previous frame
		getUpdDifTime(&prev);

		//Calculate sending times based on bitrate
		DWORD sendingTime = videoFrame->GetLength()*8/current;

		//Adjust to maximum time
		if (sendingTime>frameTime/1000)
			//Cap it
			sendingTime = frameTime/1000;

		//If it was a I frame
		if (videoFrame->IsIntra())
			//Clean rtp rtx buffer
			rtp.FlushRTXPackets();

		//Send it smoothly
		smoother.SendFrame(videoFrame,sendingTime);

		//Dump statistics
		if (num && ((num%videoFPS*10)==0))
		{
			Debug("-Send bitrate target=%d current=%d avg=%llf rate=[%llf,%llf] fps=[%llf,%llf] limit=%d\n",target,current,bitrateAcu.GetInstantAvg()/1000,bitrateAcu.GetMinAvg()/1000,bitrateAcu.GetMaxAvg()/1000,fpsAcu.GetMinAvg(),fpsAcu.GetMaxAvg(),videoBitrateLimit);
			bitrateAcu.ResetMinMax();
			fpsAcu.ResetMinMax();
		}
		num++;
	}

	Log("-SendVideo out of loop\n");

	//Terminamos de capturar
	videoInput->StopVideoCapture();

	//Check
	if (videoEncoder)
		//Borramos el encoder
		delete videoEncoder;

	//Salimos
	Log("<SendVideo [%d]\n",sendingVideo);

	return 0;
}
コード例 #20
0
ファイル: rtl_tcp.c プロジェクト: 9nut/rtl-sdr
static void *tcp_worker(void *arg)
{
	struct llist *curelem,*prev;
	int bytesleft,bytessent, index;
	struct timeval tv= {1,0};
	struct timespec ts;
	struct timeval tp;
	fd_set writefds;
	int r = 0;

	while(1) {
		if(do_exit)
			pthread_exit(0);

		pthread_mutex_lock(&ll_mutex);
		gettimeofday(&tp, NULL);
		ts.tv_sec  = tp.tv_sec+5;
		ts.tv_nsec = tp.tv_usec * 1000;
		r = pthread_cond_timedwait(&cond, &ll_mutex, &ts);
		if(r == ETIMEDOUT) {
			pthread_mutex_unlock(&ll_mutex);
			printf("worker cond timeout\n");
			sighandler(0);
			dead[0]=1;
			pthread_exit(NULL);
		}

		curelem = ll_buffers;
		ll_buffers = 0;
		pthread_mutex_unlock(&ll_mutex);

		while(curelem != 0) {
			bytesleft = curelem->len;
			index = 0;
			bytessent = 0;
			while(bytesleft > 0) {
				FD_ZERO(&writefds);
				FD_SET(s, &writefds);
				tv.tv_sec = 1;
				tv.tv_usec = 0;
				r = select(s+1, NULL, &writefds, NULL, &tv);
				if(r) {
					bytessent = send(s,  &curelem->data[index], bytesleft, 0);
					if (bytessent == SOCKET_ERROR) {
                        perror("worker socket error");
						sighandler(0);
						dead[0]=1;
						pthread_exit(NULL);
					} else if (do_exit) {
						printf("do_exit\n");
						dead[0]=1;
						pthread_exit(NULL);
					} else {
						bytesleft -= bytessent;
						index += bytessent;
					}
				} else if(do_exit) {
						printf("worker socket bye\n");
						sighandler(0);
						dead[0]=1;
						pthread_exit(NULL);
				}
			}
			prev = curelem;
			curelem = curelem->next;
			free(prev->data);
			free(prev);
		}
	}
}
コード例 #21
0
ファイル: player.c プロジェクト: igor-sweet/shairport-sync
// get the next frame, when available. return 0 if underrun/stream reset.
static abuf_t *buffer_get_frame(void) {
  int16_t buf_fill;
  uint64_t local_time_now;
  // struct timespec tn;
  abuf_t *abuf = 0;
  int i;
  abuf_t *curframe;

  pthread_mutex_lock(&ab_mutex);
  int wait;
  int32_t dac_delay = 0;
  do {
    // get the time
    local_time_now = get_absolute_time_in_fp();

    // if config.timeout (default 120) seconds have elapsed since the last audio packet was
    // received, then we should stop.
    // config.timeout of zero means don't check..., but iTunes may be confused by a long gap
    // followed by a resumption...

    if ((time_of_last_audio_packet != 0) && (shutdown_requested == 0) &&
        (config.dont_check_timeout == 0)) {
      uint64_t ct = config.timeout; // go from int to 64-bit int
      if ((local_time_now > time_of_last_audio_packet) &&
          (local_time_now - time_of_last_audio_packet >= ct << 32)) {
        debug(1, "As Yeats almost said, \"Too long a silence / can make a stone of the heart\"");
        rtsp_request_shutdown_stream();
        shutdown_requested = 1;
      }
    }
    int rco = get_requested_connection_state_to_output();

    if (connection_state_to_output != rco) {
      connection_state_to_output = rco;
      // change happening
      if (connection_state_to_output == 0) { // going off
        pthread_mutex_lock(&flush_mutex);
        flush_requested = 1;
        pthread_mutex_unlock(&flush_mutex);
      }
    }

    pthread_mutex_lock(&flush_mutex);
    if (flush_requested == 1) {
      if (config.output->flush)
        config.output->flush();
      ab_resync();
      first_packet_timestamp = 0;
      first_packet_time_to_play = 0;
      time_since_play_started = 0;
      flush_requested = 0;
    }
    pthread_mutex_unlock(&flush_mutex);
    uint32_t flush_limit = 0;
    if (ab_synced) {
      do {
        curframe = audio_buffer + BUFIDX(ab_read);
        if (curframe->ready) {

          if (curframe->sequence_number != ab_read) {
            // some kind of sync problem has occurred.
            if (BUFIDX(curframe->sequence_number) == BUFIDX(ab_read)) {
              // it looks like some kind of aliasing has happened
              if (seq_order(ab_read, curframe->sequence_number)) {
                ab_read = curframe->sequence_number;
                debug(1, "Aliasing of buffer index -- reset.");
              }
            } else {
              debug(1, "Inconsistent sequence numbers detected");
            }
          }

          if ((flush_rtp_timestamp != 0) &&
              ((curframe->timestamp == flush_rtp_timestamp) ||
               seq32_order(curframe->timestamp, flush_rtp_timestamp))) {
            debug(1, "Dropping flushed packet seqno %u, timestamp %u", curframe->sequence_number,
                  curframe->timestamp);
            curframe->ready = 0;
            flush_limit++;
            ab_read = SUCCESSOR(ab_read);
          }
          if ((flush_rtp_timestamp != 0) &&
              (!seq32_order(curframe->timestamp,
                            flush_rtp_timestamp))) // if we have gone past the flush boundary time
            flush_rtp_timestamp = 0;
        }
      } while ((flush_rtp_timestamp != 0) && (flush_limit <= 8820) && (curframe->ready == 0));

      if (flush_limit == 8820) {
        debug(1, "Flush hit the 8820 frame limit!");
        flush_limit = 0;
      }

      curframe = audio_buffer + BUFIDX(ab_read);

      if (curframe->ready) {
        if (ab_buffering) { // if we are getting packets but not yet forwarding them to the player
          int have_sent_prefiller_silence; // set true when we have send some silent frames to the DAC
          uint32_t reference_timestamp;
          uint64_t reference_timestamp_time,remote_reference_timestamp_time;
          get_reference_timestamp_stuff(&reference_timestamp, &reference_timestamp_time, &remote_reference_timestamp_time);
          if (first_packet_timestamp == 0) { // if this is the very first packet
            // debug(1,"First frame seen, time %u, with %d
            // frames...",curframe->timestamp,seq_diff(ab_read, ab_write));
            if (reference_timestamp) { // if we have a reference time
              // debug(1,"First frame seen with timestamp...");
              first_packet_timestamp = curframe->timestamp; // we will keep buffering until we are
                                                            // supposed to start playing this
              have_sent_prefiller_silence = 0;

              // Here, calculate when we should start playing. We need to know when to allow the
              // packets to be sent to the player.
              // We will send packets of silence from now until that time and then we will send the
              // first packet, which will be followed by the subsequent packets.

              // we will get a fix every second or so, which will be stored as a pair consisting of
              // the time when the packet with a particular timestamp should be played, neglecting
              // latencies, etc.

              // It probably won't  be the timestamp of our first packet, however, so we might have
              // to do some calculations.

              // To calculate when the first packet will be played, we figure out the exact time the
              // packet should be played according to its timestamp and the reference time.
              // We then need to add the desired latency, typically 88200 frames.

              // Then we need to offset this by the backend latency offset. For example, if we knew
              // that the audio back end has a latency of 100 ms, we would
              // ask for the first packet to be emitted 100 ms earlier than it should, i.e. -4410
              // frames, so that when it got through the audio back end,
              // if would be in sync. To do this, we would give it a latency offset of -100 ms, i.e.
              // -4410 frames.

              int64_t delta = ((int64_t)first_packet_timestamp - (int64_t)reference_timestamp);
              first_packet_time_to_play =
                  reference_timestamp_time +
                  ((delta + (int64_t)config.latency + (int64_t)config.audio_backend_latency_offset)
                   << 32) /
                      44100;

              if (local_time_now >= first_packet_time_to_play) {
                debug(
                    1,
                    "First packet is late! It should have played before now. Flushing 0.1 seconds");
                player_flush(first_packet_timestamp + 4410);
              }
            }
          }

          if (first_packet_time_to_play != 0) {
            // recalculate first_packet_time_to_play -- the latency might change
            int64_t delta = ((int64_t)first_packet_timestamp - (int64_t)reference_timestamp);
            first_packet_time_to_play =
                reference_timestamp_time +
                ((delta + (int64_t)config.latency + (int64_t)config.audio_backend_latency_offset)
                 << 32) /
                    44100;

            uint32_t filler_size = frame_size;
            uint32_t max_dac_delay = 4410;
            filler_size = 4410; // 0.1 second -- the maximum we'll add to the DAC

            if (local_time_now >= first_packet_time_to_play) {
              // we've gone past the time...
              // debug(1,"Run past the exact start time by %llu frames, with time now of %llx, fpttp
              // of %llx and dac_delay of %d and %d packets;
              // flush.",(((tn-first_packet_time_to_play)*44100)>>32)+dac_delay,tn,first_packet_time_to_play,dac_delay,seq_diff(ab_read,
              // ab_write));

              if (config.output->flush)
                config.output->flush();
              ab_resync();
              first_packet_timestamp = 0;
              first_packet_time_to_play = 0;
              time_since_play_started = 0;
            } else {
              if ((config.output->delay) && (have_sent_prefiller_silence != 0)) {
                dac_delay = config.output->delay();
                if (dac_delay == -1) {
                  debug(1, "Error getting dac_delay in buffer_get_frame.");
                  dac_delay = 0;
                }
              } else
                dac_delay = 0;
              uint64_t gross_frame_gap =
                  ((first_packet_time_to_play - local_time_now) * 44100) >> 32;
              int64_t exact_frame_gap = gross_frame_gap - dac_delay;
              if (exact_frame_gap <= 0) {
                // we've gone past the time...
                // debug(1,"Run a bit past the exact start time by %lld frames, with time now of
                // %llx, fpttp of %llx and dac_delay of %d and %d packets;
                // flush.",-exact_frame_gap,tn,first_packet_time_to_play,dac_delay,seq_diff(ab_read,
                // ab_write));
                if (config.output->flush)
                  config.output->flush();
                ab_resync();
                first_packet_timestamp = 0;
                first_packet_time_to_play = 0;
              } else {
                uint32_t fs = filler_size;
                if (fs > (max_dac_delay - dac_delay))
                  fs = max_dac_delay - dac_delay;
                if ((exact_frame_gap <= fs) || (exact_frame_gap <= frame_size * 2)) {
                  fs = exact_frame_gap;
                  // debug(1,"Exact frame gap is %llu; play %d frames of silence. Dac_delay is %d,
                  // with %d packets, ab_read is %04x, ab_write is
                  // %04x.",exact_frame_gap,fs,dac_delay,seq_diff(ab_read,
                  // ab_write),ab_read,ab_write);
                  ab_buffering = 0;
                }
                signed short *silence;
                silence = malloc(FRAME_BYTES(fs));
                memset(silence, 0, FRAME_BYTES(fs));
                // debug(1,"Exact frame gap is %llu; play %d frames of silence. Dac_delay is %d,
                // with %d packets.",exact_frame_gap,fs,dac_delay,seq_diff(ab_read, ab_write));
                config.output->play(silence, fs);
                free(silence);
                have_sent_prefiller_silence = 1;
                if (ab_buffering == 0) {
                  uint64_t reference_timestamp_time; // don't need this...
                  get_reference_timestamp_stuff(&play_segment_reference_frame, &reference_timestamp_time, &play_segment_reference_frame_remote_time);
#ifdef CONFIG_METADATA
                  send_ssnc_metadata('prsm', NULL, 0, 0); // "resume", but don't wait if the queue is locked
#endif
                }
              }
            }
          }
        }
      }
    }

    // Here, we work out whether to release a packet or wait
    // We release a buffer when the time is right.

    // To work out when the time is right, we need to take account of (1) the actual time the packet
    // should be released,
    // (2) the latency requested, (3) the audio backend latency offset and (4) the desired length of
    // the audio backend's buffer

    // The time is right if the current time is later or the same as
    // The packet time + (latency + latency offset - backend_buffer_length).
    // Note: the last three items are expressed in frames and must be converted to time.

    int do_wait = 1;
    if ((ab_synced) && (curframe) && (curframe->ready) && (curframe->timestamp)) {
      uint32_t reference_timestamp;
      uint64_t reference_timestamp_time,remote_reference_timestamp_time;
      get_reference_timestamp_stuff(&reference_timestamp, &reference_timestamp_time, &remote_reference_timestamp_time);
      if (reference_timestamp) { // if we have a reference time
        uint32_t packet_timestamp = curframe->timestamp;
        int64_t delta = ((int64_t)packet_timestamp - (int64_t)reference_timestamp);
        int64_t offset = (int64_t)config.latency + config.audio_backend_latency_offset -
                         (int64_t)config.audio_backend_buffer_desired_length;
        int64_t net_offset = delta + offset;
        int64_t time_to_play = reference_timestamp_time;
        int64_t net_offset_fp_sec;
        if (net_offset >= 0) {
          net_offset_fp_sec = (net_offset << 32) / 44100;
          time_to_play += net_offset_fp_sec; // using the latency requested...
          // debug(2,"Net Offset: %lld, adjusted: %lld.",net_offset,net_offset_fp_sec);
        } else {
          net_offset_fp_sec = ((-net_offset) << 32) / 44100;
          time_to_play -= net_offset_fp_sec;
          // debug(2,"Net Offset: %lld, adjusted: -%lld.",net_offset,net_offset_fp_sec);
        }

        if (local_time_now >= time_to_play) {
          do_wait = 0;
        }
      }
    }
    wait = (ab_buffering || (do_wait != 0) || (!ab_synced)) && (!please_stop);

    if (wait) {
      uint64_t time_to_wait_for_wakeup_fp =
          ((uint64_t)1 << 32) / 44100;       // this is time period of one frame
      time_to_wait_for_wakeup_fp *= 4 * 352; // four full 352-frame packets
      time_to_wait_for_wakeup_fp /= 3; // four thirds of a packet time

#ifdef COMPILE_FOR_LINUX_AND_FREEBSD
      uint64_t time_of_wakeup_fp = local_time_now + time_to_wait_for_wakeup_fp;
      uint64_t sec = time_of_wakeup_fp >> 32;
      uint64_t nsec = ((time_of_wakeup_fp & 0xffffffff) * 1000000000) >> 32;

      struct timespec time_of_wakeup;
      time_of_wakeup.tv_sec = sec;
      time_of_wakeup.tv_nsec = nsec;

      pthread_cond_timedwait(&flowcontrol, &ab_mutex, &time_of_wakeup);
// int rc = pthread_cond_timedwait(&flowcontrol,&ab_mutex,&time_of_wakeup);
// if (rc!=0)
//  debug(1,"pthread_cond_timedwait returned error code %d.",rc);
#endif
#ifdef COMPILE_FOR_OSX
      uint64_t sec = time_to_wait_for_wakeup_fp >> 32;
      ;
      uint64_t nsec = ((time_to_wait_for_wakeup_fp & 0xffffffff) * 1000000000) >> 32;
      struct timespec time_to_wait;
      time_to_wait.tv_sec = sec;
      time_to_wait.tv_nsec = nsec;
      pthread_cond_timedwait_relative_np(&flowcontrol, &ab_mutex, &time_to_wait);
#endif
    }
  } while (wait);
コード例 #22
0
ファイル: mutex.cpp プロジェクト: 1060351485/Gateway_django
int Condition::WaitTimeOut(int timeout){
    struct timespec timer;
    timer.tv_sec = time(0) + timeout;
    timer.tv_nsec = 0;
    return pthread_cond_timedwait(&pcond_, mutex_lock_.GetPthreadMutex(), &timer);
}
コード例 #23
0
ファイル: main.c プロジェクト: 2crazyzgb/tvheadend
static void
mainloop(void)
{
  gtimer_t *gti;
  gti_callback_t *cb;
  struct timespec ts;
#if ENABLE_GTIMER_CHECK
  int64_t mtm;
  const char *id;
  const char *fcn;
#endif

  while(tvheadend_running) {
    dispatch_clock_update(&ts);

    /* Global timers */
    pthread_mutex_lock(&global_lock);

    // TODO: there is a risk that if timers re-insert themselves to
    //       the top of the list with a 0 offset we could loop indefinitely
    
#if 0
    tvhdebug("gtimer", "now %ld.%09ld", ts.tv_sec, ts.tv_nsec);
    LIST_FOREACH(gti, &gtimers, gti_link)
      tvhdebug("gtimer", "  gti %p expire %ld.%08ld",
               gti, gti->gti_expire.tv_sec, gti->gti_expire.tv_nsec);
#endif

    while((gti = LIST_FIRST(&gtimers)) != NULL) {
      
      if ((gti->gti_expire.tv_sec > ts.tv_sec) ||
          ((gti->gti_expire.tv_sec == ts.tv_sec) &&
           (gti->gti_expire.tv_nsec > ts.tv_nsec))) {
        ts = gti->gti_expire;
        break;
      }

#if ENABLE_GTIMER_CHECK
      mtm = getmonoclock();
      id = gti->gti_id;
      fcn = gti->gti_fcn;
#endif
      cb = gti->gti_callback;

      LIST_REMOVE(gti, gti_link);
      gti->gti_callback = NULL;

      cb(gti->gti_opaque);

#if ENABLE_GTIMER_CHECK
      tvhtrace("gtimer", "%s:%s duration %"PRId64"ns", id, fcn, getmonoclock() - mtm);
#endif
    }

    /* Bound wait */
    if ((LIST_FIRST(&gtimers) == NULL) || (ts.tv_sec > (dispatch_clock + 1))) {
      ts.tv_sec  = dispatch_clock + 1;
      ts.tv_nsec = 0;
    }

    /* Wait */
    pthread_cond_timedwait(&gtimer_cond, &global_lock, &ts);
    pthread_mutex_unlock(&global_lock);
  }
}
コード例 #24
0
ファイル: mutex.c プロジェクト: apprisi/foundation_lib
bool mutex_wait( mutex_t* mutex, unsigned int timeout )
{
#if FOUNDATION_PLATFORM_WINDOWS
	DWORD ret;
#elif FOUNDATION_PLATFORM_POSIX
	struct timeval now;
	struct timespec then;
#endif	
	FOUNDATION_ASSERT( mutex );
#if FOUNDATION_PLATFORM_WINDOWS

#if !BUILD_DEPLOY
	profile_wait( mutex->name );
#endif

	atomic_incr32( &mutex->waiting );

	ret = WaitForSingleObject( mutex->event, ( timeout == 0 ) ? INFINITE : timeout );

	if( ret == WAIT_OBJECT_0 )
		mutex_lock( mutex );
	
	if( atomic_decr32( &mutex->waiting ) == 0 )
		ResetEvent( mutex->event );

	return ret == WAIT_OBJECT_0;

#elif FOUNDATION_PLATFORM_POSIX
	
	mutex_lock( mutex );
	
	if( mutex->pending )
	{
		mutex->pending = false;
		return true;
	}

	--mutex->lockcount;
	
	bool was_signal = false;
	if( !timeout )
	{
		int ret = pthread_cond_wait( &mutex->cond, &mutex->mutex );
		if( ret == 0 )
		{
			was_signal = true;
		}
		else
		{
			log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to wait on mutex '%s': %s (%d)", mutex->name, system_error_message( ret ), ret );
		}
	}
	else
	{
		int ret;
		gettimeofday( &now, 0 );
		then.tv_sec  = now.tv_sec + ( timeout / 1000 );
		then.tv_nsec = ( now.tv_usec * 1000 ) + (long)( timeout % 1000 ) * 1000000L;
		while( then.tv_nsec > 999999999 )
		{
			++then.tv_sec;
			then.tv_nsec -= 1000000000L;
		}
		ret = pthread_cond_timedwait( &mutex->cond, &mutex->mutex, &then );
		if( ret == 0 )
		{
			was_signal = true;
		}
		else if( ret != ETIMEDOUT )
		{
			log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to wait (timed) on mutex '%s': %s (%d)", mutex->name, system_error_message( ret ), ret );
		}
	}

	++mutex->lockcount;
	mutex->lockedthread = thread_id();
	
	if( was_signal )
		mutex->pending = false;
	else
		mutex_unlock( mutex );
	
	return was_signal;

#else
#  error mutex_wait not implemented
#endif
}
コード例 #25
0
ファイル: dapl_osd.c プロジェクト: Cai900205/test
DAT_RETURN
dapl_os_wait_object_wait(IN DAPL_OS_WAIT_OBJECT * wait_obj,
			 IN DAT_TIMEOUT timeout_val)
{
	DAT_RETURN dat_status;
	int pthread_status;
	struct timespec future;

	dat_status = DAT_SUCCESS;
	pthread_status = 0;

	if (timeout_val != DAT_TIMEOUT_INFINITE) {
		struct timeval now;
		struct timezone tz;
		unsigned int microsecs;

		gettimeofday(&now, &tz);
#define USEC_PER_SEC 1000000
		microsecs = now.tv_usec + timeout_val;
		now.tv_sec = now.tv_sec + microsecs / USEC_PER_SEC;
		now.tv_usec = microsecs % USEC_PER_SEC;

		/* Convert timeval to timespec */
		future.tv_sec = now.tv_sec;
		future.tv_nsec = now.tv_usec * 1000;

		pthread_mutex_lock(&wait_obj->lock);
		while (wait_obj->signaled == DAT_FALSE && pthread_status == 0) {
			pthread_status =
			    pthread_cond_timedwait(&wait_obj->cv,
						   &wait_obj->lock, &future);

			/*
			 * No need to reset &future if we go around the loop;
			 * It's an absolute time.
			 */
		}
		/* Reset the signaled status if we were woken up.  */
		if (pthread_status == 0) {
			wait_obj->signaled = DAT_FALSE;
		}
		pthread_mutex_unlock(&wait_obj->lock);
	} else {
		pthread_mutex_lock(&wait_obj->lock);
		while (wait_obj->signaled == DAT_FALSE && pthread_status == 0) {
			pthread_status =
			    pthread_cond_wait(&wait_obj->cv, &wait_obj->lock);
		}
		/* Reset the signaled status if we were woken up.  */
		if (pthread_status == 0) {
			wait_obj->signaled = DAT_FALSE;
		}
		pthread_mutex_unlock(&wait_obj->lock);
	}

	if (ETIMEDOUT == pthread_status) {
		dat_status = DAT_ERROR(DAT_TIMEOUT_EXPIRED, 0);
	} else if (EINTR == pthread_status) {
		dat_status = DAT_ERROR(DAT_INTERRUPTED_CALL, 0);
	} else if (0 != pthread_status) {
		dat_status = DAT_ERROR(DAT_INTERNAL_ERROR, 0);
	}

	return dat_status;
}
コード例 #26
0
ファイル: main.cpp プロジェクト: MagicPrince666/v4l2_x264
void
*video_Capture_Thread(void *arg)
{
	compress_begin(&en, cam->width, cam->height);//初始化编码器

	int i=0;

	//unsigned char *data;

	int len=framelength;
	
	struct timeval now;

	struct timespec outtime;

	while(1)
	{
		usleep(DelayTime);

		gettimeofday(&now, NULL);

		outtime.tv_sec =now.tv_sec;

		outtime.tv_nsec =DelayTime * 1000;

		pthread_mutex_lock(&(Buff[i].lock)); /*获取互斥锁,锁定当前缓冲区*/
		if(i)   printf("----video_Capture_Thread Buff 1\n");
		if(!i)   printf("----video_Capture_Thread Buff 0\n");

		while((Buff[i].wpos + len)%BUF_SIZE==Buff[i].rpos && Buff[i].rpos != 0) /*等待缓存区处理操作完成*/
		{
			printf("***********video_Capture_Thread ************阻塞\n");
			//pthread_cond_wait(&(Buff[i].encodeOK),&(Buff[i].lock));
			pthread_cond_timedwait(&(Buff[i].encodeOK),&(Buff[i].lock),&outtime);
		}


		if(buffOneFrame(&Buff[i] , cam))//采集一帧数据
		{

			pthread_cond_signal(&(Buff[i].captureOK)); /*设置状态信号*/

			pthread_mutex_unlock(&(Buff[i].lock)); /*释放互斥锁*/
			//convert_yuv_to_rgb_buffer();

			flag[i]=1;//缓冲区i已满

			Buff[i].rpos=0;

			i=!i;	//切换到另一个缓冲区
			
			Buff[i].wpos=0;

			flag[i]=0;//缓冲区i为空


		}

		pthread_cond_signal(&(Buff[i].captureOK)); /*设置状态信号*/

		pthread_mutex_unlock(&(Buff[i].lock)); /*释放互斥锁*/
	}
}
コード例 #27
0
/* cf_queue_pop
 * if ms_wait < 0, wait forever
 * if ms_wait = 0, don't wait at all
 * if ms_wait > 0, wait that number of ms
 * */
int cf_queue_pop(cf_queue *q, void *buf, int ms_wait) {
	if (NULL == q) {
		cf_error("cf_queue_pop: try passing in a queue");
		return(-1);
	}

#ifdef EXTERNAL_LOCKS 
	if (ms_wait != CF_QUEUE_NOWAIT) {   // this implementation won't wait
		cf_error("cf_queue_pop: only nowait supported");
		return(-1);
	}
#endif // EXTERNAL_LOCKS

	QUEUE_LOCK(q);

	struct timespec tp;
	if (ms_wait > 0) {
#ifdef OSX
		uint64_t curms = cf_getms(); // using the cl generic functions defined in cf_clock.h. It is going to have slightly less resolution than the pure linux version
		tp.tv_sec = (curms + ms_wait)/1000;
		tp.tv_nsec = (ms_wait %1000) * 1000000;
#else // linux
		clock_gettime( CLOCK_REALTIME, &tp); 
		tp.tv_sec += ms_wait / 1000;
		tp.tv_nsec += (ms_wait % 1000) * 1000000;
		if (tp.tv_nsec > 1000000000) {
			tp.tv_nsec -= 1000000000;
			tp.tv_sec++;
		}
#endif
	}

	/* FIXME error checking */
	/* Note that we apparently have to use a while() loop.  Careful reading
	 * of the pthread_cond_signal() documentation says that AT LEAST ONE
	 * waiting thread will be awakened... */
	if (q->threadsafe) {
#ifdef EXTERNAL_LOCKS
		if (CF_Q_EMPTY(q)) {
			QUEUE_UNLOCK(q);
			return(CF_QUEUE_EMPTY);
		}
#else
		while (CF_Q_EMPTY(q)) {
			if (CF_QUEUE_FOREVER == ms_wait) {
				pthread_cond_wait(&q->CV, &q->LOCK);
			}
			else if (CF_QUEUE_NOWAIT == ms_wait) {
				pthread_mutex_unlock(&q->LOCK);
				return(CF_QUEUE_EMPTY);
			}
			else {
				pthread_cond_timedwait(&q->CV, &q->LOCK, &tp);
				if (CF_Q_EMPTY(q)) {
					pthread_mutex_unlock(&q->LOCK);
					return(CF_QUEUE_EMPTY);
				}
			}
		}
#endif // EXTERNAL_LOCKS
	} else if (CF_Q_EMPTY(q))
		return(CF_QUEUE_EMPTY);

	memcpy(buf, CF_Q_ELEM_PTR(q,q->read_offset), q->elementsz);
	q->read_offset++;
	
	// interesting idea - this probably keeps the cache fresher
	// because the queue is fully empty just make it all zero
	if (q->read_offset == q->write_offset) {
		q->read_offset = q->write_offset = 0;
	}

	QUEUE_UNLOCK(q);

	return(0);
}
コード例 #28
0
ファイル: 2-3.c プロジェクト: jiezh/h5vcc
/* Child function (either in a thread or in a process) */
void * child(void * arg)
{
	int ret=0;
	int timed;
	struct timespec ts;
	
	/* lock the mutex */
	ret = pthread_mutex_lock(&td->mtx);
	if (ret != 0)  {  UNRESOLVED(ret, "Failed to lock mutex in child");  }
	
	/* increment count */
	td->count++;
	timed=td->count & 1;
	
	if (timed)
	{
	/* get current time if we are a timedwait */
		struct timeval now;
		ret = gettimeofday(&now, NULL);
		if (ret != 0)  {  UNRESOLVED(errno, "Unable to read clock");  }
		ts.tv_sec = now.tv_sec + TIMEOUT;
		ts.tv_nsec = now.tv_usec * 1000;
	}
	
	do {
	/* Wait while the predicate is false */
		if (timed)
			ret = pthread_cond_timedwait(&td->cnd, &td->mtx, &ts);
		else
			ret = pthread_cond_wait(&td->cnd, &td->mtx);
		#if VERBOSE > 5
		output("[child] Wokenup timed=%i, Predicate=%i, ret=%i\n", timed, td->predicate, ret);
		#endif
	} while ((ret == 0) && (td->predicate==0));
	if (ret == ETIMEDOUT)
	{
		FAILED("Timeout occured. This means a cond signal was lost -- or parent died");
	}
	if (ret != 0)  {  UNRESOLVED(ret, "Failed to wait for the cond");  }
	
	/* Check that we are owning the mutex */
	#ifdef WITHOUT_XOPEN
	ret = pthread_mutex_trylock(&(td->mtx));
	if (ret == 0)  {  FAILED("The mutex was not owned after return from condition waiting");  }
	#else
	if (td->mtype == PTHREAD_MUTEX_RECURSIVE)
	{
		ret = pthread_mutex_trylock(&(td->mtx));
		if (ret != 0)  {  FAILED("Unable to relock recursive mutex: not owning?");  }
		ret = pthread_mutex_unlock(&(td->mtx));
		if (ret != 0)  {  UNRESOLVED(ret, "Failed to unlock the mutex");  }
	}
	if (td->mtype == PTHREAD_MUTEX_ERRORCHECK)
	{
		ret = pthread_mutex_lock(&(td->mtx));
		if (ret == 0)  {  FAILED("Was able to lock errorcheck mutex: the mutex was not acquired once already?");  }
	}
	#endif
	
	
	/* unlock the mutex */
	ret = pthread_mutex_unlock(&td->mtx);
	if (ret != 0)  {  UNRESOLVED(ret, "Failed to unlock the mutex.");  }
	
	return NULL;
}
コード例 #29
0
static void
cl_get_changes_create_test(void **state)
{
    sr_conn_ctx_t *conn = *state;
    assert_non_null(conn);
    sr_session_ctx_t *session = NULL;
    sr_subscription_ctx_t *subscription = NULL;
    changes_t changes = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cv = PTHREAD_COND_INITIALIZER, 0};
    struct timespec ts;

    sr_val_t *val = NULL;
    const char *xpath = NULL;
    int rc = SR_ERR_OK;
    xpath = "/example-module:container/list[key1='abc'][key2='def']";

    /* start session */
    rc = sr_session_start(conn, SR_DS_CANDIDATE, SR_SESS_DEFAULT, &session);
    assert_int_equal(rc, SR_ERR_OK);

    rc = sr_module_change_subscribe(session, "example-module", list_changes_cb, &changes,
            0, SR_SUBSCR_DEFAULT, &subscription);
    assert_int_equal(rc, SR_ERR_OK);

    /* check the list presence in candidate */
    rc = sr_get_item(session, xpath, &val);
    assert_int_equal(rc, SR_ERR_NOT_FOUND);


    /* create the list instance */
    rc = sr_set_item(session, xpath, NULL, SR_EDIT_DEFAULT);
    assert_int_equal(rc, SR_ERR_OK);

    /* save changes to running */
    pthread_mutex_lock(&changes.mutex);
    rc = sr_commit(session);
    assert_int_equal(rc, SR_ERR_OK);

    sr_clock_get_time(CLOCK_REALTIME, &ts);
    ts.tv_sec += COND_WAIT_SEC;
    pthread_cond_timedwait(&changes.cv, &changes.mutex, &ts);

    assert_int_equal(changes.cnt, 3);
    assert_int_equal(changes.oper[0], SR_OP_CREATED);
    assert_non_null(changes.new_values[0]);
    assert_null(changes.old_values[0]);
    assert_string_equal(xpath, changes.new_values[0]->xpath);

    assert_int_equal(changes.oper[1], SR_OP_CREATED);
    assert_non_null(changes.new_values[1]);
    assert_null(changes.old_values[1]);
    assert_string_equal("/example-module:container/list[key1='abc'][key2='def']/key1", changes.new_values[1]->xpath);

    assert_int_equal(changes.oper[2], SR_OP_CREATED);
    assert_non_null(changes.new_values[2]);
    assert_null(changes.old_values[2]);
    assert_string_equal("/example-module:container/list[key1='abc'][key2='def']/key2", changes.new_values[2]->xpath);


    for (size_t i = 0; i < changes.cnt; i++) {
        sr_free_val(changes.new_values[i]);
        sr_free_val(changes.old_values[i]);
    }

    pthread_mutex_unlock(&changes.mutex);

    rc = sr_unsubscribe(NULL, subscription);
    assert_int_equal(rc, SR_ERR_OK);

    rc = sr_session_stop(session);
    assert_int_equal(rc, SR_ERR_OK);
}

static void
cl_get_changes_modified_test(void **state)
{
    sr_conn_ctx_t *conn = *state;
    assert_non_null(conn);
    sr_session_ctx_t *session = NULL;
    sr_subscription_ctx_t *subscription = NULL;
    changes_t changes = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cv = PTHREAD_COND_INITIALIZER, 0};
    struct timespec ts;

    sr_val_t *val = NULL;
    const char *xpath = NULL;
    int rc = SR_ERR_OK;
    xpath = "/example-module:container/list[key1='key1'][key2='key2']/leaf";

    /* start session */
    rc = sr_session_start(conn, SR_DS_CANDIDATE, SR_SESS_DEFAULT, &session);
    assert_int_equal(rc, SR_ERR_OK);

    rc = sr_module_change_subscribe(session, "example-module", list_changes_cb, &changes,
            0, SR_SUBSCR_DEFAULT, &subscription);
    assert_int_equal(rc, SR_ERR_OK);

    /* check the list presence in candidate */
    rc = sr_get_item(session, xpath, &val);
    assert_int_equal(rc, SR_ERR_OK);

    sr_val_t new_val = {0};
    new_val.type = SR_STRING_T;
    new_val.data.string_val = "abcdef";

    /* create the list instance */
    rc = sr_set_item(session, xpath, &new_val, SR_EDIT_DEFAULT);
    assert_int_equal(rc, SR_ERR_OK);

    /* save changes to running */
    pthread_mutex_lock(&changes.mutex);
    rc = sr_commit(session);
    assert_int_equal(rc, SR_ERR_OK);

    sr_clock_get_time(CLOCK_REALTIME, &ts);
    ts.tv_sec += COND_WAIT_SEC;
    pthread_cond_timedwait(&changes.cv, &changes.mutex, &ts);

    assert_int_equal(changes.cnt, 1);
    assert_int_equal(changes.oper[0], SR_OP_MODIFIED);
    assert_non_null(changes.new_values[0]);
    assert_non_null(changes.old_values[0]);
    assert_string_equal(val->data.string_val, changes.old_values[0]->data.string_val);
    assert_string_equal(new_val.data.string_val, changes.new_values[0]->data.string_val);

    for (size_t i = 0; i < changes.cnt; i++) {
        sr_free_val(changes.new_values[i]);
        sr_free_val(changes.old_values[i]);
    }

    sr_free_val(val);
    pthread_mutex_unlock(&changes.mutex);

    rc = sr_unsubscribe(NULL, subscription);
    assert_int_equal(rc, SR_ERR_OK);

    rc = sr_session_stop(session);
    assert_int_equal(rc, SR_ERR_OK);
}

static void
cl_get_changes_deleted_test(void **state)
{
    sr_conn_ctx_t *conn = *state;
    assert_non_null(conn);
    sr_session_ctx_t *session = NULL;
    sr_subscription_ctx_t *subscription = NULL;
    changes_t changes = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cv = PTHREAD_COND_INITIALIZER, 0};
    struct timespec ts;

    sr_val_t *val = NULL;
    const char *xpath = NULL;
    int rc = SR_ERR_OK;
    xpath = "/example-module:container";

    /* start session */
    rc = sr_session_start(conn, SR_DS_CANDIDATE, SR_SESS_DEFAULT, &session);
    assert_int_equal(rc, SR_ERR_OK);

    rc = sr_module_change_subscribe(session, "example-module", list_changes_cb, &changes,
            0, SR_SUBSCR_DEFAULT, &subscription);
    assert_int_equal(rc, SR_ERR_OK);

    /* check the list presence in candidate */
    rc = sr_get_item(session, xpath, &val);
    assert_int_equal(rc, SR_ERR_OK);
    sr_free_val(val);

    /* delete container */
    rc = sr_delete_item(session, xpath, SR_EDIT_DEFAULT);
    assert_int_equal(rc, SR_ERR_OK);

    /* save changes to running */
    pthread_mutex_lock(&changes.mutex);
    rc = sr_commit(session);
    assert_int_equal(rc, SR_ERR_OK);

    sr_clock_get_time(CLOCK_REALTIME, &ts);
    ts.tv_sec += COND_WAIT_SEC;
    pthread_cond_timedwait(&changes.cv, &changes.mutex, &ts);

    assert_int_equal(changes.cnt, 5);
    assert_int_equal(changes.oper[0], SR_OP_DELETED);
    assert_null(changes.new_values[0]);
    assert_non_null(changes.old_values[0]);
    assert_string_equal(xpath, changes.old_values[0]->xpath);

    assert_int_equal(changes.oper[1], SR_OP_DELETED);
    assert_null(changes.new_values[1]);
    assert_non_null(changes.old_values[1]);
    assert_string_equal("/example-module:container/list[key1='key1'][key2='key2']", changes.old_values[1]->xpath);

    assert_int_equal(changes.oper[2], SR_OP_DELETED);
    assert_null(changes.new_values[2]);
    assert_non_null(changes.old_values[2]);
    assert_string_equal("/example-module:container/list[key1='key1'][key2='key2']/key1", changes.old_values[2]->xpath);

    assert_int_equal(changes.oper[3], SR_OP_DELETED);
    assert_null(changes.new_values[3]);
    assert_non_null(changes.old_values[3]);
    assert_string_equal("/example-module:container/list[key1='key1'][key2='key2']/key2", changes.old_values[3]->xpath);

    assert_int_equal(changes.oper[4], SR_OP_DELETED);
    assert_null(changes.new_values[4]);
    assert_non_null(changes.old_values[4]);
    assert_string_equal("/example-module:container/list[key1='key1'][key2='key2']/leaf", changes.old_values[4]->xpath);

    for (size_t i = 0; i < changes.cnt; i++) {
        sr_free_val(changes.new_values[i]);
        sr_free_val(changes.old_values[i]);
    }
    pthread_mutex_unlock(&changes.mutex);

    rc = sr_unsubscribe(NULL, subscription);
    assert_int_equal(rc, SR_ERR_OK);

    rc = sr_session_stop(session);
    assert_int_equal(rc, SR_ERR_OK);
}

static void
cl_get_changes_moved_test(void **state)
{
    sr_conn_ctx_t *conn = *state;
    assert_non_null(conn);
    sr_session_ctx_t *session = NULL;
    sr_subscription_ctx_t *subscription = NULL;
    changes_t changes = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cv = PTHREAD_COND_INITIALIZER, 0};
    struct timespec ts;

    const char *xpath = NULL;
    int rc = SR_ERR_OK;
    xpath = "/test-module:ordered-numbers";

    /* start session */
    rc = sr_session_start(conn, SR_DS_STARTUP, SR_SESS_DEFAULT, &session);
    assert_int_equal(rc, SR_ERR_OK);

    sr_val_t v = {0};
    v.type = SR_UINT8_T;
    v.data.uint8_val = 1;
    /* create user ordered leaf-list instance */
    rc = sr_set_item(session, xpath, &v, SR_EDIT_STRICT);
    assert_int_equal(rc, SR_ERR_OK);

    v.data.uint8_val = 2;
    rc = sr_set_item(session, xpath, &v, SR_EDIT_STRICT);
    assert_int_equal(rc, SR_ERR_OK);

    v.data.uint8_val = 3;
    rc = sr_set_item(session, xpath, &v, SR_EDIT_STRICT);
    assert_int_equal(rc, SR_ERR_OK);

    /* save changes to running */
    rc = sr_commit(session);
    assert_int_equal(rc, SR_ERR_OK);

    rc = sr_session_switch_ds(session, SR_DS_CANDIDATE);
    assert_int_equal(rc, SR_ERR_OK);

    rc = sr_module_change_subscribe(session, "test-module", list_changes_cb, &changes,
            0, SR_SUBSCR_DEFAULT, &subscription);
    assert_int_equal(rc, SR_ERR_OK);

    /* move leaf-list */
    rc = sr_move_item(session, "/test-module:ordered-numbers[.='3']", SR_MOVE_AFTER, "/test-module:ordered-numbers[.='1']");
    assert_int_equal(rc, SR_ERR_OK);

    /* save changes to running */
    pthread_mutex_lock(&changes.mutex);
    rc = sr_commit(session);
    assert_int_equal(rc, SR_ERR_OK);

    sr_clock_get_time(CLOCK_REALTIME, &ts);
    ts.tv_sec += COND_WAIT_SEC;
    pthread_cond_timedwait(&changes.cv, &changes.mutex, &ts);

    assert_int_equal(changes.cnt, 1);
    assert_int_equal(changes.oper[0], SR_OP_MOVED);
    assert_non_null(changes.new_values[0]);
    assert_non_null(changes.old_values[0]);
    assert_string_equal(xpath, changes.old_values[0]->xpath);
    assert_int_equal(changes.new_values[0]->data.uint8_val, 2);
    assert_int_equal(changes.old_values[0]->data.uint8_val, 3);

    for (size_t i = 0; i < changes.cnt; i++) {
        sr_free_val(changes.new_values[i]);
        sr_free_val(changes.old_values[i]);
    }
    pthread_mutex_unlock(&changes.mutex);

    rc = sr_unsubscribe(NULL, subscription);
    assert_int_equal(rc, SR_ERR_OK);

    rc = sr_session_stop(session);
    assert_int_equal(rc, SR_ERR_OK);

}

typedef struct priority_s {
    int count;
    int cb[3];
}priority_t;

static int
priority_zero_cb(sr_session_ctx_t *session, const char *module_name, sr_notif_event_t ev, void *private_ctx)
{
    priority_t *pr = (priority_t *) private_ctx;
    pr->cb[pr->count] = 0;
    pr->count++;

    return SR_ERR_OK;
}
コード例 #30
0
XnStatus XnLinuxPosixEvent::Wait(XnUInt32 nMilliseconds)
{
	XnStatus nRetVal = XN_STATUS_OK;

	struct timespec time = {0};
	if (nMilliseconds != XN_WAIT_INFINITE)
	{
		nRetVal = xnOSGetAbsTimeout(&time, nMilliseconds);
		if (nRetVal != XN_STATUS_OK)
		{
			return XN_STATUS_OS_EVENT_WAIT_FAILED;
		}
	}

	// lock the mutex
	if (0 != pthread_mutex_lock(&m_mutex))
	{
		return (XN_STATUS_OS_EVENT_WAIT_FAILED);
	}

	// wait for the condition to become signaled (or a failure)
	int rc;
	while (nRetVal == XN_STATUS_OK && !m_bSignaled)
	{
		if (nMilliseconds != XN_WAIT_INFINITE)
		{
			rc = pthread_cond_timedwait(&m_cond, &m_mutex, &time);
		}
		else // infinite
		{
			rc = pthread_cond_wait(&m_cond, &m_mutex);
		}

		if (rc == ETIMEDOUT)
		{
			nRetVal = XN_STATUS_OS_EVENT_TIMEOUT;
		}
		else if (rc != 0)
		{
			nRetVal = XN_STATUS_OS_EVENT_WAIT_FAILED;
		}
	}

	// check all went well
	if (nRetVal != XN_STATUS_OK)
	{
		pthread_mutex_unlock(&m_mutex);
		return nRetVal;	
	}

	if (!m_bManualReset)
	{
		// auto-reset the event
		m_bSignaled = FALSE;
	}

	// unlock the mutex
	if (0 != pthread_mutex_unlock(&m_mutex))
	{
		return (XN_STATUS_OS_EVENT_WAIT_FAILED);
	}

	return (XN_STATUS_OK);
}