/* * 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 } }
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; }
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; }
/* * 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(); } }
/* * 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; }
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++; }
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; }
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; }
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; }
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); }
// 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; }
/** * 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; }
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; }
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; }
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; }
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; }
/** * 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; }
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(); }
/******************************************* * 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; }
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); } } }
// 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);
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); }
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, >imers, 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(>imers)) != 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(>imers) == NULL) || (ts.tv_sec > (dispatch_clock + 1))) { ts.tv_sec = dispatch_clock + 1; ts.tv_nsec = 0; } /* Wait */ pthread_cond_timedwait(>imer_cond, &global_lock, &ts); pthread_mutex_unlock(&global_lock); } }
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 }
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; }
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)); /*释放互斥锁*/ } }
/* 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); }
/* 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; }
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; }
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); }