VCOS_STATUS_T vcos_init(void)
{
   VCOS_STATUS_T st = VCOS_SUCCESS;

#ifdef HAVE_MTRACE
   // enable glibc memory debugging, if the environment
   // variable MALLOC_TRACE names a valid file.
   mtrace();
#endif

   vcos_mutex_create(&lock, "global_lock");

   vcos_demand(pthread_key_create(&_vcos_thread_current_key, NULL) == 0);

   /* Initialise a VCOS wrapper for the thread which called vcos_init. */
   vcos_semaphore_create(&vcos_thread_main.suspend, NULL, 0);
   vcos_thread_main.thread = pthread_self();
   pthread_setspecific(_vcos_thread_current_key, &vcos_thread_main);

   st = vcos_msgq_init();
   vcos_assert(st == VCOS_SUCCESS);

   vcos_logging_init();

   return st;
}
/***********************************************************
 * Name: os_cond_wait
 *
 * Arguments:  OS_COND_T *cond,
 *             OS_SEMAPHORE_T *semaphore
 *
 * Description: Routine to wait for a condition variable
 *              to be signalled. Semaphore is released
 *              while waiting. The same semaphore must
 *              always be used.
 *
 * Returns: int32_t - success == 0
 *
 ***********************************************************/
int32_t os_cond_wait( OS_COND_T *cond, OS_SEMAPHORE_T *semaphore )
{
   int32_t success = -1;
    
   if (cond && semaphore)
   {
      COND_WAITER_T w;
      COND_WAITER_T *p, **prev;
       
      // Check the API is being followed
      os_assert((*cond)->semaphore == semaphore && os_semaphore_obtained(semaphore));
      
      // Fill in a new waiter structure allocated on our stack
      w.next = NULL;
      vcos_demand(vcos_event_create(&w.latch, NULL) == VCOS_SUCCESS);
      
      // Add it to the end of the condvar's wait queue (we wake first come, first served)
      prev = &(*cond)->waiters;
      p = (*cond)->waiters;
      while (p)
         prev = &p->next, p = p->next;
      *prev = &w;

      // Ready to go to sleep now
      success = os_semaphore_release(semaphore);
      os_assert(success == 0);

      vcos_event_wait(&w.latch);

      success = os_semaphore_obtain(semaphore);
      os_assert(success == 0);
   }
   
   return success;
}
Esempio n. 3
0
void vchiq_release_message(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header)
{
   SLOT_T *s = (SLOT_T *) header;
   VCHIQ_WRAPPER_T *st = (VCHIQ_WRAPPER_T *) s->hdr.u.slot;
   int slot = s-st->slot;
   
   vcos_demand(slot < SLOT_NUM);

   st->slot_free |= 1<<slot; 
}
Esempio n. 4
0
void vchiq_wrapper_callback(void *callback_param,
                            VCHI_CALLBACK_REASON_T reason,
                            void *handle)
{
   VCHIQ_WRAPPER_T *st = (VCHIQ_WRAPPER_T *) callback_param;

   switch(reason) {
   case VCHI_CALLBACK_MSG_AVAILABLE:
      {
         void *data;
         uint32_t size;
         int count = 0;

         while(vchi_msg_peek(st->vchi_handle, &data, &size, 0) == 0)
         {
            SLOT_T *s;
            int slot = 0;
            vcos_demand(st->slot_free != 0);
            while(!((1<<slot) & st->slot_free))
               slot++;
            
            s = st->slot+slot;
            st->slot_free &= ~(1<<slot);
            s->hdr.u.slot = (VCHIQ_SLOT_T *) st; // store this away so we can release the slot properly
            s->hdr.size = size;
            
            vcos_demand(s->hdr.size <= SLOT_SIZE);
            memcpy(s->data, data, s->hdr.size);
            vchi_msg_remove(st->vchi_handle);
            
            st->callback(VCHIQ_MESSAGE_AVAILABLE, (VCHIQ_HEADER_T *) s, st->userdata, NULL);
         }
         break;
      }
   case VCHI_CALLBACK_BULK_RECEIVED:
      {
         // this doesn't seem to be used, but leave it in anyway
         st->callback(VCHIQ_BULK_RECEIVE_DONE, NULL, st->userdata, NULL);
         break;
      }
   }
}
Esempio n. 5
0
void vchiq_queue_message(VCHIQ_STATE_T *state, int fourcc, const VCHIQ_ELEMENT_T *elements, int count)
{
   VCHIQ_WRAPPER_T *st = wrapper_list;
   VCHI_MSG_VECTOR_EX_T vec[4];
   int i;

   while(st != NULL && (st->state != state || st->fourcc != fourcc))
      st = st->next;

   vcos_demand(st != NULL);
   vcos_demand(count <= 4);

   for(i=0; i<count; i++)
   {
      vec[i].type = VCHI_VEC_POINTER;
      vec[i].u.ptr.vec_base = elements[i].data;
      vec[i].u.ptr.vec_len = elements[i].size;
   }

   vchi_msg_queuev_ex(st->vchi_handle, vec, count, VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL);
}
Esempio n. 6
0
// if handle==MEM_HANDLE_INVALID: data is a pointer, size is length
// if handle!=MEM_HANDLE_INVALID: data is int, offset from handle base, size is length
void vchiq_queue_bulk_transmit(VCHIQ_STATE_T *state, int fourcc, VCHI_MEM_HANDLE_T handle, const void *data, int size, void *userdata)
{
   VCHIQ_WRAPPER_T *st = wrapper_list;

   while(st != NULL && (st->state != state || st->fourcc != fourcc))
      st = st->next;

   vcos_demand(st != NULL);

   if(handle == MEM_HANDLE_INVALID)
      vchi_bulk_queue_transmit(st->vchi_handle, data, size, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
   else
      vchi_bulk_queue_transmit_reloc(st->vchi_handle, handle, (uint32_t) data, size, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
}
Esempio n. 7
0
// if handle==MEM_HANDLE_INVALID: data is a pointer, size is length
// if handle!=MEM_HANDLE_INVALID: data is int, offset from handle base, size is length
void vchiq_queue_bulk_receive(VCHIQ_STATE_T *state, int fourcc, VCHI_MEM_HANDLE_T handle, void *data, int size, void *userdata)
{
   VCHIQ_WRAPPER_T *st = wrapper_list;

   while(st != NULL && (st->state != state || st->fourcc != fourcc))
      st = st->next;

   vcos_demand(st != NULL);

   if(handle == MEM_HANDLE_INVALID)
      vchi_bulk_queue_receive(st->vchi_handle, data, size, VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL);
   else
      vchi_bulk_queue_receive_reloc(st->vchi_handle, handle, (uint32_t) data, size, VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL);

   st->callback(VCHIQ_BULK_RECEIVE_DONE, NULL, st->userdata, NULL);
}
Esempio n. 8
0
/* OMX_Init */
OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void)
{
   VCOS_STATUS_T status;
   OMX_ERRORTYPE err = OMX_ErrorNone;

   status = vcos_once(&once, initOnce);
   vcos_demand(status == VCOS_SUCCESS);

   vcos_mutex_lock(&lock);

   if(coreInit == 0)
   {
      // we need to connect via an ILCS connection to VideoCore
      VCHI_INSTANCE_T initialise_instance;
      VCHI_CONNECTION_T *connection;
      ILCS_CONFIG_T config;

      vc_host_get_vchi_state(&initialise_instance, &connection);

      vcilcs_config(&config);

      ilcs_service = ilcs_init((VCHIQ_INSTANCE_T) initialise_instance, (void **) &connection, &config, 0);

      if(ilcs_service == NULL)
      {
         err = OMX_ErrorHardware;
         goto end;
      }

      coreInit = 1;
   }
   else
      coreInit++;

end:
   vcos_mutex_unlock(&lock);
   return err;
}
Esempio n. 9
0
/** Render text.
  *
  * FIXME: Not at all optimal - re-renders each time.
  * FIXME: Not UTF-8 aware
  * FIXME: better caching
  */
VCOS_STATUS_T gx_priv_render_text( GX_DISPLAY_T *disp,
                                   GRAPHICS_RESOURCE_HANDLE res,
                                   uint32_t x,
                                   uint32_t y,
                                   uint32_t width,
                                   uint32_t height,
                                   uint32_t fg_colour,
                                   uint32_t bg_colour,
                                   const char *text,
                                   uint32_t text_length,
                                   uint32_t text_size )
{
   VGfloat vg_colour[4];
   VGFT_FONT_T *font;
   VGPaint fg;
   GX_CLIENT_STATE_T save;
   VCOS_STATUS_T status = VCOS_SUCCESS;
   int clip = 1;

   vcos_demand(inited); // has gx_font_init() been called?

   gx_priv_save(&save, res);

   if (width == GRAPHICS_RESOURCE_WIDTH &&
       height == GRAPHICS_RESOURCE_HEIGHT)
   {
      clip = 0;
   }

   width = (width == GRAPHICS_RESOURCE_WIDTH) ? res->width : width;
   height = (height == GRAPHICS_RESOURCE_HEIGHT) ? res->height : height;
   font = find_font(text, text_size);
   if (!font)
   {
      status = VCOS_ENOMEM;
      goto finish;
   }

   // setup the clipping rectangle
   if (clip)
   {
      VGint coords[] = {x,y,width,height};
      vgSeti(VG_SCISSORING, VG_TRUE);
      vgSetiv(VG_SCISSOR_RECTS, 4, coords);
   }

   // setup the background colour if needed
   if (bg_colour != GRAPHICS_TRANSPARENT_COLOUR)
   {
      int err;
      VGfloat rendered_w, rendered_h;
      VGfloat vg_bg_colour[4];

      // setup the background colour...
      gx_priv_colour_to_paint(bg_colour, vg_bg_colour);
      vgSetfv(VG_CLEAR_COLOR, 4, vg_bg_colour);

      // fill in a rectangle...
      vgft_get_text_extents(font, text, text_length, (VGfloat)x, (VGfloat)y, &rendered_w, &rendered_h);

      if ( ( 0 < (VGint)rendered_w ) && ( 0 < (VGint)rendered_h ) )
      {
         vgClear(x, y, (VGint)rendered_w, (VGint)rendered_h);
         err = vgGetError();
         if (err)
         {
            GX_LOG("Error %d clearing bg text %d %d %g %g",
                   err, x, y, rendered_w, rendered_h);
            vcos_assert(0);
         } // if
      } // if
   } // if
   // setup the foreground colour
   fg = vgCreatePaint();
   if (!fg)
   {
      status = VCOS_ENOMEM;
      goto finish;
   }

   // draw the foreground text
   vgSetParameteri(fg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
   gx_priv_colour_to_paint(fg_colour, vg_colour);
   vgSetParameterfv(fg, VG_PAINT_COLOR, 4, vg_colour);
   vgSetPaint(fg, VG_FILL_PATH);

   vgft_font_draw(font, (VGfloat)x, (VGfloat)y, text, text_length, VG_FILL_PATH);

   vgDestroyPaint(fg);

   vcos_assert(vgGetError() == 0);
   vgSeti(VG_SCISSORING, VG_FALSE);

finish:
   gx_priv_restore(&save);

   return status;
}
VCOS_STATUS_T vcos_thread_create(VCOS_THREAD_T *thread,
                                 const char *name,
                                 VCOS_THREAD_ATTR_T *attrs,
                                 VCOS_THREAD_ENTRY_FN_T entry,
                                 void *arg)
{
   VCOS_STATUS_T st;
   pthread_attr_t pt_attrs;
   VCOS_THREAD_ATTR_T *local_attrs = attrs ? attrs : &default_attrs;

   int rc = pthread_attr_init(&pt_attrs);
   if (rc < 0)
      return VCOS_ENOMEM;

   st = vcos_semaphore_create(&thread->suspend, NULL, 0);
   if (st != VCOS_SUCCESS)
   {
      pthread_attr_destroy(&pt_attrs);
      return st;
   }

   thread->task_timer.pfn = NULL; /* Not initialised */

   pthread_attr_setstacksize(&pt_attrs, local_attrs->ta_stacksz);
#if VCOS_CAN_SET_STACK_ADDR
   if (local_attrs->ta_stackaddr)
   {
      pthread_attr_setstackaddr(&pt_attrs, local_attrs->ta_stackaddr);
   }
#else
   vcos_demand(local_attrs->ta_stackaddr == 0);
#endif

   /* pthread_attr_setpriority(&pt_attrs, local_attrs->ta_priority); */
   
   vcos_assert(local_attrs->ta_stackaddr == 0); /* Not possible */

   thread->entry = entry;
   thread->arg = arg;
   thread->legacy = local_attrs->legacy;

   if (name)
   {
	   strncpy(thread->name, name, sizeof(thread->name)-1);
	   thread->name[sizeof(thread->name)-1] = '\0';
   }
   else
   {
	   thread->name[0] = '\0';
   }

   rc = pthread_create(&thread->thread, &pt_attrs, vcos_thread_entry, thread);

   pthread_attr_destroy(&pt_attrs);

   memset(thread->at_exit, 0, sizeof(thread->at_exit));

   if (rc < 0)
   {
      vcos_semaphore_delete(&thread->suspend);
      return VCOS_ENOMEM;
   }
   else
   {
      return VCOS_SUCCESS;
   }
}
void os_cond_init(void)
{
   vcos_assert(vcos_cv_inited++ == 0);
   vcos_demand(vcos_mutex_create(&cond_latch,NULL) == VCOS_SUCCESS);
}
Esempio n. 12
0
/* Atomic creation of lock protecting shared state */
static void initOnce(void)
{
   VCOS_STATUS_T status;
   status = vcos_mutex_create(&lock, VCOS_FUNCTION);
   vcos_demand(status == VCOS_SUCCESS);
}
Esempio n. 13
0
VCOS_STATUS_T vcos_generic_blockpool_init(VCOS_BLOCKPOOL_T *pool,
      VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
      void *start, VCOS_UNSIGNED pool_size, VCOS_UNSIGNED align,
      VCOS_UNSIGNED flags, const char *name)
{
   VCOS_STATUS_T status = VCOS_SUCCESS;

   vcos_unused(name);
   vcos_unused(flags);

   vcos_log_trace(
         "%s: pool %p num_blocks %d block_size %d start %p pool_size %d name %p",
         VCOS_FUNCTION, pool, num_blocks, block_size, start, pool_size, name);

   vcos_demand(pool);
   vcos_demand(start);
   vcos_assert((block_size > 0));
   vcos_assert(num_blocks > 0);

   if (! align)
      align = VCOS_BLOCKPOOL_ALIGN_DEFAULT;

   if (align & 0x3)
   {
      vcos_log_error("%s: invalid alignment %d", VCOS_FUNCTION, align);
      return VCOS_EINVAL;
   }

   if (VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align) > pool_size)
   {
      vcos_log_error("%s: Pool is too small" \
            " num_blocks %d block_size %d align %d"
            " pool_size %d required size %d", VCOS_FUNCTION,
            num_blocks, block_size, align,
            pool_size, (int) VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align));
      return VCOS_ENOMEM;
   }

   status = vcos_mutex_create(&pool->mutex, "vcos blockpool mutex");
   if (status != VCOS_SUCCESS)
      return status;

   pool->block_data_size = block_size;

   /* TODO - create flag that if set forces the header to be in its own cache
    * line */
   pool->block_size = VCOS_BLOCKPOOL_ROUND_UP(pool->block_data_size +
         (align >= 4096 ? 32 : 0) +
         sizeof(VCOS_BLOCKPOOL_HEADER_T), align);

   pool->magic = VCOS_BLOCKPOOL_MAGIC;
   pool->num_subpools = 1;
   pool->num_extension_blocks = 0;
   pool->align = align;
   memset(pool->subpools, 0, sizeof(pool->subpools));

   vcos_generic_blockpool_subpool_init(pool, &pool->subpools[0], start,
         pool_size, num_blocks, align, VCOS_BLOCKPOOL_SUBPOOL_FLAG_NONE);

   return status;
}