Пример #1
0
static void *attempt_thread(void *data)
{
	struct outgoing *o = data;
	int res, reason;
	if (!ast_strlen_zero(o->app)) {
		if (option_verbose > 2)
			ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
		res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
	} else {
		if (option_verbose > 2)
			ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
		res = ast_pbx_outgoing_exten(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
	}
	if (res) {
		ast_log(LOG_NOTICE, "Call failed to go through, reason %d\n", reason);
		if (o->retries >= o->maxretries + 1) {
			/* Max retries exceeded */
			ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
			remove_from_queue(o, "Expired");
		} else {
			/* Notate that the call is still active */
			safe_append(o, time(NULL), "EndRetry");
		}
	} else {
		ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
		ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
		remove_from_queue(o, "Completed");
	}
	free_outgoing(o);
	return NULL;
}
Пример #2
0
static int scan_service(char *fn, time_t now, time_t atime)
{
	struct outgoing *o;
	FILE *f;
	o = malloc(sizeof(struct outgoing));
	if (o) {
		init_outgoing(o);
		f = fopen(fn, "r+");
		if (f) {
			if (!apply_outgoing(o, fn, f)) {
#if 0
				printf("Filename: %s, Retries: %d, max: %d\n", fn, o->retries, o->maxretries);
#endif
				fclose(f);
				if (o->retries <= o->maxretries) {
					now += o->retrytime;
					if (o->callingpid && (o->callingpid == ast_mainpid)) {
						safe_append(o, time(NULL), "DelayedRetry");
						ast_log(LOG_DEBUG, "Delaying retry since we're currently running '%s'\n", o->fn);
						free_outgoing(o);
					} else {
						/* Increment retries */
						o->retries++;
						/* If someone else was calling, they're presumably gone now
						   so abort their retry and continue as we were... */
						if (o->callingpid)
							safe_append(o, time(NULL), "AbortRetry");

						safe_append(o, now, "StartRetry");
						launch_service(o);
					}
					return now;
				} else {
					ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
					free_outgoing(o);
					remove_from_queue(o, "Expired");
					return 0;
				}
			} else {
				free_outgoing(o);
				ast_log(LOG_WARNING, "Invalid file contents in %s, deleting\n", fn);
				fclose(f);
				remove_from_queue(o, "Failed");
			}
		} else {
			free_outgoing(o);
			ast_log(LOG_WARNING, "Unable to open %s: %s, deleting\n", fn, strerror(errno));
			remove_from_queue(o, "Failed");
		}
	} else
		ast_log(LOG_WARNING, "Out of memory :(\n");
	return -1;
}
Пример #3
0
// Give up the CPU for one scheduling round.
void
yield(void)
{
  //cprintf("yield...\n");
  acquire(&ptable.lock);  //DOC: yieldlock
  proc->state = RUNNABLE;
  // Loop thru pstat.pid to find the slot number in ptable.
  int slot_no;  // slot idx
  for (slot_no = 0; slot_no < NPROC; ++slot_no) 
    if (proc_stat.pid[slot_no] == proc->pid) break;
  //assert(i < NPROC);
  if (slot_no == NPROC)
    cprintf("slot_no == NPROC\n");
  int pri = proc_stat.priority[slot_no];
  ++proc_stat.ticks[slot_no][pri];
  //cprintf("pid: %d have used %d timerticks.\n",
	  //proc->pid, proc_stat.ticks[slot_no][pri]);
  // Updates priority queues here.
  if (proc_stat.ticks[slot_no][pri] == tick_bounds(pri) ||
      (pri == 3 && proc_stat.ticks[slot_no][pri] % 8 == 0)) {
    switch (pri) {
      case 0:
	//cprintf("pri 0 to pri 1.\n");
	remove_from_queue(&q0_head, &q0_tail, proc);
	append_to_queue(&q1_head, &q1_tail, proc);
	proc_stat.priority[slot_no] = 1;
	break;
      case 1:
	//cprintf("pri 1 to pri 2.\n");
	remove_from_queue(&q1_head, &q1_tail, proc);
	append_to_queue(&q2_head, &q2_tail, proc);
	proc_stat.priority[slot_no] = 2;
	break;
      case 2:
	//cprintf("pri 2 to pri 3.\n");
	remove_from_queue(&q2_head, &q2_tail, proc);
	append_to_queue(&q3_head, &q3_tail, proc);
	proc_stat.priority[slot_no] = 3;
	break;
      case 3:
	// RR
	//cprintf("RR here.\n");
	remove_from_queue(&q3_head, &q3_tail, proc);
	append_to_queue(&q3_head, &q3_tail, proc);
	break;
      default:
	cprintf("Wrong priority.\n");
    }
  }
  sched();
  release(&ptable.lock);
}
Пример #4
0
/* Go through the pending queue for the indicated semaphore
 * looking for tasks that can be completed.
 */
static void update_queue (struct sem_array * sma)
{
	int error;
	struct sem_queue * q;

	for (q = sma->sem_pending; q; q = q->next) {
			
		if (q->status == 1)
			continue;	/* this one was woken up before */

		error = try_atomic_semop(sma, q->sops, q->nsops,
					 q->undo, q->pid, q->alter);

		/* Does q->sleeper still need to sleep? */
		if (error <= 0) {
				/* Found one, wake it up */
			wake_up_process(q->sleeper);
			if (error == 0 && q->alter) {
				/* if q-> alter let it self try */
				q->status = 1;
				return;
			}
			q->status = error;
			remove_from_queue(sma,q);
		}
	}
}
Пример #5
0
int setpriority(int pid,int new_priority){

  struct proc *p;
  int found = -1;

  acquire(&ptable.lock);

  // Scan through table looking for the process with the specified pid
  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
      if(p->pid == pid){
	  
		 acquire(&runqueue.lock);
		 remove_from_queue( p->pid, p->priority );
		 cprintf("set priority of proc %d from %d to %d\n", p->pid,p->priority, new_priority); 
		 p->priority = new_priority;
		 	
         release(&runqueue.lock);
		  
		 found = 0;
		 break; 
	  }
  }      	  
  
  release(&ptable.lock); 
  
  return found;
  
}
Пример #6
0
/* Go through the pending queue for the indicated semaphore
 * looking for tasks that can be completed.
 */
