void vcos_log_unregister(VCOS_LOG_CAT_T *category) { VCOS_LOG_CAT_T **pcat; vcos_mutex_lock(&lock); category->refcount--; if (category->refcount == 0) { pcat = &vcos_logging_categories; while (*pcat != category) { if (!*pcat) break; /* possibly deregistered twice? */ if ((*pcat)->next == NULL) { vcos_assert(0); /* already removed! */ vcos_mutex_unlock(&lock); return; } pcat = &(*pcat)->next; } if (*pcat) *pcat = category->next; vcos_log_platform_unregister(category); } vcos_mutex_unlock(&lock); }
/** Send a message and do not wait for a reply. * * @note * This function should only be called from within a mmal component, so * vchiq_use/release_service calls aren't required (dealt with at higher level). * * @param client client to send message for * @param msg_header message header to send * @param size length of message, including header * @param msgid message id */ MMAL_STATUS_T mmal_vc_send_message(MMAL_CLIENT_T *client, mmal_worker_msg_header *msg_header, size_t size, uint8_t *data, size_t data_size, uint32_t msgid) { VCHIQ_STATUS_T vst; VCHIQ_ELEMENT_T elems[] = {{msg_header, size}}; MMAL_BOOL_T using_bulk_transfer = (data_size != 0); LOG_TRACE("len %d", data_size); vcos_assert(size >= sizeof(mmal_worker_msg_header)); if (!client->inited) { vcos_assert(0); return MMAL_EINVAL; } if (using_bulk_transfer) vcos_mutex_lock(&client->bulk_lock); msg_header->msgid = msgid; msg_header->magic = MMAL_MAGIC; vst = vchiq_queue_message(client->service, elems, 1); if (vst != VCHIQ_SUCCESS) { if (using_bulk_transfer) vcos_mutex_unlock(&client->bulk_lock); LOG_ERROR("failed"); goto error; } if (using_bulk_transfer) { LOG_TRACE("bulk transmit: %p, %i", data, data_size); data_size = (data_size + 3) & ~3; 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); goto error; } } return MMAL_SUCCESS; error: return MMAL_EIO; }
int32_t vc_gpuserv_init( void ) { VCHIQ_SERVICE_PARAMS_T vchiq_params; VCOS_STATUS_T status = VCOS_ENXIO; VCHIQ_STATUS_T vchiq_status; vcos_once(&gpuserv_client_once, init_once); vcos_mutex_lock(&gpuserv_client.lock); if (gpuserv_client.refcount++ > 0) { /* Already initialised so nothing to do */ vcos_mutex_unlock(&gpuserv_client.lock); return VCOS_SUCCESS; } vcos_log_set_level(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE); vcos_log_register("gpuserv", VCOS_LOG_CATEGORY); vcos_log_trace("%s: starting initialisation", VCOS_FUNCTION); /* Initialise a VCHIQ instance */ vchiq_status = vchiq_initialise(&gpuserv_client_vchiq_instance); if (vchiq_status != VCHIQ_SUCCESS) { vcos_log_error("%s: failed to initialise vchiq: %d", VCOS_FUNCTION, vchiq_status); goto error; } vchiq_status = vchiq_connect(gpuserv_client_vchiq_instance); if (vchiq_status != VCHIQ_SUCCESS) { vcos_log_error("%s: failed to connect to vchiq: %d", VCOS_FUNCTION, vchiq_status); goto error; } memset(&vchiq_params, 0, sizeof(vchiq_params)); vchiq_params.fourcc = VCHIQ_MAKE_FOURCC('G','P','U','S'); vchiq_params.callback = gpuserv_callback; vchiq_params.userdata = NULL; vchiq_params.version = 1; vchiq_params.version_min = 1; vchiq_status = vchiq_open_service(gpuserv_client_vchiq_instance, &vchiq_params, &gpuserv_client.service); if (vchiq_status != VCHIQ_SUCCESS) { vcos_log_error("%s: could not open vchiq service: %d", VCOS_FUNCTION, vchiq_status); goto error; } vcos_mutex_unlock(&gpuserv_client.lock); return 0; error: vcos_mutex_unlock(&gpuserv_client.lock); return -1; }
VCOS_STATUS_T vcos_generic_named_semaphore_create(VCOS_NAMED_SEMAPHORE_T *sem, const char *name, VCOS_UNSIGNED count) { VCOS_STATUS_T status; int i, name_len; vcos_mutex_lock(&lock); /* do we already have this semaphore? */ for (i=0; i<MAX_SEMS; i++) { if (sems[i].refs && strcmp(name, sems[i].name) == 0) { sems[i].refs++; sem->actual = sems+i; sem->sem = &sems[i].sem; vcos_mutex_unlock(&lock); return VCOS_SUCCESS; } } /* search for unused semaphore */ name_len = strlen(name); if (name_len >= VCOS_NAMED_SEMAPHORE_NAMELEN) { vcos_assert(0); vcos_mutex_unlock(&lock); return VCOS_EINVAL; } for (i=0; i<MAX_SEMS; i++) { if (sems[i].refs == 0) { status = vcos_semaphore_create(&sems[i].sem, name, count); if (status == VCOS_SUCCESS) { sems[i].refs = 1; strcpy(sems[i].name, name); /* already checked length! */ sem->actual = sems+i; sem->sem = &sems[i].sem; } vcos_mutex_unlock(&lock); return status; } } vcos_mutex_unlock(&lock); return VCOS_ENOSPC; }
/* find a message queue, optionally blocking until it is created */ static VCOS_MSGQUEUE_T *vcos_msgq_find_helper(const char *name, int wait) { VCOS_MSG_ENDPOINT_T *ep; VCOS_ENDPOINT_WAITER_T waiter; do { vcos_mutex_lock(&lock); for (ep = endpoints; ep != NULL; ep = ep->next) { if (strcmp(ep->name, name) == 0) { /* found it - return to caller */ vcos_mutex_unlock(&lock); return &ep->primary; } } /* if we get here, we did not find it */ if (!wait) { vcos_mutex_unlock(&lock); return NULL; } else { VCOS_STATUS_T st; waiter.name = name; st = vcos_semaphore_create(&waiter.sem,"vcos:waiter",0); if (st != VCOS_SUCCESS) { vcos_assert(0); vcos_mutex_unlock(&lock); return NULL; } /* Push new waiter onto head of global waiters list */ /* coverity[use] Suppress ATOMICITY warning - 'waiters' might have * changed since the last iteration of the loop, which is okay */ waiter.next = waiters; waiters = &waiter; /* we're now on the list, so can safely go to sleep */ vcos_mutex_unlock(&lock); vcos_semaphore_wait(&waiter.sem); /* It should now be on the list, but it could in theory be deleted * between waking up and going to look for it. So may have to wait * again. * So, go round again.... */ vcos_semaphore_delete(&waiter.sem); continue; } } while (1); }
void vcos_vlog_default_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args) { (void)_level; #ifdef ANDROID if ( vcos_use_android_log ) { __android_log_vprint(log_prio[_level], cat->name, fmt, args); } else { vcos_mutex_lock(&printf_lock); #endif if(NULL != log_fhandle) { if (cat->flags.want_prefix) fprintf( log_fhandle, "%s: ", cat->name ); vfprintf(log_fhandle, fmt, args); fputs("\n", log_fhandle); fflush(log_fhandle); } #ifdef ANDROID vcos_mutex_unlock(&printf_lock); } #endif }
void *vcos_generic_blockpool_elem_from_handle( VCOS_BLOCKPOOL_T *pool, uint32_t handle) { VCOS_BLOCKPOOL_SUBPOOL_T *subpool; uint32_t subpool_id; uint32_t index; void *ret = NULL; ASSERT_POOL(pool); vcos_mutex_lock(&pool->mutex); subpool_id = VCOS_BLOCKPOOL_HANDLE_GET_SUBPOOL(handle); if (subpool_id < pool->num_subpools) { index = VCOS_BLOCKPOOL_HANDLE_GET_INDEX(handle); subpool = &pool->subpools[subpool_id]; if (pool->subpools[subpool_id].magic == VCOS_BLOCKPOOL_SUBPOOL_MAGIC && pool->subpools[subpool_id].mem && index < subpool->num_blocks) { VCOS_BLOCKPOOL_HEADER_T *hdr = (VCOS_BLOCKPOOL_HEADER_T*) ((size_t) subpool->start + (index * pool->block_size)); if (hdr->owner.subpool == subpool) /* Check block is allocated */ ret = hdr + 1; } } vcos_mutex_unlock(&pool->mutex); vcos_log_trace("%s: pool %p handle 0x%08x elem %p", VCOS_FUNCTION, pool, handle, ret); return ret; }
VCHIQ_STATUS_T vchiq_open_service(VCHIQ_INSTANCE_T instance, int fourcc, VCHIQ_CALLBACK_T callback, void *userdata, VCHIQ_SERVICE_HANDLE_T *pservice) { VCHIQ_STATE_T *state = &instance->state; VCHIQ_SERVICE_T *service; VCHIQ_STATUS_T status = VCHIQ_ERROR; vcos_assert(fourcc != VCHIQ_FOURCC_INVALID); vcos_assert(callback != NULL); if (!is_valid_instance(instance)) return VCHIQ_ERROR; if (!instance->connected) return VCHIQ_ERROR; vcos_mutex_lock(&state->mutex); service = vchiq_add_service_internal(state, fourcc, callback, userdata, VCHIQ_SRVSTATE_OPENING, instance); vcos_mutex_unlock(&state->mutex); if (service) { status = vchiq_open_service_internal(service); if (status != VCHIQ_SUCCESS) { vchiq_remove_service(&service->base); service = NULL; } } *pservice = &service->base; return status; }
/** Create a QUEUE of MMAL_BUFFER_HEADER_T */ MMAL_QUEUE_T *mmal_queue_create(void) { MMAL_QUEUE_T *queue; queue = vcos_malloc(sizeof(*queue), "MMAL queue"); if(!queue) return 0; if(vcos_mutex_create(&queue->lock, "MMAL queue lock") != VCOS_SUCCESS ) { vcos_free(queue); return 0; } if(vcos_semaphore_create(&queue->semaphore, "MMAL queue sema", 0) != VCOS_SUCCESS ) { vcos_mutex_delete(&queue->lock); vcos_free(queue); return 0; } /* gratuitous lock for coverity */ vcos_mutex_lock(&queue->lock); queue->length = 0; queue->first = 0; queue->last = &queue->first; mmal_queue_sanity_check(queue, NULL); /* gratuitous unlock for coverity */ vcos_mutex_unlock(&queue->lock); return queue; }
/* OMX_FreeHandle */ OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( OMX_IN OMX_HANDLETYPE hComponent) { OMX_ERRORTYPE eError = OMX_ErrorNone; OMX_COMPONENTTYPE *pComp; if (hComponent == NULL || ilcs_service == NULL) return OMX_ErrorBadParameter; pComp = (OMX_COMPONENTTYPE*)hComponent; if (ilcs_service == NULL) return OMX_ErrorBadParameter; eError = (pComp->ComponentDeInit)(hComponent); if (eError == OMX_ErrorNone) { vcos_mutex_lock(&lock); --nActiveHandles; vcos_mutex_unlock(&lock); free(pComp); } vcos_assert(nActiveHandles >= 0); return eError; }
static void mmal_vc_payload_list_release(MMAL_VC_PAYLOAD_ELEM_T *elem) { vcos_mutex_lock(&mmal_vc_payload_list.lock); elem->handle = elem->vc_handle = 0; elem->mem = 0; elem->in_use = 0; vcos_mutex_unlock(&mmal_vc_payload_list.lock); }
/** Set quit flag, with locking. * @param quit New value of the quit flag: true - command thread to quit; false - command thread * to continue. * @return Old value of the quit flag. */ static bool vidtex_set_quit(VIDTEX_T *vt, bool quit) { vcos_mutex_lock(&vt->mutex); bool old_quit = vt->quit; vt->quit = quit; vcos_mutex_unlock(&vt->mutex); return old_quit; }
/** Get value of svp->stop, with locking. */ static uint32_t svp_get_stop(SVP_T *svp) { uint32_t stop; vcos_mutex_lock(&svp->mutex); stop = svp->stop; vcos_mutex_unlock(&svp->mutex); return stop; }
VCOS_STATUS_T vcos_log_status_cmd( VCOS_CMD_PARAM_T *param ) { VCOS_LOG_CAT_T *cat; VCOS_STATUS_T status; vcos_mutex_lock(&lock); if ( param->argc == 1) { int nw; int nameWidth = 0; /* Print information about all of the categories. */ for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next ) { nw = (int)strlen( cat->name ); if ( nw > nameWidth ) { nameWidth = nw; } } for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next ) { vcos_cmd_printf( param, "%-*s - %s\n", nameWidth, cat->name, vcos_log_level_to_string( cat->level )); } } else { /* Print information about a particular category */ for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next ) { if ( vcos_strcmp( cat->name, param->argv[1] ) == 0 ) { vcos_cmd_printf( param, "%s - %s\n", cat->name, vcos_log_level_to_string( cat->level )); break; } } if ( cat == NULL ) { vcos_cmd_printf( param, "Unrecognized logging category: '%s'\n", param->argv[1] ); status = VCOS_ENOENT; goto out; } } status = VCOS_SUCCESS; out: vcos_mutex_unlock(&lock); return status; }
//Unlock the host state static __inline void lock_release (void) { uint32_t i; vcos_assert(dispmanx_client.initialised); if(dispmanx_client.initialised) { for (i=0; i<dispmanx_client.num_connections; i++) { vchi_service_release(dispmanx_client.client_handle[i]); } } vcos_mutex_unlock( &dispmanx_client.lock ); }
void vc_gpuserv_deinit( void ) { vcos_mutex_lock(&gpuserv_client.lock); if (gpuserv_client.refcount > 0 && --gpuserv_client.refcount == 0) { vchi_service_close(gpuserv_client.service); gpuserv_client.service = 0; } vcos_mutex_unlock(&gpuserv_client.lock); }
void vcos_generic_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m) { vcos_assert(m->count != 0); vcos_assert(m->owner == vcos_thread_current()); m->count--; if (m->count == 0) { m->owner = 0; vcos_mutex_unlock(&m->mutex); } }
void *CComponent::EventThreadProc(VCOS_EVENT_FLAGS_T& EventFlags, VCOS_EVENT_T& InitialzedEvent) { vcos_event_signal(&InitialzedEvent); VCOS_UNSIGNED nEvents; try { for (;;) { CHECK_VCOS(vcos_event_flags_get(&EventFlags, CThread::s_nTerminationFlag | s_nNewEventFlag, VCOS_CONSUME, VCOS_SUSPEND, &nEvents), "failed to wait for events"); if (nEvents & CThread::s_nTerminationFlag) { // Component is being destoryed break; } else if (nEvents & s_nNewEventFlag) { // New event that cannot be handled in the notification callback bool bEventsPending = false; do { CComponentEvent Event; { CHECK_VCOS(vcos_mutex_lock(&m_EventQueueMutex), "failed to lock event queue mutex"); Event = m_EventQueue.front(); m_EventQueue.pop_front(); bEventsPending = !m_EventQueue.empty(); vcos_mutex_unlock(&m_EventQueueMutex); } switch (Event.m_EventType) { case OMX_EventPortSettingsChanged: { if (m_pGraph) { m_pGraph->OnPortSettingsChanged(this, Event.m_nData1); } } break; default: break; } } while (bEventsPending); } } } catch (std::exception& Exception) { std::cerr << "Error: " << Exception.what() << std::endl; } return NULL; }
static void *mmal_playback(void *id) { FILE_PLAY_INFO_T *play_info = id; MMALPLAY_OPTIONS_T opts; MMAL_STATUS_T status; MMALPLAY_T *ctx; /* Setup the options */ opts = options; opts.output_uri = play_info->options.output_uri; opts.render_layer = play_info->options.render_layer; vcos_mutex_lock(&play_info->lock); ctx = mmalplay_create(play_info->uri, &opts, &status); play_info->ctx = ctx; vcos_mutex_unlock(&play_info->lock); if (!ctx) goto end; if (!opts.disable_playback) status = mmalplay_play(ctx); if (unclean_exit) goto end; vcos_mutex_lock(&play_info->lock); if (ctx) { /* coverity[use] Suppress ATOMICITY warning - ctx might have changed since * we initialised it above, which is okay */ mmalplay_destroy(ctx); } play_info->ctx = 0; vcos_mutex_unlock(&play_info->lock); end: LOG_TRACE("Thread %s terminating, result %d", play_info->name, status); play_info->status = status; return NULL; }
/** Put a MMAL_BUFFER_HEADER_T back at the start of a QUEUE. */ void mmal_queue_put_back(MMAL_QUEUE_T *queue, MMAL_BUFFER_HEADER_T *buffer) { if(!queue || !buffer) return; vcos_mutex_lock(&queue->lock); mmal_queue_sanity_check(queue, buffer); queue->length++; buffer->next = queue->first; queue->first = buffer; if(queue->last == &queue->first) queue->last = &buffer->next; vcos_semaphore_post(&queue->semaphore); vcos_mutex_unlock(&queue->lock); }
void vcos_named_semaphore_delete(VCOS_NAMED_SEMAPHORE_T *sem) { VCOS_NAMED_SEMAPHORE_IMPL_T *actual = sem->actual; vcos_mutex_lock(&lock); vcos_assert(actual->refs); /* if this fires, the semaphore has already been deleted */ if (--actual->refs == 0) { vcos_semaphore_delete(&actual->sem); } vcos_mutex_unlock(&lock); }
VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance) { VCHIQ_STATUS_T status; if (!is_valid_instance(instance)) return VCHIQ_ERROR; vcos_mutex_lock(&instance->state.mutex); status = vchiq_connect_internal(&instance->state, instance); if (status == VCHIQ_SUCCESS) instance->connected = 1; vcos_mutex_unlock(&instance->state.mutex); return status; }
void mmal_vc_deinit(void) { int count; vcos_mutex_lock(&client.lock); count = --client.refcount; if (count != 0) { /* Still in use so don't do anything */ vcos_mutex_unlock(&client.lock); return; } vcos_mutex_delete(&client.bulk_lock); destroy_waitpool(&client.waitpool); vchiq_close_service(client.service); vchiq_shutdown(mmal_vchiq_instance); vcos_log_unregister(VCOS_LOG_CATEGORY); client.service = VCHIQ_SERVICE_HANDLE_INVALID; client.inited = 0; vcos_mutex_unlock(&client.lock); }
VCOS_STATUS_T vcos_log_set_cmd( VCOS_CMD_PARAM_T *param ) { VCOS_LOG_CAT_T *cat; char *name; char *levelStr; VCOS_LOG_LEVEL_T level; VCOS_STATUS_T status; if ( param->argc != 3 ) { vcos_cmd_usage( param ); return VCOS_EINVAL; } name = param->argv[1]; levelStr = param->argv[2]; if ( vcos_string_to_log_level( levelStr, &level ) != VCOS_SUCCESS ) { vcos_cmd_printf( param, "Unrecognized logging level: '%s'\n", levelStr ); return VCOS_EINVAL; } vcos_mutex_lock(&lock); status = VCOS_SUCCESS; for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next ) { if ( vcos_strcmp( name, cat->name ) == 0 ) { cat->level = level; vcos_cmd_printf( param, "Category %s level set to %s\n", name, levelStr ); break; } else if ( vcos_strcmp( name, "*") == 0 ) { cat->level = level; vcos_cmd_printf( param, "Category %s level set to %s\n", name, levelStr ); } } if ( cat == NULL ) { vcos_cmd_printf( param, "Unrecognized category: '%s'\n", name ); status = VCOS_ENOENT; } vcos_mutex_unlock(&lock); return status; }
/* append a message to a message queue */ static void msgq_append(VCOS_MSGQUEUE_T *q, VCOS_MSG_T *msg) { vcos_mutex_lock(&q->lock); if (q->head == NULL) { q->head = q->tail = msg; } else { q->tail->next = msg; q->tail = msg; } vcos_mutex_unlock(&q->lock); }
static MMAL_STATUS_T mmal_vc_release_internal(MMAL_CLIENT_T *client) { MMAL_STATUS_T status = MMAL_SUCCESS; vcos_mutex_lock(&client->lock); if(--client->usecount == 0) { if(vchiq_release_service(client->service) != VCHIQ_SUCCESS) { client->usecount++; status = MMAL_EIO; } } vcos_mutex_unlock(&client->lock); return status; }
/** Called when a get call times out. Remove this thread's * entry from the waiting queue, then resume the thread. */ static void event_flags_timer_expired(void *cxt) { VCOS_EVENT_WAITER_T *waitreq = (VCOS_EVENT_WAITER_T *)cxt; VCOS_EVENT_FLAGS_T *flags = waitreq->flags; VCOS_EVENT_WAITER_T **plist; VCOS_EVENT_WAITER_T *prev = NULL; VCOS_THREAD_T *thread = 0; vcos_assert(flags); vcos_mutex_lock(&flags->lock); /* walk the list of waiting threads on this event group, and remove * the one that has expired. * * FIXME: could use doubly-linked list if lots of threads are found * to be waiting on a single event flag instance. */ plist = &flags->waiters.head; while (*plist != NULL) { if (*plist == waitreq) { int at_end; /* found it */ thread = (*plist)->thread; at_end = ((*plist)->next == NULL); /* link past */ *plist = (*plist)->next; if (at_end) flags->waiters.tail = prev; break; } prev = *plist; plist = &(*plist)->next; } vcos_assert(waiter_list_valid(flags)); vcos_mutex_unlock(&flags->lock); if (thread) { _vcos_thread_sem_post(thread); } }
/* wait on a queue for a message */ static _VCOS_INLINE VCOS_MSG_T *vcos_msg_wait_helper(VCOS_MSGQUEUE_T *queue) { VCOS_MSG_T *msg; vcos_semaphore_wait(&queue->sem); vcos_mutex_lock(&queue->lock); msg = queue->head; vcos_assert(msg); /* should always be a message here! */ queue->head = msg->next; if (queue->head == NULL) queue->tail = NULL; vcos_mutex_unlock(&queue->lock); return msg; }
/** Get a MMAL_BUFFER_HEADER_T from a QUEUE. Semaphore already claimed */ static MMAL_BUFFER_HEADER_T *mmal_queue_get_core(MMAL_QUEUE_T *queue) { MMAL_BUFFER_HEADER_T * buffer; vcos_mutex_lock(&queue->lock); mmal_queue_sanity_check(queue, NULL); buffer = queue->first; vcos_assert(buffer != NULL); queue->first = buffer->next; if(!queue->first) queue->last = &queue->first; queue->length--; vcos_mutex_unlock(&queue->lock); return buffer; }
static MMAL_VC_PAYLOAD_ELEM_T *mmal_vc_payload_list_get() { MMAL_VC_PAYLOAD_ELEM_T *elem = 0; unsigned int i; vcos_mutex_lock(&mmal_vc_payload_list.lock); for (i = 0; i < MMAL_VC_PAYLOAD_ELEM_MAX; i++) { if (mmal_vc_payload_list.list[i].in_use) continue; elem = &mmal_vc_payload_list.list[i]; elem->in_use = 1; break; } vcos_mutex_unlock(&mmal_vc_payload_list.lock); return elem; }