Esempio n. 1
0
/* Wait for a condition, putting thread into blocked state.  Fails if:
    - condp has not been initialized
    - thread doesn't hold mutexp
    - thread is blocked on some other object
    - thread is already blocked on mutex
 */
void VG_(tm_cond_wait)(ThreadId tid, Addr condp, Addr mutexp)
{
   struct thread *th = thread_get(tid);
   struct mutex *mx;
   struct condvar *cv;
   struct condvar_waiter *waiter;

   /* Condvar must exist */
   cv = condvar_check_initialized(tid, condp, "waiting");

   /* Mutex must exist */
   mx = mutex_check_initialized(tid, mutexp, "waiting on condvar");

   /* Thread must own mutex */
   if (mx->state != MX_Locked) {
      mutex_report(tid, mutexp, MXE_NotLocked, "waiting on condvar");
      VG_(tm_mutex_trylock)(tid, mutexp);
      VG_(tm_mutex_acquire)(tid, mutexp);
   } else if (mx->owner != tid) {
      mutex_report(tid, mutexp, MXE_NotOwner, "waiting on condvar");
      mx->owner = tid;
   }

   /* Thread must not be already waiting for condvar */
   waiter = get_waiter(cv, tid);
   if (waiter != NULL)
      condvar_report(tid, condp, CVE_Blocked, "waiting");
   else {
      waiter = VG_(arena_malloc)(VG_AR_CORE, sizeof(*waiter));
      waiter->condvar = cv;
      waiter->mutex = mx;
      waiter->next = cv->waiters;
      cv->waiters = waiter;
   }

   /* Thread is now blocking on condvar */
   do_thread_block_condvar(th, cv);

   /* (half) release mutex */
   VG_(tm_mutex_tryunlock)(tid, mutexp);
}
Esempio n. 2
0
/** Send a message and wait for a reply.
  *
  * @param client       client to send message for
  * @param msg_header   message vchiq_header to send
  * @param size         length of message, including header
  * @param msgid        message id
  * @param dest         destination for reply
  * @param destlen      size of destination, updated with actual length
  * @param send_dummy_bulk whether to send a dummy bulk transfer
  */
MMAL_STATUS_T mmal_vc_sendwait_message(struct MMAL_CLIENT_T *client,
                                       mmal_worker_msg_header *msg_header,
                                       size_t size,
                                       uint32_t msgid,
                                       void *dest,
                                       size_t *destlen,
                                       MMAL_BOOL_T send_dummy_bulk)
{
   MMAL_STATUS_T ret;
   MMAL_WAITER_T *waiter;
   VCHIQ_STATUS_T vst;
   VCHIQ_ELEMENT_T elems[] = {{msg_header, size}};

   vcos_assert(size >= sizeof(mmal_worker_msg_header));
   vcos_assert(dest);

   if (!client->inited)
   {
      vcos_assert(0);
      return MMAL_EINVAL;
   }

   if (send_dummy_bulk)
      vcos_mutex_lock(&client->bulk_lock);

   waiter = get_waiter(client);
   msg_header->msgid  = msgid;
   msg_header->u.waiter = waiter;
   msg_header->magic  = MMAL_MAGIC;

   waiter->dest    = dest;
   waiter->destlen = *destlen;
   LOG_TRACE("wait %p, reply to %p", waiter, dest);
   mmal_vc_use_internal(client);

   vst = vchiq_queue_message(client->service, elems, 1);

   if (vst != VCHIQ_SUCCESS)
   {
      ret = MMAL_EIO;
      if (send_dummy_bulk)
        vcos_mutex_unlock(&client->bulk_lock);
      goto fail_msg;
   }

   if (send_dummy_bulk)
   {
      uint32_t data_size = 8;
      /* The data is just some dummy bytes so it's fine for it to be static */
      static uint8_t data[8];
      vst = vchiq_queue_bulk_transmit(client->service, data, data_size, msg_header);

      vcos_mutex_unlock(&client->bulk_lock);

      if (!vcos_verify(vst == VCHIQ_SUCCESS))
      {
         LOG_ERROR("failed bulk transmit");
         /* This really should not happen and if it does, things will go wrong as
          * we've already queued the vchiq message above. */
         vcos_assert(0);
         ret = MMAL_EIO;
         goto fail_msg;
      }
   }

   /* now wait for the reply...
    *
    * FIXME: we could do with a timeout here. Need to be careful to cancel
    * the semaphore on a timeout.
    */
   vcos_semaphore_wait(&waiter->sem);

   mmal_vc_release_internal(client);
   LOG_TRACE("got reply (len %i/%i)", (int)*destlen, (int)waiter->destlen);
   *destlen = waiter->destlen;

   release_waiter(client, waiter);
   return MMAL_SUCCESS;

fail_msg:
   mmal_vc_release_internal(client);

   release_waiter(client, waiter);
   return ret;
}
Esempio n. 3
0
 bool dismiss_wait(waiter* ) {
     auto w = get_waiter();
     return w == 0 ||
         ( w != signaled &&
           state.compare_exchange_strong(w, empty));
 }
Esempio n. 4
0
 bool try_wait(waiter * w) {
     assert(w);
     auto old_w = get_waiter();
     return (old_w != signaled && state.compare_exchange_strong(old_w, w));
 }