static void update_queue (struct semid_ds * sma)
{
	int error;
	struct sem_queue * q;

        for (q = sma->sem_pending; q; q = q->next) {
                        
                if (q->status == 1)
                        return; /* wait for other process */

                error = try_atomic_semop(sma, q->sops, q->nsops,
                                         q->undo, q->pid, q->alter);

                /* Does q->sleeper still need to sleep? */
                if (error <= 0) {
                                /* Found one, wake it up */
                        wake_up_interruptible(&q->sleeper);
                        if (error == 0 && q->alter) {
                                /* if q-> alter let it self try */
                                q->status = 1;
                                return;
                        }
                        q->status = error;
                        remove_from_queue(sma,q);
                }
        }
}
//Given a queue try to pull some items off
//Let's abuse the things we were given
//Use the queue as a list, order doesn't matter. Why rewrite code;
//Return queue of strings, and the number of items in there
queue_t * get_items(queue_t * queue, unsigned int num_items, unsigned int * num_returned)
{
	//Allocate a queue
	queue_t * ret_queue = create_queue();
	
	//Remove elements until reaching null or the number requested
	*num_returned = 0;
	#pragma omp critical
	{
		while(1)
		{
			//Try to remove an item
			queue_element_t * item = remove_from_queue(queue);
			if(item == NULL)
			{
				break;
			}
			
			//Add this item to the queue
			insert_in_queue(ret_queue, item);
			*num_returned = *num_returned +1;
			
			if(*num_returned >=num_items)
			{
				break;
			}
		}
	}
	
	
	//printf("Got %u/%u from queue\n", *num_returned, num_items);
	
	return ret_queue;
}
Пример #8
0
uint64_t syscall_kill(int32_t option, int32_t pid)
{
    if (pid == 0 || pid == 1) {
        printf("-sbush: kill(%d): Not allowed\n", pid);
        return -1;
    }
    struct process_queue *iter = pqueue;
    struct process_queue *item = NULL;
    while (iter) {
        if (iter->proc.pid == pid) {
            item = iter;
            break;
        }
        iter = iter->next;
    }
    if (item) {
        remove_from_queue(&pqueue, item);
        resume_wait_proc(item->proc.pid);
        if (curr_task->proc.parent_fg == &item->proc) {
            curr_task->proc.parent_fg = item->proc.parent_fg;
        }
        cleanup_task(item);
        return 0;
    }
    iter = wqueue;
    while (iter) {
        if (iter->proc.pid == pid) {
            item = iter;
            break;
        }
        iter = iter->next;
    }
    if (item) {
        remove_from_queue(&wqueue, item);
        resume_wait_proc(item->proc.pid);
        if (curr_task->proc.parent_fg == &item->proc) {
            curr_task->proc.parent_fg = item->proc.parent_fg;
        }
        cleanup_task(item);
        return 0;
    }
    printf("-sbush: kill(%d): No such process\n", pid);
    return 0;
}
Пример #9
0
int
__pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock,
			      const struct timespec *abstime)
{
  pthread_descr self;
  pthread_extricate_if extr;

  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
    return EINVAL;

  self = thread_self ();

  /* Set up extrication interface */
  extr.pu_object = rwlock;
  extr.pu_extricate_func =  rwlock_wr_extricate_func;

  /* Register extrication interface */
  __pthread_set_own_extricate_if (self, &extr);

  while(1)
    {
      __pthread_lock (&rwlock->__rw_lock, self);

      if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
	{
	  rwlock->__rw_writer = self;
	  __pthread_set_own_extricate_if (self, 0);
	  __pthread_unlock (&rwlock->__rw_lock);
	  return 0;
	}

      /* Suspend ourselves, then try again */
      enqueue (&rwlock->__rw_write_waiting, self);
      __pthread_unlock (&rwlock->__rw_lock);
      /* This is not a cancellation point */
      if (timedsuspend (self, abstime) == 0)
	{
	  int was_on_queue;

	  __pthread_lock (&rwlock->__rw_lock, self);
	  was_on_queue = remove_from_queue (&rwlock->__rw_write_waiting, self);
	  __pthread_unlock (&rwlock->__rw_lock);

	  if (was_on_queue)
	    {
	      __pthread_set_own_extricate_if (self, 0);
	      return ETIMEDOUT;
	    }

	  /* Eat the outstanding restart() from the signaller */
	  suspend (self);
	}
    }
}
Пример #10
0
static int rwlock_wr_extricate_func(void *obj, pthread_descr th)
{
  pthread_rwlock_t *rwlock = obj;
  int did_remove = 0;

  __pthread_lock(&rwlock->__rw_lock, NULL);
  did_remove = remove_from_queue(&rwlock->__rw_write_waiting, th);
  __pthread_unlock(&rwlock->__rw_lock);

  return did_remove;
}
Пример #11
0
static int _cancel_net_timer(net_timer_event *e)
{
    if(!e->pending) {
        return ERR_GENERAL;
    }

    remove_from_queue(e);
    e->pending = false;

    return NO_ERROR;
}
Пример #12
0
static int new_sem_extricate_func(void *obj, pthread_descr th)
{
  __volatile__ pthread_descr self = thread_self();
  sem_t *sem = obj;
  int did_remove = 0;

  __pthread_lock(&sem->__sem_lock, self);
  did_remove = remove_from_queue(&sem->__sem_waiting, th);
  __pthread_unlock(&sem->__sem_lock);

  return did_remove;
}
Пример #13
0
/*
 * add semadj values to semaphores, free undo structures.
 * undo structures are not freed when semaphore arrays are destroyed
 * so some of them may be out of date.
 * IMPLEMENTATION NOTE: There is some confusion over whether the
 * set of adjustments that needs to be done should be done in an atomic
 * manner or not. That is, if we are attempting to decrement the semval
 * should we queue up and wait until we can do so legally?
 * The original implementation attempted to do this (queue and wait).
 * The current implementation does not do so. The POSIX standard
 * and SVID should be consulted to determine what behavior is mandated.
 */
