Ejemplo n.º 1
0
semaphore_t *
semaphore_allocate (int entry_count)
{
  NEW_VAR (pthread_mutex_t, ptm);
  NEW_VAR (semaphore_t, sem);
  int rc;

  memset ((void *) ptm, 0, sizeof (pthread_mutex_t));
#ifndef OLD_PTHREADS
  rc = pthread_mutex_init (ptm, &_mutex_attr);
#else
  rc = pthread_mutex_init (ptm, _mutex_attr);
#endif
  CKRET (rc);

  sem->sem_entry_count = entry_count;
  sem->sem_handle = (void *) ptm;
#ifdef SEM_NO_ORDER
  sem->sem_cv = _alloc_cv ();
  if (!sem->sem_cv) goto failed;
  sem->sem_any_signalled = 0;
#endif
  thread_queue_init (&sem->sem_waiting);
  return sem;

failed:
  dk_free ((void *) ptm, sizeof (pthread_mutex_t));
  dk_free (sem, sizeof (semaphore_t));
  return NULL;
}
Ejemplo n.º 2
0
semaphore_t *
semaphore_allocate (int entry_count)
{
  NEW_VAR (semaphore_t, sem);
  sem->sem_entry_count = entry_count;
  thread_queue_init (&sem->sem_waiting);

  return sem;
}
Ejemplo n.º 3
0
void runStorageProcessor()
{
	uv_thread_t thread;

	saveQueue = malloc(sizeof(struct threadqueue));
	thread_queue_init(saveQueue);

	uv_thread_create(&thread, storageProcessor, NULL);
}
Ejemplo n.º 4
0
void thread_manager_init()
/* call this once before launching any threads */
{
	/* first study current system and see if thread launch worth trying */
	(void) fill();		/* do a probe with filler on stack */
	(void) boundlow();	/* do a probe without filler */
	(void) studyit();	/* figure out what it all means */

	/* now build thread manager data structures */
	thread_queue_init( &readylist );
	mem_to_free = (void *)0;
	current = thread_null;
}
Ejemplo n.º 5
0
static void
_sched_init (void)
{
  int i;

  for (i = 0; i < MAX_PRIORITY; i++)
    thread_queue_init (&_runq[i]);

  thread_queue_init (&_waitq);
  thread_queue_init (&_deadq);

  _thread_num_wait = 0;
  _thread_num_dead = 0;
  _thread_num_runnable = 0;
  _thread_num_total = 1;

#ifdef EXPIRIMENTAL
  _timerq = timer_queue_allocate ();
  timer_queue_update (_timerq, timer_queue_time_elapsed (_timerq));
  io_init ();
#endif
}
Ejemplo n.º 6
0
static void
_sched_init (void)
{
  _q_lock = mutex_allocate ();

  thread_queue_init (&_deadq);
  thread_queue_init (&_waitq);

  _thread_num_wait = 0;
  _thread_num_dead = 0;
  _thread_num_runnable = -1;	/* not counted */
  _thread_num_total = 1;

#ifdef EXPIRIMENTAL
  io_init ();

  pipe (_ev_pipes);
  thread_nb_fd (_ev_pipes[0]);
  thread_nb_fd (_ev_pipes[1]);
#endif
#ifdef MTX_METER
  all_mtxs_mtx = mutex_allocate ();
#endif
}
Ejemplo n.º 7
0
int
thread_release_dead_threads (int leave_count)
{
  thread_t *thr;
  int rc;
  long thread_killed = 0;
  thread_queue_t term;

  Q_LOCK ();
  if (_deadq.thq_count <= leave_count)
    {
      Q_UNLOCK ();
      return 0;
    }
  thread_queue_init (&term);
  while (_deadq.thq_count > leave_count)
    {
      thr = thread_queue_from (&_deadq);
      if (!thr)
	break;
      _thread_num_dead--;
      thread_queue_to (&term, thr);
    }
  Q_UNLOCK ();

  while (NULL != (thr = thread_queue_from (&term)))
    {
      thr->thr_status = TERMINATE;
      rc = pthread_cond_signal ((pthread_cond_t *) thr->thr_cv);
      CKRET (rc);
      thread_killed++;
    }
#if 0
  if (thread_killed)
    log_info ("%ld OS threads released", thread_killed);
#endif
  return thread_killed;
failed:
  GPF_T1("Thread restart failed");
  return 0;
}
Ejemplo n.º 8
0
int
allocate_port(const unsigned long id, const int new_owner)
{
 register int i;
 register int first_available=-1;

 /* Loop over all ports to see if the port has already been allocated. */
 for(i=0; i<MAX_NUMBER_OF_PORTS; i++)
 {
  /* We keep track of the first available port. This way we do not
     have to scan the table twice. */
  if ((-1 == port_table[i].owner) &&
      (-1 == first_available))
  {
   first_available=i;
  }

  /* Check if the port entry match the one we want to create. */
  if ((new_owner == port_table[i].owner) &&
      (id == port_table[i].id))
  {
   return -1;
  }
 }

 if (-1 != first_available)
 {
  /* Set the new owner and new identity. */
  port_table[first_available].owner=new_owner;
  port_table[first_available].id=id;

  /* Initially, the sender queue is  empty and there are no receiving thread. */
  port_table[first_available].receiver=-1;
  thread_queue_init(&port_table[first_available].sender_queue);

  return first_available;
 }

 /* Return -1 if we ran out of ports. */
 return -1;
}
Ejemplo n.º 9
0
//启动播放器
int Java_info_sodapanda_sodaplayer_FFmpegVideoView_openfile(JNIEnv* env,jobject obj,jstring file,jlong ptr){
	playInstance * instance = (playInstance *)ptr;
	//初始化队列
	instance->queue = malloc(sizeof(struct threadqueue));
	thread_queue_init(instance->queue);
	instance->video_queue = malloc(sizeof(struct threadqueue));
	thread_queue_init(instance->video_queue);
	instance->audio_queue = malloc(sizeof(struct threadqueue));
	thread_queue_init(instance->audio_queue);

	instance->stop=0;
	instance->timeout_flag = 0;
	instance->vs=av_malloc(sizeof (VideoState));

	LOGE("开始执行openfile\n");
	jboolean isfilenameCopy;
	const char *filename = (*env)-> GetStringUTFChars(env, file, &isfilenameCopy);
	jclass cls = (*env)->GetObjectClass(env,obj);
	instance->initAdudioTrack = (*env)->GetMethodID(env,cls,"initAdudioTrack","(I)[B");
	instance->onNativeConnected = (*env)->GetMethodID(env,cls,"onNativeConnected","()V");
	instance->finishplay = (*env)->GetMethodID(env,cls,"finishplay","()V");

	(*env)->GetJavaVM(env,&(instance->gJavaVm));
	instance->gJavaobj = (*env)->NewGlobalRef(env,obj);

	//video
	AVFormatContext *pFormatCtx =NULL;
	AVCodecContext *pCodecCtx=NULL;
	AVCodec *pCodec=NULL;
	AVFrame *pFrame =NULL;
	int videoStream;
	AVDictionary *videoOptionsDict= NULL;
	struct SwsContext *sws_ctx =NULL;
	void* buffer;
	jobject bitmap;

	//audio
	AVCodecContext *aCodecCtx=NULL;
	AVCodec *aCodec=NULL;
	int audioStream;
	AVDictionary *audioOptionsDict = NULL;
	AVFrame *audio_frame;
	audio_frame = avcodec_alloc_frame();

	av_register_all();	//注册解码器等操作
	avformat_network_init();	//初始化网络
	pFormatCtx= avformat_alloc_context();
	pFormatCtx->max_analyze_duration=1000000;//最长分析时间10000微秒
	pFormatCtx->interrupt_callback.callback = call_back;//设置中断回调函数
	pFormatCtx->interrupt_callback.opaque = instance;//中断回调函数的参数

	//开始读取线程 提前开始为了捕获到打开文件的超时
	pthread_t rtid;
	pthread_create(&rtid,NULL,getPacket,instance);

	//打开视频文件
	if(avformat_open_input(&pFormatCtx,filename, NULL, NULL)!=0){
		if(instance->stop){
			return 0;
		}
		LOGE("无法打开文件\n");
		return -1; // 无法打开视频文件
	}
	if(instance->stop){
		return 0;
	}

	// 检索视频信息
	if(avformat_find_stream_info(pFormatCtx, NULL)<0){
		LOGE("无法找到流信息\n");
		return -1;
	}

	av_dump_format(pFormatCtx, 0, filename, 0);//打印分析的视频信息

	videoStream = -1;
	audioStream = -1;

	int i =0;
	for (i=0;i<pFormatCtx->nb_streams;i++){//遍历寻找音频流和视频流
		if(videoStream<0 && pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
			videoStream = i;
			instance->vs->video_time_base = av_q2d(pFormatCtx->streams[videoStream]->time_base);
			LOGE("videostream is %d\n",videoStream);
		}
		if(audioStream<0 && pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){
			audioStream = i;
			LOGE("audiostream is %d\n",audioStream);
			instance->vs->audio_time_base = av_q2d(pFormatCtx->streams[audioStream]->time_base);
			instance->vs->sample_rate_src = pFormatCtx->streams[i]->codec->sample_rate;
			instance->vs->sample_fmt = pFormatCtx->streams[i]->codec->sample_fmt;
			instance->vs->sample_layout = pFormatCtx->streams[i]->codec->channel_layout;
			if(instance->vs->sample_rate_src <= 0){
				LOGE("Audio Sample Rate is wrong");
				return -1;
			}else{
				jbyteArray aarray = (jbyteArray)((*env)->CallObjectMethod(env,obj,instance->initAdudioTrack,instance->vs->sample_rate_src));
				instance->global_aarray = (*env)->NewGlobalRef(env,aarray);
				LOGE("initAdudioTrack返回\n");
			}
		}
	}

	if(videoStream==-1){
		LOGE("无法找到视频流");
		return -1;
	}

	//打开音频解码器
	if(audioStream != -1 && instance->vs->sample_rate_src>0){
		aCodecCtx = pFormatCtx->streams[audioStream]->codec;
		aCodec= avcodec_find_decoder(aCodecCtx->codec_id);

		if(avcodec_open2(aCodecCtx,aCodec,&audioOptionsDict)<0){
			LOGE("无法打开Audio解码器");
			return -1;
		}
	}

	//打开视频解码器
	if(videoStream != -1){
		pCodecCtx=pFormatCtx->streams[videoStream]->codec;
		pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
		if(avcodec_open2(pCodecCtx,pCodec,&videoOptionsDict)<0){
			LOGE("无法打开视频解码器\n");
			return -1;
		}
	}

	if(instance->display_height == 0 ){
		instance->display_width = pCodecCtx->width;
		instance->display_height = pCodecCtx->height;
		setAndroidWindowPix(pCodecCtx->width,pCodecCtx->height,instance);
	}

	pFrame = avcodec_alloc_frame();

	//视频转换
	sws_ctx = sws_getContext(
		pCodecCtx->width,
		pCodecCtx->height,
		pCodecCtx->pix_fmt,
		instance->display_width,
		instance->display_height,
		AV_PIX_FMT_RGBA,
		SWS_BILINEAR,
		NULL,
		NULL,
		NULL
	);

	//创建bitmap
	bitmap = createBitmap(env, instance->display_width, instance->display_height);
	AndroidBitmap_lockPixels(env, bitmap, &buffer);
	AVFrame *RGBAFrame;
	RGBAFrame = avcodec_alloc_frame();
	avpicture_fill((AVPicture *) RGBAFrame, buffer, AV_PIX_FMT_RGBA, instance->display_width, instance->display_height);

	//原始音频转换
	struct SwrContext *swr_ctx;
	swr_ctx = swr_alloc();

	av_opt_set_int(swr_ctx, "in_sample_fmt", instance->vs->sample_fmt, 0);
	av_opt_set_int(swr_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
	av_opt_set_int(swr_ctx, "in_channel_layout", instance->vs->sample_layout, 0);
	av_opt_set_int(swr_ctx, "out_channel_layout", AV_CH_LAYOUT_MONO, 0);

	swr_init(swr_ctx);

	instance->vs->RGBAFrame=RGBAFrame;
	instance->vs->buffer=buffer;
	instance->vs->pCodecCtx=pCodecCtx;
	instance->vs->pFrame=pFrame;
	instance->vs->sws_ctx=sws_ctx;
	instance->vs->videoStream=videoStream;
	instance->vs->aCodecCtx=aCodecCtx;
	instance->vs->audioStream=audioStream;
	instance->vs->audio_decode_frame=audio_frame;
	instance->vs->swr_ctx=swr_ctx;

	//视频线程
	pthread_t video_tid;
	if(videoStream!=-1){
		pthread_create(&video_tid,NULL,video_thread,instance);
	}

	//音频线程
	pthread_t audio_tid;
	if(audioStream!=-1 && instance->vs->sample_rate_src >0){
		pthread_create(&audio_tid,NULL,audio_thread,instance);
	}

	//通知android  connected to RTMPserver
	(*env)->CallVoidMethod(env,obj,instance->onNativeConnected);

	while(1){
		if(instance->stop){//关闭线程
			//队列放空表示结束
			thread_queue_add(instance->queue,NULL,-1);
			break;
		}

		AVPacket *packet_p = malloc(sizeof(AVPacket));
		//加入队列
		if(av_read_frame(pFormatCtx,packet_p)<0){//网络断开或停止视频
			thread_queue_add(instance->queue,NULL,-1);
			break;
		}

		thread_queue_add(instance->queue,packet_p,1);
	}

	LOGE("native主循环退出\n");
	thread_queue_add(instance->queue,NULL,-1);//让get线程停止
	pthread_join(rtid,NULL);
	pthread_join(video_tid,NULL);
	pthread_join(audio_tid,NULL);

	LOGE("getpacket线程环退出\n");
	thread_queue_cleanup(instance->queue,1);
	thread_queue_cleanup(instance->video_queue,1);
	thread_queue_cleanup(instance->audio_queue,1);

    av_free(instance->vs);
    av_free(RGBAFrame);
    av_free(pFrame);
    avcodec_close(pCodecCtx);
    avcodec_close(aCodecCtx);
    avformat_close_input(&pFormatCtx);
    AndroidBitmap_unlockPixels(env,bitmap);
    LOGE("清理退出\n");
    if(instance->stop){
    	return 0;
    }
    if(instance->timeout_flag){
    	return -1;
    }else{
        LOGE("执行到finishplay");
    	(*env)->CallVoidMethod(env,obj,instance->finishplay);
    	return 0;
    }
}
Ejemplo n.º 10
0
void
initialize(void)
{
 register int i;

 /* Loop over all threads in the thread table and reset the owner. */
 for(i=0; i<MAX_NUMBER_OF_THREADS; i++)
 {
  thread_table[i].data.owner=-1; /* -1 is an illegal process_table index.
                                     We use that to show that the thread
                                     is dormant. */
 }

 /* Loop over all processes in the thread table and mark them as not
    executing. */
 for(i=0; i<MAX_NUMBER_OF_PROCESSES; i++)
 {
  process_table[i].threads=0;    /* No executing process has less than 1
                                    thread. */
 }

 /* Initialize the ready queue. */
 thread_queue_init(&ready_queue);

 /* Go through the linked list of executable images and verify that they
    are correct. At the same time build the executable_table. */
 {
  const struct executable_image* image;

  for (image=ELF_images_start; 0!=image; image=image->next)
  {
   unsigned long      image_size;

   /* First calculate the size of the image. */
   if (0 != image->next)
   {
    image_size = ((char *) (image->next)) - ((char *) image) -1;
   }
   else
   {
    image_size = ((char *) ELF_images_end) - ((char *) image) - 1;
   }

   /* Check that the image is an ELF image and that it is of the
      right type. */
   if (
       /* EI_MAG0 - EI_MAG3 have to be 0x7f 'E' 'L' 'F'. */
       (image->elf_image.e_ident[EI_MAG0] != 0x7f) ||
       (image->elf_image.e_ident[EI_MAG1] != 'E') ||
       (image->elf_image.e_ident[EI_MAG2] != 'L') ||
       (image->elf_image.e_ident[EI_MAG3] != 'F') ||
       /* Check that the image is a 64-bit image. */
       (image->elf_image.e_ident[EI_CLASS] != 2) ||
       /* Check that the image is a little endian image. */
       (image->elf_image.e_ident[EI_DATA] != 1) ||
       /* And that the version of the image format is correct. */
       (image->elf_image.e_ident[EI_VERSION] != 1) ||
       /* NB: We do not check the ABI or ABI version. We really should
          but currently those fields are not set properly by the build
          tools. They are both set to zero which means: System V ABI,
          third edition. However, the ABI used is clearly not System V :-) */

       /* Check that the image is executable. */
       (image->elf_image.e_type != 2) ||
       /* Check that the image is executable on AMD64. */
       (image->elf_image.e_machine != 0x3e) ||
       /* Check that the object format is corrent. */
       (image->elf_image.e_version != 1) ||
       /* Check that the processor dependent flags are all reset. */
       (image->elf_image.e_flags != 0) ||
       /* Check that the length of t   he header is what we expect. */
       (image->elf_image.e_ehsize != sizeof(struct Elf64_Ehdr)) ||
       /* Check that the size of the program header table entry is what
          we expect. */
       (image->elf_image.e_phentsize != sizeof(struct Elf64_Phdr)) ||
       /* Check that the number of entries is reasonable. */
       (image->elf_image.e_phnum < 0) ||
       (image->elf_image.e_phnum > 8) ||
       /* Check that the entry point is within the image. */
       (image->elf_image.e_entry < 0) ||
       (image->elf_image.e_entry >= image_size) ||
       /* Finally, check that the program header table is within the image. */
       (image->elf_image.e_phoff > image_size) ||
       ((image->elf_image.e_phoff +
         image->elf_image.e_phnum * sizeof(struct Elf64_Phdr)) > image_size )
      )

   {
    /* There is something wrong with the image. */
    while (1)
    {
     kprints("Kernel panic! Corrupt executable image.\n");
    }
    continue;
   }

   /* Now check the program header table. */
   {
    int                program_header_index;
    struct Elf64_Phdr* program_header = ((struct Elf64_Phdr*)
                                         (((char*) &(image->elf_image)) +
                                          image->elf_image.e_phoff));
    unsigned long      memory_footprint_size = 0;

    for (program_header_index = 0;
         program_header_index < image->elf_image.e_phnum;
         program_header_index++)
    {
     /* First sanity check the entry. */
     if (
         /* Check that the segment is a type we can handle. */
         (program_header[program_header_index].p_type < 0) ||
         (!((program_header[program_header_index].p_type == PT_NULL) ||
            (program_header[program_header_index].p_type == PT_LOAD) ||
            (program_header[program_header_index].p_type == PT_PHDR))) ||
         /* Look more carefully into loadable segments. */
         ((program_header[program_header_index].p_type == PT_LOAD) &&
           /* Check if any flags that we can not handle is set. */
          (((program_header[program_header_index].p_flags & ~7) != 0) ||
           /* Check if sizes and offsets look sane. */
           (program_header[program_header_index].p_offset < 0) ||
           (program_header[program_header_index].p_vaddr < 0) ||
           (program_header[program_header_index].p_filesz < 0) ||
           (program_header[program_header_index].p_memsz < 0) ||
          /* Check if the segment has an odd size. We require the
             segement size to be an even multiple of 8. */
           (0 != (program_header[program_header_index].p_memsz&7)) ||
           (0 != (program_header[program_header_index].p_filesz&7)) ||
           /* Check if the segment goes beyond the image. */
           ((program_header[program_header_index].p_offset +
             program_header[program_header_index].p_filesz) > image_size)))
        )
     {
      while (1)
      {
       kprints("Kernel panic! Corrupt segment.\n");
      }
     }

     /* Check that all PT_LOAD segments are contigous starting from
        address 0. Also, calculate the memory footprint of the image. */
     if (program_header[program_header_index].p_type == PT_LOAD)
     {
      if (program_header[program_header_index].p_vaddr !=
          memory_footprint_size)
      {
       while (1)
       {
        kprints("Kernel panic! Executable image has illegal memory layout.\n");
       }
      }

      memory_footprint_size += program_header[program_header_index].p_memsz;
     }
    }

    executable_table[executable_table_size].memory_footprint_size =
     memory_footprint_size;
   }

   executable_table[executable_table_size].elf_image = &(image->elf_image);
   executable_table_size += 1;

   kprints("Found an executable image.\n");

   if (executable_table_size >= MAX_NUMBER_OF_PROCESSES)
   {
    while (1)
    {
     kprints("Kernel panic! Too many executable images found.\n");
    }
   }
  }
 }

 /* Check that actually some executable files are found. Also check that the
    thread structure is of the right size. The assembly code will break if it
    is not. */

 if ((0 >= executable_table_size) || (1024 != sizeof(union thread)))
 {
  while (1)
  {
   kprints("Kernel panic! Can not boot.\n");
  }
 }

 /* Start running the first program in the executable table. */

 /* Use the ELF program header table and copy the right portions of the
    image to memory. This is done by prepare_process. */
 {
  struct prepare_process_return_value prepare_process_ret_val = 
   prepare_process(executable_table[0].elf_image,
                   0,
                   executable_table[0].memory_footprint_size);

  if (0 == prepare_process_ret_val.first_instruction_address)
  {
   while (1)
   {
    kprints("Kernel panic! Can not start process 0!\n");
   }
  }

  /* Start executable program 0 as process 0. At this point, there are no
     processes so we can just grab entry 0 and use it. */
  process_table[0].parent=-1;    /* We put -1 to indicate that there is no
                                    parent process. */
  process_table[0].threads=1;

  /* We need a thread. We just take the first one as no threads are running or
     have been allocated at this point. */
  thread_table[0].data.owner=0;  /* 0 is the index of the first process. */

  /* We reset all flags and enable interrupts */
  thread_table[0].data.registers.integer_registers.rflags=0x200;

  /* And set the start address. */
  thread_table[0].data.registers.integer_registers.rip =
   prepare_process_ret_val.first_instruction_address;

  /* Finally we set the current thread. */
  cpu_private_data.thread_index = 0;
  //cpu_private_data.ticks_left_of_time_slice = TIMESLICE_SIZE;
 }

 /* Set up the timer hardware to generate interrupts 200 times a second. */
 outb(0x43, 0x36);
 outb(0x40, 78);
 outb(0x40, 23);

 /* Now we set up the interrupt controller to allow timer interrupts. */
 outb(0x20, 0x11);
 outb(0xA0, 0x11);

 outb(0x21, 0x20);
 outb(0xA1, 0x28);

 outb(0x21, 1<<2);
 outb(0xA1, 2);

 outb(0x21, 1);
 outb(0xA1, 1);

 outb(0x21, 0xfe);
 outb(0xA1, 0xff);

 kprints("\n\n\nThe kernel has booted!\n\n\n");
 /* Now go back to the assembly language code and let the process run. */
}
Ejemplo n.º 11
0
/* methods applying to semaphores */
void thread_semaphore_init( struct thread_semaphore * s, int v )
/* call this to initialize semaphore s to a count of v */
{
	s->count = v;
        thread_queue_init( &s->queue );
}
Ejemplo n.º 12
0
void
initialize(void)
{
 register int i;

 /* Loop over all threads in the thread table and reset the owner. */
 for(i=0; i<MAX_NUMBER_OF_THREADS; i++)
 {
  thread_table[i].data.owner=-1; /* -1 is an illegal process_table index.
                                     We use that to show that the thread
                                     is dormant. */
 }

 /* Loop over all processes in the thread table and mark them as not
    executing. */
 for(i=0; i<MAX_NUMBER_OF_PROCESSES; i++)
 {
  process_table[i].threads=0;    /* No executing process has less than 1
                                    thread. */
 }

 /* Initialize the ready queue. */
 thread_queue_init(&ready_queue);

 /* Initialize the list of blocked threads waiting for the keyboard. */
 thread_queue_init(&keyboard_blocked_threads);

 /* Calculate the number of pages. */
 memory_pages = memory_size/(4*1024);

 {
  /* Calculate the number of frames occupied by the kernel and executable
     images. */
  const register int k=first_available_memory_byte/(4*1024);

  /* Mark the pages that are used by the kernel or executable images as taken
    by the kernel (-2 in the owner field). */
  for(i=0; i<k; i++)
  {
   page_frame_table[i].owner=-2;
   page_frame_table[i].free_is_allowed=0;
  }

  /* Loop over all the rest page frames and mark them as free (-1 in owner
     field). */
  for(i=k; i<memory_pages; i++)
  {
   page_frame_table[i].owner=-1;
   page_frame_table[i].free_is_allowed=1;
  }

  /* Mark any unusable pages as taken by the kernel. */
  for(i=memory_pages; i<MAX_NUMBER_OF_FRAMES; i++)
  {
   page_frame_table[i].owner=-2;
   page_frame_table[i].free_is_allowed=0;
  }
 }

 /* Go through the linked list of executable images and verify that they
    are correct. At the same time build the executable_table. */
 {
  const struct executable_image* image;

  for (image=ELF_images_start; 0!=image; image=image->next)
  {
   unsigned long      image_size;

   /* First calculate the size of the image. */
   if (0 != image->next)
   {
    image_size = ((char *) (image->next)) - ((char *) image) -1;
   }
   else
   {
    image_size = ((char *) ELF_images_end) - ((char *) image) - 1;
   }

   /* Check that the image is an ELF image and that it is of the
      right type. */
   if (
       /* EI_MAG0 - EI_MAG3 have to be 0x7f 'E' 'L' 'F'. */
       (image->elf_image.e_ident[EI_MAG0] != 0x7f) ||
       (image->elf_image.e_ident[EI_MAG1] != 'E') ||
       (image->elf_image.e_ident[EI_MAG2] != 'L') ||
       (image->elf_image.e_ident[EI_MAG3] != 'F') ||
       /* Check that the image is a 64-bit image. */
       (image->elf_image.e_ident[EI_CLASS] != 2) ||
       /* Check that the image is a little endian image. */
       (image->elf_image.e_ident[EI_DATA] != 1) ||
       /* And that the version of the image format is correct. */
       (image->elf_image.e_ident[EI_VERSION] != 1) ||
       /* NB: We do not check the ABI or ABI version. We really should
          but currently those fields are not set properly by the build
          tools. They are both set to zero which means: System V ABI,
          third edition. However, the ABI used is clearly not System V :-) */

       /* Check that the image is executable. */
       (image->elf_image.e_type != 2) ||
       /* Check that the image is executable on AMD64. */
       (image->elf_image.e_machine != 0x3e) ||
       /* Check that the object format is corrent. */
       (image->elf_image.e_version != 1) ||
       /* Check that the processor dependent flags are all reset. */
       (image->elf_image.e_flags != 0) ||
       /* Check that the length of t   he header is what we expect. */
       (image->elf_image.e_ehsize != sizeof(struct Elf64_Ehdr)) ||
       /* Check that the size of the program header table entry is what
          we expect. */
       (image->elf_image.e_phentsize != sizeof(struct Elf64_Phdr)) ||
       /* Check that the number of entries is reasonable. */
       (image->elf_image.e_phnum < 0) ||
       (image->elf_image.e_phnum > 8) ||
       /* Check that the entry point is within the image. */
       (image->elf_image.e_entry < 0) ||
       (image->elf_image.e_entry >= image_size) ||
       /* Finally, check that the program header table is within the image. */
       (image->elf_image.e_phoff > image_size) ||
       ((image->elf_image.e_phoff +
         image->elf_image.e_phnum * sizeof(struct Elf64_Phdr)) > image_size )
      )

   {
    /* There is something wrong with the image. */
    while (1)
    {
     kprints("Kernel panic! Corrupt executable image.\n");
    }
    continue;
   }

   /* Now check the program header table. */
   {
    int                program_header_index;
    struct Elf64_Phdr* program_header = ((struct Elf64_Phdr*)
                                         (((char*) &(image->elf_image)) +
                                          image->elf_image.e_phoff));
    unsigned long      memory_footprint_size = 0;

    for (program_header_index = 0;
         program_header_index < image->elf_image.e_phnum;
         program_header_index++)
    {
     /* First sanity check the entry. */
     if (
         /* Check that the segment is a type we can handle. */
         (program_header[program_header_index].p_type < 0) ||
         (!((program_header[program_header_index].p_type == PT_NULL) ||
            (program_header[program_header_index].p_type == PT_LOAD) ||
            (program_header[program_header_index].p_type == PT_PHDR))) ||
         /* Look more carefully into loadable segments. */
         ((program_header[program_header_index].p_type == PT_LOAD) &&
           /* Check if any flags that we can not handle is set. */
          (((program_header[program_header_index].p_flags & ~7) != 0) ||
           /* Check if sizes and offsets look sane. */
           (program_header[program_header_index].p_offset < 0) ||
           (program_header[program_header_index].p_vaddr < 0) ||
           (program_header[program_header_index].p_filesz < 0) ||
           (program_header[program_header_index].p_memsz < 0) ||
          /* Check if the segment has an odd size. We require the
             segment size to be an even multiple of 8. */
           (0 != (program_header[program_header_index].p_memsz&7)) ||
           (0 != (program_header[program_header_index].p_filesz&7)) ||
           /* Check if the segment goes beyond the image. */
           ((program_header[program_header_index].p_offset +
             program_header[program_header_index].p_filesz) > image_size)))
        )
     {
      while (1)
      {
       kprints("Kernel panic! Corrupt segment.\n");
      }
     }

     /* Check that all PT_LOAD segments are contiguous starting from
        address 0. Also, calculate the memory footprint of the image. */
     if (program_header[program_header_index].p_type == PT_LOAD)
     {
      if (program_header[program_header_index].p_vaddr !=
          memory_footprint_size)
      {
       while (1)
       {
        kprints("Kernel panic! Executable image has illegal memory layout.\n");
       }
      }

      memory_footprint_size += program_header[program_header_index].p_memsz;
     }
    }

    executable_table[executable_table_size].memory_footprint_size =
     memory_footprint_size;
   }

   executable_table[executable_table_size].elf_image = &(image->elf_image);
   executable_table_size += 1;

   kprints("Found an executable image.\n");

   if (executable_table_size >= MAX_NUMBER_OF_PROCESSES)
   {
    while (1)
    {
     kprints("Kernel panic! Too many executable images found.\n");
    }
   }
  }
 }

 /* Check that actually some executable files are found. Also check that the
    thread structure is of the right size. The assembly code will break if it
    is not. Finally, initialize memory protection. You will implement memory
    protection in task A4. */

 if ((0 >= executable_table_size) ||
     (1024 != sizeof(union thread)))
 {
  while (1)
  {
   kprints("Kernel panic! Can not boot.\n");
  }
 }

 initialize_memory_protection();
 initialize_ports();
 initialize_thread_synchronization();

 /* All sub-systems are now initialized. Kernel areas can now get the right
    memory protection. */

 {
  /* Use the kernel's ELF header. */
  struct Elf32_Phdr* program_header = ((struct Elf32_Phdr*)
                                       (((char*) (0x00100000)) +
                                        ((struct Elf32_Ehdr*)0x00100000)->
                                          e_phoff));

  /* Traverse the program header. */
  short              number_of_program_header_entries =
                      ((struct Elf32_Ehdr*)0x00100000)->e_phnum;
  int                i;
  for(i=0; i<number_of_program_header_entries; i++)
  {
   if (PT_LOAD == program_header[i].p_type)
   {
    /* Set protection on each segment. */

    update_memory_protection(kernel_page_table_root,
                             program_header[i].p_vaddr,
                             program_header[i].p_memsz,
                             (program_header[i].p_flags&7) | PF_KERNEL);
   }
  }
 }

 /* Start running the first program in the executable table. */

 /* Use the ELF program header table and copy the right portions of the
    image to memory. This is done by prepare_process. */

 {
  struct prepare_process_return_value prepare_process_ret_val =
   prepare_process(executable_table[0].elf_image,
                   0,
                   executable_table[0].memory_footprint_size);

  if (0 == prepare_process_ret_val.first_instruction_address)
  {
   while (1)
   {
    kprints("Kernel panic! Can not start process 0!\n");
   }
  }

  /* Start executable program 0 as process 0. At this point, there are no
     processes so we can just grab entry 0 and use it. */
  process_table[0].parent=-1;    /* We put -1 to indicate that there is no
                                    parent process. */
  process_table[0].threads=1;

  /*  all processes should start with an allocated port with id zero */
  if (-1 == allocate_port(0,0))
  {
   while(1)
   {
    kprints("Kernel panic! Can not initialize the IPC system!\n");
   }
  }

  /* Set the page table address. */
  process_table[0].page_table_root =
   prepare_process_ret_val.page_table_address;
  cpu_private_data.page_table_root =
   prepare_process_ret_val.page_table_address;

  /* We need a thread. We just take the first one as no threads are running or
     have been allocated at this point. */
  thread_table[0].data.owner=0;  /* 0 is the index of the first process. */

  /* We reset all flags and enable interrupts */
  thread_table[0].data.registers.integer_registers.rflags=0x200;

  /* And set the start address. */
  thread_table[0].data.registers.integer_registers.rip =
   prepare_process_ret_val.first_instruction_address;

  /* Finally we set the current thread. */
  cpu_private_data.thread_index = 0;
 }

 /* Set up the timer hardware to generate interrupts 200 times a second. */
 outb(0x43, 0x36);
 outb(0x40, 78);
 outb(0x40, 23);

 /* Set up the keyboard controller. */
 
 /* Empty the keyboard buffer. */
 {
  register unsigned char status_byte;
  do
  {
   status_byte=inb(0x64);
   if ((status_byte&3)==1)
   {
    inb(0x60);
   }
  } while((status_byte&0x3)!=0x0);
 }

 /* Change the command byte to enable interrupts. */
 outb(0x64, 0x20);
 {
  register unsigned char keyboard_controller_command_byte;

  {
   register unsigned char status_byte;
   do
   {
    status_byte=inb(0x64);
   } while((status_byte&3)!=1);
  }

  keyboard_controller_command_byte=inb(0x60);

  /* Enable keyboard interrupts. */
  keyboard_controller_command_byte|=1;

  kprints("Keyboard controller command byte:");
  kprinthex(keyboard_controller_command_byte);
  kprints("\n");

  outb(0x64, 0x60);
  outb(0x60, keyboard_controller_command_byte);

  /* Wait until command is done. */
  {
   register unsigned char status_byte;
   do
   {
    status_byte=inb(0x64);
   } while((status_byte&0x2)!=0x0);
  }
 } 

 /* Now we set up the interrupt controller to allow timer and keyboard 
    interrupts. */
 outb(0x20, 0x11);
 outb(0xA0, 0x11);

 outb(0x21, 0x20);
 outb(0xA1, 0x28);

 outb(0x21, 1<<2);
 outb(0xA1, 2);

 outb(0x21, 1);
 outb(0xA1, 1);

 outb(0x21, 0xfc);
 outb(0xA1, 0xff);

 clear_screen();

 kprints("\n\n\nThe kernel has booted!\n\n\n");

 /* Now go back to the assembly language code and let the process run. */
}
    }
}


int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
{
    int ret;
    int sfd;
    int efd;

    struct epoll_event event;
    struct epoll_event *events;

    ALOGI("OpenImmVibed starting");

    ret = thread_queue_init(&work_queue);
    if (ret) {
        ALOGE("error initializing work queue: ret=%d", ret);
        return 1;
    }

    ret = pthread_create(&worker_thread, NULL, worker_thread_proc, &work_queue);
    if (ret) {
        ALOGE("error creating worker thread: ret=%d", ret);
        return 1;
    }

    fd = immvibe_open(&ret);
    if (!fd) {
        ALOGE("error opening immvibe driver: errno=%d", ret);
        return 1;