void sem_exit (void)
{
	struct sem_queue *q;
	struct sem_undo *u, *un = NULL, **up, **unp;
	struct semid_ds *sma;
	int nsems, i;

	/* If the current process was sleeping for a semaphore,
	 * remove it from the queue.
	 */
	if ((q = current->semsleeping)) {
		if (q->prev)
			remove_from_queue(q->sma,q);
		current->semsleeping = NULL;
	}

	for (up = &current->semundo; (u = *up); *up = u->proc_next, kfree(u)) {
		if (u->semid == -1)
			continue;
		sma = semary[(unsigned int) u->semid % SEMMNI];
		if (sma == IPC_UNUSED || sma == IPC_NOID)
			continue;
		if (sma->sem_perm.seq != (unsigned int) u->semid / SEMMNI)
			continue;
		/* remove u from the sma->undo list */
		for (unp = &sma->undo; (un = *unp); unp = &un->id_next) {
			if (u == un)
				goto found;
		}
		printk ("sem_exit undo list error id=%d\n", u->semid);
		break;
found:
		*unp = un->id_next;
		/* perform adjustments registered in u */
		nsems = sma->sem_nsems;
		for (i = 0; i < nsems; i++) {
			struct sem * sem = &sma->sem_base[i];
			sem->semval += u->semadj[i];
			if (sem->semval < 0)
				sem->semval = 0; /* shouldn't happen */
			sem->sempid = current->pid;
		}
		sma->sem_otime = CURRENT_TIME;
		/* maybe some queued-up processes were waiting for this */
		update_queue(sma);
	}
	current->semundo = NULL;
}
Пример #14
0
bool Resource::erase(Arrival* arrival, bool stay) {
  if (stay) {
    int amount = remove_from_server(false, sim->now(), arrival, -1);
    server_count += amount;
    return false;
  }

  if (!remove_from_queue(sim->verbose, sim->now(), arrival)) {
    release(arrival, -1);
    return false;
  }

  if (is_monitored())
    sim->record_resource(name, server_count, queue_count, capacity, queue_size);
  return true;
}
//Given dirs just for this thread and global file queue
void process_dirs(queue_t * loc_dir_queue, queue_t * glb_file_queue, queue_t * glb_dir_queue)
{
	//We have a list of dirs
	//Loop through each of them
	while(1)
	{
		queue_element_t * item = remove_from_queue(loc_dir_queue);
		if(item == NULL)
		{
			return;
		}
		
		//Get the str from this item
		char * str = item->path_name;
		//Process this dir
		process_dir(str,glb_file_queue, glb_dir_queue);
	}	
}
Пример #16
0
void handle_string(char * str, char ** result, void * state){
  struct Queue * queue = (struct Queue *) state;
  *result = NULL;
  if (queue == NULL)
    exit(1);

  char *command, *body;
  command = strtok_r(str, " ", &body);

  if (command != NULL &&
      !strncmp(command, PUSH, PUSHLEN)){
    add_to_queue(queue, body);
  } else if (str != NULL &&
             !strncmp(str, POP, POPLEN)){
    remove_from_queue(queue, result);
  } else {
    printf("don't know what we did\n");
  }
}
Пример #17
0
// Give up the CPU for one scheduling round.
void
yield(void)
{

  //cprintf("Entered yield\n");
 
  acquire(&ptable.lock);  //DOC: yieldlock
  proc->state = RUNNABLE;

  // START HW4   
  // put process at end of queue
  acquire(&runqueue.lock); 
  remove_from_queue( proc->pid, proc->priority );
  enqueue( proc->pid,proc->priority  ); //
  release(&runqueue.lock); 
  // END HW4
  
  sched();
  
  release(&ptable.lock);
}
//Given files just for this thread and global num found
void process_files(queue_t * loc_file_queue, unsigned int * num_found, char * to_find)
{
	unsigned int local_num_found = 0;
	
	//We have a list of files
	//Loop through each of them
	while(1)
	{
		queue_element_t * item = remove_from_queue(loc_file_queue);
		if(item == NULL)
		{
			//Done increment global with local
			(*num_found) +=local_num_found;
			return;
		}
		
		//Get the str from this item
		char * str = item->path_name;
		//Process this dir
		process_file(str, to_find, &local_num_found);
	}	
}
Пример #19
0
static void net_timer_runner(void *arg)
{
    (void) arg;

    net_timer_event *e;
    bigtime_t now;

    t_current_set_name("Net Timer");

    for(;;) {
        //sem_acquire_etc(net_q.wait_sem, 1, SEM_FLAG_TIMEOUT, NET_TIMER_INTERVAL, NULL);
        hal_sleep_msec(NET_TIMER_INTERVAL);

        now = system_time();
//printf("(^)");
    retry:
        mutex_lock(&net_q.lock);

        // pull off the head of the list and run it, if it timed out
        if((e = peek_queue_head()) != NULL && e->sched_time <= now) {

            remove_from_queue(e);
            e->pending = false;

            mutex_unlock(&net_q.lock);

            e->func(e->args);

            // Since we ran an event, loop back and check the head of
            // the list again, because the list may have changed while
            // inside the callback.
            goto retry;

        } else {
            mutex_unlock(&net_q.lock);
        }
    }

}
Пример #20
0
/* Go through the pending queue for the indicated semaphore
 * looking for tasks that can be completed. Keep cycling through
 * the queue until a pass is made in which no process is woken up.
 */
static void update_queue (struct semid_ds * sma)
{
	int wokeup, error;
	struct sem_queue * q;

	do {
		wokeup = 0;
		for (q = sma->sem_pending; q; q = q->next) {
			error = try_semop(sma, q->sops, q->nsops);
			/* Does q->sleeper still need to sleep? */
			if (error > 0)
				continue;
			/* Perform the operations the sleeper was waiting for */
			if (!error)
				error = do_semop(sma, q->sops, q->nsops, q->undo, q->pid);
			q->status = error;
			/* Remove it from the queue */
			remove_from_queue(sma,q);
			/* Wake it up */
			wake_up_interruptible(&q->sleeper); /* doesn't sleep! */
			wokeup++;
		}
	} while (wokeup);
}
Пример #21
0
static void *start_smoothing( void *ptr )
{
    obe_t *h = ptr;
    int num_muxed_data = 0, buffer_complete = 0;
    int64_t start_clock = -1, start_pcr, end_pcr, temporal_vbv_size = 0, cur_pcr;
    obe_muxed_data_t **muxed_data = NULL, *start_data, *end_data;
    AVFifoBuffer *fifo_data = NULL, *fifo_pcr = NULL;
    uint8_t *output_buf;

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

    /* This thread buffers one VBV worth of frames */
    fifo_data = av_fifo_alloc( TS_PACKETS_SIZE );
    if( !fifo_data )
    {
        fprintf( stderr, "[mux-smoothing] Could not allocate data fifo" );
        return NULL;
    }

    fifo_pcr = av_fifo_alloc( 7 * sizeof(int64_t) );
    if( !fifo_pcr )
    {
        fprintf( stderr, "[mux-smoothing] Could not allocate pcr fifo" );
        return NULL;
    }

    if( h->obe_system == OBE_SYSTEM_TYPE_GENERIC )
    {
        for( int i = 0; i < h->num_encoders; i++ )
        {
            if( h->encoders[i]->is_video )
            {
                pthread_mutex_lock( &h->encoders[i]->queue.mutex );
                while( !h->encoders[i]->is_ready )
                    pthread_cond_wait( &h->encoders[i]->queue.in_cv, &h->encoders[i]->queue.mutex );
                x264_param_t *params = h->encoders[i]->encoder_params;
                temporal_vbv_size = av_rescale_q_rnd(
                (int64_t)params->rc.i_vbv_buffer_size * params->rc.f_vbv_buffer_init,
                (AVRational){1, params->rc.i_vbv_max_bitrate }, (AVRational){ 1, OBE_CLOCK }, AV_ROUND_UP );
                pthread_mutex_unlock( &h->encoders[i]->queue.mutex );
                break;
            }
        }
    }

    while( 1 )
    {
        pthread_mutex_lock( &h->mux_smoothing_queue.mutex );

        while( h->mux_smoothing_queue.size == num_muxed_data && !h->cancel_mux_smoothing_thread )
            pthread_cond_wait( &h->mux_smoothing_queue.in_cv, &h->mux_smoothing_queue.mutex );

        if( h->cancel_mux_smoothing_thread )
        {
            pthread_mutex_unlock( &h->mux_smoothing_queue.mutex );
            break;
        }

        num_muxed_data = h->mux_smoothing_queue.size;

        /* Refill the buffer after a drop */
        pthread_mutex_lock( &h->drop_mutex );
        if( h->mux_drop )
        {
            syslog( LOG_INFO, "Mux smoothing buffer reset\n" );
            h->mux_drop = 0;
            av_fifo_reset( fifo_data );
            av_fifo_reset( fifo_pcr );
            buffer_complete = 0;
            start_clock = -1;
        }
        pthread_mutex_unlock( &h->drop_mutex );

        if( !buffer_complete )
        {
            start_data = h->mux_smoothing_queue.queue[0];
            end_data = h->mux_smoothing_queue.queue[num_muxed_data-1];

            start_pcr = start_data->pcr_list[0];
            end_pcr = end_data->pcr_list[(end_data->len / 188)-1];
            if( end_pcr - start_pcr >= temporal_vbv_size )
            {
                buffer_complete = 1;
                start_clock = -1;
            }
            else
            {
                pthread_mutex_unlock( &h->mux_smoothing_queue.mutex );
                continue;
            }
        }

        //printf("\n mux smoothed frames %i \n", num_muxed_data );

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

        for( int i = 0; i < num_muxed_data; i++ )
        {
            if( av_fifo_realloc2( fifo_data, av_fifo_size( fifo_data ) + muxed_data[i]->len ) < 0 )
            {
                syslog( LOG_ERR, "Malloc failed\n" );
                return NULL;
            }

            av_fifo_generic_write( fifo_data, muxed_data[i]->data, muxed_data[i]->len, NULL );

            if( av_fifo_realloc2( fifo_pcr, av_fifo_size( fifo_pcr ) + ((muxed_data[i]->len * sizeof(int64_t)) / 188) ) < 0 )
            {
                syslog( LOG_ERR, "Malloc failed\n" );
                return NULL;
            }

            av_fifo_generic_write( fifo_pcr, muxed_data[i]->pcr_list, (muxed_data[i]->len * sizeof(int64_t)) / 188, NULL );

            remove_from_queue( &h->mux_smoothing_queue );
            destroy_muxed_data( muxed_data[i] );
        }

        free( muxed_data );
        muxed_data = NULL;
        num_muxed_data = 0;

        while( av_fifo_size( fifo_data ) >= TS_PACKETS_SIZE )
        {
            output_buf = malloc( TS_PACKETS_SIZE + 7 * sizeof(int64_t) );
            if( !output_buf )
            {
                syslog( LOG_ERR, "Malloc failed\n" );
                return NULL;
            }
            av_fifo_generic_read( fifo_pcr, output_buf, 7 * sizeof(int64_t), NULL );
            av_fifo_generic_read( fifo_data, &output_buf[7 * sizeof(int64_t)], TS_PACKETS_SIZE, NULL );

            cur_pcr = AV_RN64( output_buf );

            if( start_clock != -1 )
            {
                sleep_input_clock( h, cur_pcr - start_pcr + start_clock );
            }

            if( start_clock == -1 )
            {
                start_clock = get_input_clock_in_mpeg_ticks( h );
                start_pcr = cur_pcr;
            }

            if( add_to_queue( &h->output_queue, output_buf ) < 0 )
                return NULL;
            output_buf = NULL;
        }
    }

    av_fifo_free( fifo_data );
    av_fifo_free( fifo_pcr );

    return NULL;
}
Пример #22
0
static void *start_encoder( void *ptr )
{
    obe_aud_enc_params_t *enc_params = ptr;
    obe_t *h = enc_params->h;
    obe_encoder_t *encoder = enc_params->encoder;
    obe_output_stream_t *stream = enc_params->stream;
    obe_raw_frame_t *raw_frame;
    obe_coded_frame_t *coded_frame;
    void *audio_buf = NULL;
    int64_t cur_pts = -1, pts_increment;
    int i, frame_size, ret, got_pkt, num_frames = 0, total_size = 0, audio_buf_len;
    AVFifoBuffer *out_fifo = NULL;
    AVAudioResampleContext *avr = NULL;
    AVPacket pkt;
    AVCodecContext *codec = NULL;
    AVFrame *frame = NULL;
    AVDictionary *opts = NULL;
    char is_latm[2];

    avcodec_register_all();

    codec = avcodec_alloc_context3( NULL );
    if( !codec )
    {
        fprintf( stderr, "Malloc failed\n" );
        goto finish;
    }

    for( i = 0; lavc_encoders[i].obe_name != -1; i++ )
    {
        if( lavc_encoders[i].obe_name == stream->stream_format )
            break;
    }

    if( lavc_encoders[i].obe_name == -1 )
    {
        fprintf( stderr, "[lavc] Could not find encoder1\n" );
        goto finish;
    }

    AVCodec *enc = avcodec_find_encoder( lavc_encoders[i].lavc_name );
    if( !enc )
    {
        fprintf( stderr, "[lavc] Could not find encoder2\n" );
        goto finish;
    }

    if( enc->sample_fmts[0] == -1 )
    {
        fprintf( stderr, "[lavc] No valid sample formats\n" );
        goto finish;
    }

    codec->sample_rate = enc_params->sample_rate;
    codec->bit_rate = stream->bitrate * 1000;
    codec->sample_fmt = enc->sample_fmts[0];
    codec->channels = av_get_channel_layout_nb_channels( stream->channel_layout );
    codec->channel_layout = stream->channel_layout;
    codec->time_base.num = 1;
    codec->time_base.den = OBE_CLOCK;
    codec->profile = stream->aac_opts.aac_profile == AAC_HE_V2 ? FF_PROFILE_AAC_HE_V2 :
                     stream->aac_opts.aac_profile == AAC_HE_V1 ? FF_PROFILE_AAC_HE :
                     FF_PROFILE_AAC_LOW;

    snprintf( is_latm, sizeof(is_latm), "%i", stream->aac_opts.latm_output );
    av_dict_set( &opts, "latm", is_latm, 0 );
    av_dict_set( &opts, "header_period", "2", 0 );

    if( avcodec_open2( codec, enc, &opts ) < 0 )
    {
        fprintf( stderr, "[lavc] Could not open encoder\n" );
        goto finish;
    }

    avr = avresample_alloc_context();
    if( !avr )
    {
        fprintf( stderr, "Malloc failed\n" );
        goto finish;
    }

    av_opt_set_int( avr, "in_channel_layout",   codec->channel_layout, 0 );
    av_opt_set_int( avr, "in_sample_fmt",       enc_params->input_sample_format, 0 );
    av_opt_set_int( avr, "in_sample_rate",      enc_params->sample_rate, 0 );
    av_opt_set_int( avr, "out_channel_layout",  codec->channel_layout, 0 );
    av_opt_set_int( avr, "out_sample_fmt",      codec->sample_fmt,     0 );
    av_opt_set_int( avr, "dither_method",       AV_RESAMPLE_DITHER_TRIANGULAR_NS, 0 );

    if( avresample_open( avr ) < 0 )
    {
        fprintf( stderr, "Could not open AVResample\n" );
        goto finish;
    }

    /* The number of samples per E-AC3 frame is unknown until the encoder is ready */
    if( stream->stream_format == AUDIO_E_AC_3 || stream->stream_format == AUDIO_AAC )
    {
        pthread_mutex_lock( &encoder->queue.mutex );
        encoder->is_ready = 1;
        encoder->num_samples = codec->frame_size;
        /* Broadcast because input and muxer can be stuck waiting for encoder */
        pthread_cond_broadcast( &encoder->queue.in_cv );
        pthread_mutex_unlock( &encoder->queue.mutex );
    }

    frame_size = (double)codec->frame_size * 125 * stream->bitrate *
                 enc_params->frames_per_pes / enc_params->sample_rate;
    /* NB: libfdk-aac already doubles the frame size appropriately */
    pts_increment = (double)codec->frame_size * OBE_CLOCK * enc_params->frames_per_pes / enc_params->sample_rate;

    out_fifo = av_fifo_alloc( frame_size );
    if( !out_fifo )
    {
        fprintf( stderr, "Malloc failed\n" );
        goto finish;
    }

    audio_buf_len = codec->frame_size * av_get_bytes_per_sample( codec->sample_fmt ) * codec->channels;
    audio_buf = av_malloc( audio_buf_len );
    if( !audio_buf )
    {
        fprintf( stderr, "Malloc failed\n" );
        goto finish;
    }

    frame = avcodec_alloc_frame();
    if( !frame )
    {
        fprintf( stderr, "Could not allocate frame\n" );
        goto finish;
    }

    while( 1 )
    {
        /* TODO: detect bitrate or channel reconfig */
        pthread_mutex_lock( &encoder->queue.mutex );

        while( !encoder->queue.size && !encoder->cancel_thread )
            pthread_cond_wait( &encoder->queue.in_cv, &encoder->queue.mutex );

        if( encoder->cancel_thread )
        {
            pthread_mutex_unlock( &encoder->queue.mutex );
            goto finish;
        }

        raw_frame = encoder->queue.queue[0];
        pthread_mutex_unlock( &encoder->queue.mutex );

        if( cur_pts == -1 )
            cur_pts = raw_frame->pts;

        if( avresample_convert( avr, NULL, 0, raw_frame->audio_frame.num_samples, raw_frame->audio_frame.audio_data,
                                raw_frame->audio_frame.linesize, raw_frame->audio_frame.num_samples ) < 0 )
        {
            syslog( LOG_ERR, "[lavc] Sample format conversion failed\n" );
            break;
        }

        raw_frame->release_data( raw_frame );
        raw_frame->release_frame( raw_frame );
        remove_from_queue( &encoder->queue );

        while( avresample_available( avr ) >= codec->frame_size )
        {
            got_pkt = 0;
            avcodec_get_frame_defaults( frame );
            frame->nb_samples = codec->frame_size;
            avresample_read( avr, &audio_buf, codec->frame_size );

            if( avcodec_fill_audio_frame( frame, codec->channels, codec->sample_fmt, audio_buf, audio_buf_len, 0 ) < 0 )
            {
                syslog( LOG_ERR, "[lavc] Could not fill audio frame\n" );
                break;
            }

            av_init_packet( &pkt );
            pkt.data = NULL;
            pkt.size = 0;

            ret = avcodec_encode_audio2( codec, &pkt, frame, &got_pkt );
            if( ret < 0 )
            {
                syslog( LOG_ERR, "[lavc] Audio encoding failed\n" );
                goto finish;
            }

            if( !got_pkt )
                continue;

            total_size += pkt.size;
            num_frames++;

            if( av_fifo_realloc2( out_fifo, av_fifo_size( out_fifo ) + pkt.size ) < 0 )
            {
                syslog( LOG_ERR, "Malloc failed\n" );
                break;
            }

            av_fifo_generic_write( out_fifo, pkt.data, pkt.size, NULL );
            obe_free_packet( &pkt );

            if( num_frames == enc_params->frames_per_pes )
            {
                coded_frame = new_coded_frame( encoder->output_stream_id, total_size );
                if( !coded_frame )
                {
                    syslog( LOG_ERR, "Malloc failed\n" );
                    goto finish;
                }

                av_fifo_generic_read( out_fifo, coded_frame->data, total_size, NULL );

                coded_frame->pts = cur_pts;
                coded_frame->random_access = 1; /* Every frame output is a random access point */
                add_to_queue( &h->mux_queue, coded_frame );

                /* We need to generate PTS because frame sizes have changed */
                cur_pts += pts_increment;
                total_size = num_frames = 0;
            }
        }
    }

finish:
    if( frame )
       avcodec_free_frame( &frame );

    if( audio_buf )
        av_free( audio_buf );

    if( out_fifo )
        av_fifo_free( out_fifo );

    if( avr )
        avresample_free( &avr );

    if( codec )
    {
        avcodec_close( codec );
        av_free( codec );
    }

    free( enc_params );

    return NULL;
}
Пример #23
0
int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
{
	int i, id, size, error;
	struct semid_ds *sma;
	struct sembuf sops[SEMOPM], *sop;
	struct sem_undo *un;
	int undos = 0, alter = 0;

	if (nsops < 1 || semid < 0)
		return -EINVAL;
	if (nsops > SEMOPM)
		return -E2BIG;
	if (!tsops)
		return -EFAULT;
	if ((i = verify_area (VERIFY_READ, tsops, nsops * sizeof(*tsops))))
		return i;
	memcpy_fromfs (sops, tsops, nsops * sizeof(*tsops));
	id = (unsigned int) semid % SEMMNI;
	if ((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)
		return -EINVAL;
	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
		return -EIDRM;
	for (i = 0; i < nsops; i++) {
		sop = &sops[i];
		if (sop->sem_num >= sma->sem_nsems)
			return -EFBIG;
		if (sop->sem_flg & SEM_UNDO)
			undos++;
		if (sop->sem_op)
			alter++;
	}
	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
		return -EACCES;
	error = try_semop(sma, sops, nsops);
	if (error < 0)
		return error;
	if (undos) {
		/* Make sure we have an undo structure
		 * for this process and this semaphore set.
		 */
		for (un = current->semundo; un; un = un->proc_next)
			if (un->semid == semid)
				break;
		if (!un) {
			size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
			un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);
			if (!un)
				return -ENOMEM;
			memset(un, 0, size);
			un->semadj = (short *) &un[1];
			un->semid = semid;
			un->proc_next = current->semundo;
			current->semundo = un;
			un->id_next = sma->undo;
			sma->undo = un;
		}
	} else
		un = NULL;
	if (error == 0) {
		/* the operations go through immediately */
		error = do_semop(sma, sops, nsops, un, current->pid);
		/* maybe some queued-up processes were waiting for this */
		update_queue(sma);
		return error;
	} else {
		/* We need to sleep on this operation, so we put the current
		 * task into the pending queue and go to sleep.
		 */
		struct sem_queue queue;

		queue.sma = sma;
		queue.sops = sops;
		queue.nsops = nsops;
		queue.undo = un;
		queue.pid = current->pid;
		queue.status = 0;
		insert_into_queue(sma,&queue);
		queue.sleeper = NULL;
		current->semsleeping = &queue;
		interruptible_sleep_on(&queue.sleeper);
		current->semsleeping = NULL;
		/* When we wake up, either the operation is finished,
		 * or some kind of error happened.
		 */
		if (!queue.prev) {
			/* operation is finished, update_queue() removed us */
			return queue.status;
		} else {
			remove_from_queue(sma,&queue);
			return -EINTR;
		}
	}
}
Пример #24
0
int
__pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
			      const struct timespec *abstime)
{
  pthread_descr self = NULL;
  pthread_readlock_info *existing;
  int out_of_mem, have_lock_already;
  pthread_extricate_if extr;

  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
    return EINVAL;

  have_lock_already = rwlock_have_already(&self, rwlock,
					  &existing, &out_of_mem);

  if (self == NULL)
    self = thread_self ();

  /* Set up extrication interface */
  extr.pu_object = rwlock;
  extr.pu_extricate_func = rwlock_rd_extricate_func;

  /* Register extrication interface */
  __pthread_set_own_extricate_if (self, &extr);

  for (;;)
    {
      __pthread_lock (&rwlock->__rw_lock, self);

      if (rwlock_can_rdlock(rwlock, have_lock_already))
	break;

      enqueue (&rwlock->__rw_read_waiting, self);
      __pthread_unlock (&rwlock->__rw_lock);
      /* This is not a cancellation point */
      if (timedsuspend (self, abstime) == 0)
	{
	  int was_on_queue;

	  __pthread_lock (&rwlock->__rw_lock, self);
	  was_on_queue = remove_from_queue (&rwlock->__rw_read_waiting, self);
	  __pthread_unlock (&rwlock->__rw_lock);

	  if (was_on_queue)
	    {
	      __pthread_set_own_extricate_if (self, 0);
	      return ETIMEDOUT;
	    }

	  /* Eat the outstanding restart() from the signaller */
	  suspend (self);
	}
    }

  __pthread_set_own_extricate_if (self, 0);

  ++rwlock->__rw_readers;
  __pthread_unlock (&rwlock->__rw_lock);

  if (have_lock_already || out_of_mem)
    {
      if (existing != NULL)
	++existing->pr_lock_count;
      else
	++self->p_untracked_readlock_count;
    }

  return 0;
}
Пример #25
0
asmlinkage int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
{
	int id, size, error = -EINVAL;
	struct semid_ds *sma;
	struct sembuf sops[SEMOPM], *sop;
	struct sem_undo *un;
	int undos = 0, decrease = 0, alter = 0;
	struct sem_queue queue;

	lock_kernel();
	if (nsops < 1 || semid < 0)
		goto out;
	error = -E2BIG;
	if (nsops > SEMOPM)
		goto out;
	error = -EFAULT;
	if (copy_from_user (sops, tsops, nsops * sizeof(*tsops)))
		goto out;
	id = (unsigned int) semid % SEMMNI;
	error = -EINVAL;
	if ((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)
		goto out;
	error = -EIDRM;
	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
		goto out;

		error = -EFBIG;
	for (sop = sops; sop < sops + nsops; sop++) {
		if (sop->sem_num >= sma->sem_nsems)
			goto out;
		if (sop->sem_flg & SEM_UNDO)
			undos++;
		if (sop->sem_op < 0)
			decrease = 1;
                if (sop->sem_op > 0)
                        alter = 1;
	}
        alter |= decrease;

	error = -EACCES;
	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
		goto out;
	if (undos) {
		/* Make sure we have an undo structure
		 * for this process and this semaphore set.
		 */
		for (un = current->semundo; un; un = un->proc_next)
			if (un->semid == semid)
				break;
		if (!un) {
			size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
			un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);
			if (!un) {
				error = -ENOMEM;
				goto out;
			}
			memset(un, 0, size);
			un->semadj = (short *) &un[1];
			un->semid = semid;
			un->proc_next = current->semundo;
			current->semundo = un;
			un->id_next = sma->undo;
			sma->undo = un;
		}
	} else
		un = NULL;

	error = try_atomic_semop (sma, sops, nsops, un, current->pid, 0);
	if (error <= 0)
                goto update;

        /* We need to sleep on this operation, so we put the current
         * task into the pending queue and go to sleep.
         */
                
        queue.sma = sma;
        queue.sops = sops;
        queue.nsops = nsops;
        queue.undo = un;
        queue.pid = current->pid;
        queue.alter = decrease;
        current->semsleeping = &queue;
        if (alter)
                append_to_queue(sma ,&queue);
        else
                prepend_to_queue(sma ,&queue);

        for (;;) {
                queue.status = -EINTR;
                queue.sleeper = NULL;
                interruptible_sleep_on(&queue.sleeper);

                /*
                 * If queue.status == 1 we where woken up and
                 * have to retry else we simply return.
                 * If an interrupt occurred we have to clean up the
                 * queue
                 *
                 */
                if (queue.status == 1)
                {
                        error = try_atomic_semop (sma, sops, nsops, un,
                                                  current->pid,0);
                        if (error <= 0) 
                                break;
                } else {
                        error = queue.status;;
                        if (queue.prev) /* got Interrupt */
                                break;
                        /* Everything done by update_queue */
                        current->semsleeping = NULL;
                        goto out;
                }
        }
        current->semsleeping = NULL;
        remove_from_queue(sma,&queue);
update:
        if (alter)
                update_queue (sma);
out:
	unlock_kernel();
	return error;
}
Пример #26
0
// TODO(byan23): Set inuse[] to 0?
// Exit the current process.  Does not return.
// An exited process remains in the zombie state
// until its parent calls wait() to find out it exited.
void
exit(void)
{
  //cprintf("exit pid: %d.\n", proc->pid);
  struct proc *p;
  int fd;

  if(proc == initproc)
    panic("init exiting");

  // Close all open files.
  for(fd = 0; fd < NOFILE; fd++){
    if(proc->ofile[fd]){
      fileclose(proc->ofile[fd]);
      proc->ofile[fd] = 0;
    }
  }

  iput(proc->cwd);
  proc->cwd = 0;

  acquire(&ptable.lock);

  // Parent might be sleeping in wait().
  wakeup1(proc->parent);

  // Pass abandoned children to init.
  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
    if(p->parent == proc){
      p->parent = initproc;
      if(p->state == ZOMBIE)
	wakeup1(initproc);
    }
  }

  // Jump into the scheduler, never to return.
  proc->state = ZOMBIE;
  int slot_no;
  for (slot_no = 0; slot_no < NPROC; ++slot_no) {
    if (&ptable.proc[slot_no] == proc)
      break;
  }
  //cprintf("found at slot: %d\n", slot_no);
  int pri = proc_stat.priority[slot_no];
  switch(pri) {
    case 0:
      remove_from_queue(&q0_head, &q0_tail, proc);
      break;
    case 1:
      remove_from_queue(&q1_head, &q1_tail, proc);
      break;
    case 2:
      remove_from_queue(&q2_head, &q2_tail, proc);
      break;
    case 3:
      remove_from_queue(&q3_head, &q3_tail, proc);
      break;
    default:
      cprintf("Wrong priority queue while exiting.\n");
  }
  proc_stat.inuse[slot_no] = 0;
  sched();
  panic("zombie exit");
}
Пример #27
0
int sem_timedwait(sem_t *sem, const struct timespec *abstime)
{
  pthread_descr self = thread_self();
  pthread_extricate_if extr;
  int already_canceled = 0;
  int spurious_wakeup_count;

  __pthread_lock(&sem->__sem_lock, self);
  if (sem->__sem_value > 0) {
    --sem->__sem_value;
    __pthread_unlock(&sem->__sem_lock);
    return 0;
  }

  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) {
    /* The standard requires that if the function would block and the
       time value is illegal, the function returns with an error.  */
    __pthread_unlock(&sem->__sem_lock);
    __set_errno (EINVAL);
    return -1;
  }

  /* Set up extrication interface */
  extr.pu_object = sem;
  extr.pu_extricate_func = new_sem_extricate_func;

  /* Register extrication interface */
  THREAD_SETMEM(self, p_sem_avail, 0);
  __pthread_set_own_extricate_if(self, &extr);
  /* Enqueue only if not already cancelled. */
  if (!(THREAD_GETMEM(self, p_canceled)
      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
    enqueue(&sem->__sem_waiting, self);
  else
    already_canceled = 1;
  __pthread_unlock(&sem->__sem_lock);

  if (already_canceled) {
    __pthread_set_own_extricate_if(self, 0);
    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
  }

  spurious_wakeup_count = 0;
  while (1)
    {
      if (timedsuspend(self, abstime) == 0) {
	int was_on_queue;

	/* __pthread_lock will queue back any spurious restarts that
	   may happen to it. */

	__pthread_lock(&sem->__sem_lock, self);
	was_on_queue = remove_from_queue(&sem->__sem_waiting, self);
	__pthread_unlock(&sem->__sem_lock);

	if (was_on_queue) {
	  __pthread_set_own_extricate_if(self, 0);
	  __set_errno (ETIMEDOUT);
	  return -1;
	}

	/* Eat the outstanding restart() from the signaller */
	suspend(self);
      }

      if (THREAD_GETMEM(self, p_sem_avail) == 0
	  && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
	      || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
	{
	  /* Count resumes that don't belong to us. */
	  spurious_wakeup_count++;
	  continue;
	}
      break;
    }

 __pthread_set_own_extricate_if(self, 0);

  /* Terminate only if the wakeup came from cancellation. */
  /* Otherwise ignore cancellation because we got the semaphore. */

  if (THREAD_GETMEM(self, p_woken_by_cancel)
      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
    THREAD_SETMEM(self, p_woken_by_cancel, 0);
    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
  }
  /* We got the semaphore */
  return 0;
}
Пример #28
0
asmlinkage long sys_semtimedop (int semid, struct sembuf *tsops,
			unsigned nsops, const struct timespec *timeout)
{
	int error = -EINVAL;
	struct sem_array *sma;
	struct sembuf fast_sops[SEMOPM_FAST];
	struct sembuf* sops = fast_sops, *sop;
	struct sem_undo *un;
	int undos = 0, decrease = 0, alter = 0;
	struct sem_queue queue;
	unsigned long jiffies_left = 0;

	if (nsops < 1 || semid < 0)
		return -EINVAL;
	if (nsops > sc_semopm)
		return -E2BIG;
	if(nsops > SEMOPM_FAST) {
		sops = kmalloc(sizeof(*sops)*nsops,GFP_KERNEL);
		if(sops==NULL)
			return -ENOMEM;
	}
	if (copy_from_user (sops, tsops, nsops * sizeof(*tsops))) {
		error=-EFAULT;
		goto out_free;
	}
	if (timeout) {
		struct timespec _timeout;
		if (copy_from_user(&_timeout, timeout, sizeof(*timeout))) {
			error = -EFAULT;
			goto out_free;
		}
		if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
		    _timeout.tv_nsec >= 1000000000L) {
			error = -EINVAL;
			goto out_free;
		}
		jiffies_left = timespec_to_jiffies(&_timeout);
	}
	sma = sem_lock(semid);
	error=-EINVAL;
	if(sma==NULL)
		goto out_free;
	error = -EIDRM;
	if (sem_checkid(sma,semid))
		goto out_unlock_free;
	error = -EFBIG;
	for (sop = sops; sop < sops + nsops; sop++) {
		if (sop->sem_num >= sma->sem_nsems)
			goto out_unlock_free;
		if (sop->sem_flg & SEM_UNDO)
			undos++;
		if (sop->sem_op < 0)
			decrease = 1;
		if (sop->sem_op > 0)
			alter = 1;
	}
	alter |= decrease;

	error = -EACCES;
	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
		goto out_unlock_free;
	if (undos) {
		/* Make sure we have an undo structure
		 * for this process and this semaphore set.
		 */
		un=current->semundo;
		while(un != NULL) {
			if(un->semid==semid)
				break;
			if(un->semid==-1)
				un=freeundos(sma,un);
			 else
				un=un->proc_next;
		}
		if (!un) {
			error = alloc_undo(sma,&un,semid,alter);
			if(error)
				goto out_free;
		}
	} else
		un = NULL;

	error = try_atomic_semop (sma, sops, nsops, un, current->tgid, 0);
	if (error <= 0)
		goto update;

	/* We need to sleep on this operation, so we put the current
	 * task into the pending queue and go to sleep.
	 */
		
	queue.sma = sma;
	queue.sops = sops;
	queue.nsops = nsops;
	queue.undo = un;
	queue.pid = current->tgid;
	queue.alter = decrease;
	queue.id = semid;
	if (alter)
		append_to_queue(sma ,&queue);
	else
		prepend_to_queue(sma ,&queue);
	current->semsleeping = &queue;

	for (;;) {
		struct sem_array* tmp;
		queue.status = -EINTR;
		queue.sleeper = current;
		current->state = TASK_INTERRUPTIBLE;
		sem_unlock(semid);

		if (timeout)
			jiffies_left = schedule_timeout(jiffies_left);
		else
			schedule();

		tmp = sem_lock(semid);
		if(tmp==NULL) {
			if(queue.prev != NULL)
				BUG();
			current->semsleeping = NULL;
			error = -EIDRM;
			goto out_free;
		}
		/*
		 * If queue.status == 1 we where woken up and
		 * have to retry else we simply return.
		 * If an interrupt occurred we have to clean up the
		 * queue
		 *
		 */
		if (queue.status == 1)
		{
			error = try_atomic_semop (sma, sops, nsops, un,
						  current->tgid, 0);
			if (error <= 0) 
				break;
		} else {
			error = queue.status;
			if (error == -EINTR && timeout && jiffies_left == 0)
				error = -EAGAIN;
			if (queue.prev) /* got Interrupt */
				break;
			/* Everything done by update_queue */
			current->semsleeping = NULL;
			goto out_unlock_free;
		}
	}
	current->semsleeping = NULL;
	remove_from_queue(sma,&queue);
update:
	if (alter)
		update_queue (sma);
out_unlock_free:
	sem_unlock(semid);
out_free:
	if(sops != fast_sops)
		kfree(sops);
	return error;
}
Пример #29
0
static void *start_smoothing( void *ptr )
{
    obe_t *h = ptr;
    int num_enc_smoothing_frames = 0, buffer_frames = 0;
    int64_t start_dts = -1, start_pts = -1, last_clock = -1;
    obe_coded_frame_t *coded_frame = NULL;

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

    /* FIXME: when we have soft pulldown this will need changing */
    if( h->obe_system == OBE_SYSTEM_TYPE_GENERIC )
    {
        for( int i = 0; i < h->num_encoders; i++ )
        {
            if( h->encoders[i]->is_video )
            {
                pthread_mutex_lock( &h->encoders[i]->queue.mutex );
                while( !h->encoders[i]->is_ready )
                    pthread_cond_wait( &h->encoders[i]->queue.in_cv, &h->encoders[i]->queue.mutex );
                x264_param_t *params = h->encoders[i]->encoder_params;
                buffer_frames = params->sc.i_buffer_size;
                pthread_mutex_unlock( &h->encoders[i]->queue.mutex );
                break;
            }
        }
    }

    int64_t send_delta = 0;

    while( 1 )
    {
        pthread_mutex_lock( &h->enc_smoothing_queue.mutex );

        if( h->cancel_enc_smoothing_thread )
        {
            pthread_mutex_unlock( &h->enc_smoothing_queue.mutex );
            break;
        }

        while( h->enc_smoothing_queue.size == num_enc_smoothing_frames )
            pthread_cond_wait( &h->enc_smoothing_queue.in_cv, &h->enc_smoothing_queue.mutex );

        if( h->cancel_enc_smoothing_thread )
        {
            pthread_mutex_unlock( &h->enc_smoothing_queue.mutex );
            break;
        }

        num_enc_smoothing_frames = h->enc_smoothing_queue.size;

        if( !h->enc_smoothing_buffer_complete )
        {
            if( num_enc_smoothing_frames >= buffer_frames )
            {
                h->enc_smoothing_buffer_complete = 1;
                start_dts = -1;
            }
            else
            {
                pthread_mutex_unlock( &h->enc_smoothing_queue.mutex );
                continue;
            }
        }

//        printf("\n smoothed frames %i \n", num_enc_smoothing_frames );

        coded_frame = h->enc_smoothing_queue.queue[0];
        pthread_mutex_unlock( &h->enc_smoothing_queue.mutex );

        /* The terminology can be a cause for confusion:
         *   pts refers to the pts from the input which is monotonic
         *   dts refers to the dts out of the encoder which is monotonic */

        pthread_mutex_lock( &h->obe_clock_mutex );

        //printf("\n dts gap %"PRIi64" \n", coded_frame->real_dts - start_dts );
        //printf("\n pts gap %"PRIi64" \n", h->obe_clock_last_pts - start_pts );

        last_clock = h->obe_clock_last_pts;

        if( start_dts == -1 )
        {
            start_dts = coded_frame->real_dts;
            /* Wait until the next clock tick */
            while( last_clock == h->obe_clock_last_pts )
                pthread_cond_wait( &h->obe_clock_cv, &h->obe_clock_mutex );
            start_pts = h->obe_clock_last_pts;
        }
        else if( coded_frame->real_dts - start_dts > h->obe_clock_last_pts - start_pts )
        {
            //printf("\n waiting \n");
            while( last_clock == h->obe_clock_last_pts )
                pthread_cond_wait( &h->obe_clock_cv, &h->obe_clock_mutex );
        }
        /* otherwise, continue since the frame is late */

        pthread_mutex_unlock( &h->obe_clock_mutex );

        add_to_queue( &h->mux_queue, coded_frame );

        //printf("\n send_delta %"PRIi64" \n", get_input_clock_in_mpeg_ticks( h ) - send_delta );
        //send_delta = get_input_clock_in_mpeg_ticks( h );

        remove_from_queue( &h->enc_smoothing_queue );
        pthread_mutex_lock( &h->enc_smoothing_queue.mutex );
        h->enc_smoothing_last_exit_time = get_input_clock_in_mpeg_ticks( h );
        pthread_mutex_unlock( &h->enc_smoothing_queue.mutex );
        num_enc_smoothing_frames = 0;
    }

    return NULL;
}
Пример #30
0
/*
 * add semadj values to semaphores, free undo structures.
 * undo structures are not freed when semaphore arrays are destroyed
 * so some of them may be out of date.
 * IMPLEMENTATION NOTE: There is some confusion over whether the
 * set of adjustments that needs to be done should be done in an atomic
 * manner or not. That is, if we are attempting to decrement the semval
 * should we queue up and wait until we can do so legally?
 * The original implementation attempted to do this (queue and wait).
 * The current implementation does not do so. The POSIX standard
 * and SVID should be consulted to determine what behavior is mandated.
 */
void sem_exit (void)
{
	struct sem_queue *q;
	struct sem_undo *u, *un = NULL, **up, **unp;
	struct sem_array *sma;
	int nsems, i;

	/* If the current process was sleeping for a semaphore,
	 * remove it from the queue.
	 */
	if ((q = current->semsleeping)) {
		int semid = q->id;
		sma = sem_lock(semid);
		current->semsleeping = NULL;

		if (q->prev) {
			if(sma==NULL)
				BUG();
			remove_from_queue(q->sma,q);
		}
		if(sma!=NULL)
			sem_unlock(semid);
	}

	for (up = &current->semundo; (u = *up); *up = u->proc_next, kfree(u)) {
		int semid = u->semid;
		if(semid == -1)
			continue;
		sma = sem_lock(semid);
		if (sma == NULL)
			continue;

		if (u->semid == -1)
			goto next_entry;

		if (sem_checkid(sma,u->semid))
			goto next_entry;

		/* remove u from the sma->undo list */
		for (unp = &sma->undo; (un = *unp); unp = &un->id_next) {
			if (u == un)
				goto found;
		}
		printk ("sem_exit undo list error id=%d\n", u->semid);
		goto next_entry;
found:
		*unp = un->id_next;
		/* perform adjustments registered in u */
		nsems = sma->sem_nsems;
		for (i = 0; i < nsems; i++) {
			struct sem * sem = &sma->sem_base[i];
			sem->semval += u->semadj[i];
			if (sem->semval < 0)
				sem->semval = 0; /* shouldn't happen */
			sem->sempid = current->tgid;
		}
		sma->sem_otime = CURRENT_TIME;
		/* maybe some queued-up processes were waiting for this */
		update_queue(sma);
next_entry:
		sem_unlock(semid);
	}
	current->semundo = NULL;
}