__unused JNIEXPORT void JNICALL Java_pl_droidsonroids_gif_GifInfoHandle_bindSurface(JNIEnv *env, jclass __unused handleClass, jlong gifInfo, jobject jsurface, jlongArray savedState) { GifInfo *info = (GifInfo *) (intptr_t) gifInfo; SurfaceDescriptor *descriptor = info->frameBufferDescriptor; if (descriptor == NULL) { descriptor = malloc(sizeof(SurfaceDescriptor)); if (descriptor == NULL) { throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE); return; } descriptor->eventPollFd.events = POLL_IN; descriptor->eventPollFd.fd = eventfd(0, 0); if (descriptor->eventPollFd.fd == -1) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Eventfd creation failed "); free(descriptor); return; } errno = pthread_cond_init(&descriptor->slurpCond, NULL); THROW_ON_NONZERO_RESULT(errno, "Slurp condition variable initialization failed "); errno = pthread_cond_init(&descriptor->renderCond, NULL); THROW_ON_NONZERO_RESULT(errno, "Render condition variable initialization failed "); errno = pthread_mutex_init(&descriptor->slurpMutex, NULL); THROW_ON_NONZERO_RESULT(errno, "Slurp mutex initialization failed "); errno = pthread_mutex_init(&descriptor->renderMutex, NULL); THROW_ON_NONZERO_RESULT(errno, "Render mutex initialization failed "); descriptor->frameBuffer = NULL; info->frameBufferDescriptor = descriptor; info->destructor = releaseSurfaceDescriptor; } eventfd_t eventValue; int pollResult; while (1) { pollResult = TEMP_FAILURE_RETRY(poll(&descriptor->eventPollFd, 1, 0)); if (pollResult == 0) break; else if (pollResult > 0) { const int readResult = TEMP_FAILURE_RETRY(eventfd_read(descriptor->eventPollFd.fd, &eventValue)); if (readResult != 0) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Could not read from eventfd "); return; } } else { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Could not poll on eventfd "); return; } } const int32_t windowFormat = info->isOpaque ? WINDOW_FORMAT_RGBX_8888 : WINDOW_FORMAT_RGBA_8888; struct ANativeWindow *window = ANativeWindow_fromSurface(env, jsurface); GifFileType *const gifFilePtr = info->gifFilePtr; if (ANativeWindow_setBuffersGeometry(window, (int32_t) gifFilePtr->SWidth, (int32_t) gifFilePtr->SHeight, windowFormat) != 0) { ANativeWindow_release(window); throwException(env, RUNTIME_EXCEPTION_ERRNO, "Buffers geometry setting failed "); return; } struct ANativeWindow_Buffer buffer = {.bits =NULL}; void *oldBufferBits; if (ANativeWindow_lock(window, &buffer, NULL) != 0) { #ifdef DEBUG LOGE("Window lock failed %d", errno); #endif ANativeWindow_release(window); return; } const size_t bufferSize = buffer.stride * buffer.height * sizeof(argb); info->stride = buffer.stride; long long invalidationDelayMillis; if (descriptor->frameBuffer) { memcpy(buffer.bits, descriptor->frameBuffer, bufferSize); invalidationDelayMillis = 0; descriptor->renderHelper = 1; descriptor->slurpHelper = 0; } else { if (savedState != NULL) { invalidationDelayMillis = restoreSavedState(info, env, savedState, buffer.bits); if (invalidationDelayMillis < 0) invalidationDelayMillis = 0; } else invalidationDelayMillis = 0; descriptor->renderHelper = 0; descriptor->slurpHelper = 1; } info->lastFrameRemainder = -1; ANativeWindow_unlockAndPost(window); if (info->loopCount != 0 && info->currentLoop == info->loopCount) { ANativeWindow_release(window); pollResult = TEMP_FAILURE_RETRY(poll(&descriptor->eventPollFd, 1, -1)); if (pollResult < 0) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Animation end poll failed "); } return; } errno = pthread_create(&descriptor->slurpThread, NULL, slurp, info); if (errno != 0) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Slurp thread creation failed "); ANativeWindow_release(window); return; } while (1) { pollResult = TEMP_FAILURE_RETRY(poll(&descriptor->eventPollFd, 1, (int) invalidationDelayMillis)); long renderingStartTime = getRealTime(); if (pollResult < 0) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Display loop poll failed "); break; } else if (pollResult > 0) { if (descriptor->frameBuffer == NULL) { descriptor->frameBuffer = malloc(bufferSize); if (descriptor->frameBuffer == NULL) { throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE); break; } } memcpy(descriptor->frameBuffer, buffer.bits, bufferSize); break; } oldBufferBits = buffer.bits; struct ARect *dirtyRectPtr; if (info->currentIndex == 0) { dirtyRectPtr = NULL; } else { const GifImageDesc imageDesc = gifFilePtr->SavedImages[info->currentIndex].ImageDesc; struct ARect dirtyRect = { .left = imageDesc.Left, .top = imageDesc.Top, .right = imageDesc.Left + imageDesc.Width, .bottom = imageDesc.Top + imageDesc.Height }; dirtyRectPtr = &dirtyRect; } if (ANativeWindow_lock(window, &buffer, dirtyRectPtr) != 0) { #ifdef DEBUG LOGE("Window lock failed %d", errno); #endif break; } if (info->currentIndex == 0) prepareCanvas(buffer.bits, info); else memcpy(buffer.bits, oldBufferBits, bufferSize); pthread_mutex_lock(&descriptor->renderMutex); while (descriptor->renderHelper == 0) { pthread_cond_wait(&descriptor->renderCond, &descriptor->renderMutex); } descriptor->renderHelper = 0; pthread_mutex_unlock(&descriptor->renderMutex); const uint_fast32_t frameDuration = getBitmap(buffer.bits, info); pthread_mutex_lock(&descriptor->slurpMutex); descriptor->slurpHelper = 1; pthread_cond_signal(&descriptor->slurpCond); pthread_mutex_unlock(&descriptor->slurpMutex); ANativeWindow_unlockAndPost(window); invalidationDelayMillis = calculateInvalidationDelay(info, renderingStartTime, frameDuration); if (info->lastFrameRemainder >= 0) { invalidationDelayMillis = info->lastFrameRemainder; info->lastFrameRemainder = -1; } } ANativeWindow_release(window); pthread_mutex_lock(&descriptor->slurpMutex); descriptor->slurpHelper = 2; pthread_cond_signal(&descriptor->slurpCond); pthread_mutex_unlock(&descriptor->slurpMutex); errno = pthread_join(descriptor->slurpThread, NULL); THROW_ON_NONZERO_RESULT(errno, "Slurp thread join failed"); } __unused JNIEXPORT void JNICALL Java_pl_droidsonroids_gif_GifInfoHandle_postUnbindSurface(JNIEnv *env, jclass __unused handleClass, jlong gifInfo) { GifInfo *info = (GifInfo *) (intptr_t) gifInfo; if (info == NULL || info->frameBufferDescriptor == NULL) { return; } SurfaceDescriptor const *descriptor = info->frameBufferDescriptor; const int writeResult = TEMP_FAILURE_RETRY(eventfd_write(descriptor->eventPollFd.fd, 1)); if (writeResult != 0 && errno != EBADF) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Could not write to eventfd "); } }
void ponyint_asio_backend_final(asio_backend_t* b) { atomic_store_explicit(&b->terminate, true, memory_order_relaxed); eventfd_write(b->wakeup, 1); }
void asio_backend_terminate(asio_backend_t* b) { b->terminate = true; eventfd_write(b->wakeup, 1); }
int eventfd_send_state(int efd, eventfd_t s) { return eventfd_write(efd, s); }
static void eventfd_wakeup(grpc_wakeup_fd *fd_info) { int err; do { err = eventfd_write(fd_info->read_fd, 1); } while (err < 0 && errno == EINTR); }
Device::~Device() { eventfd_write(mEventFd, 1); if (mFd >= 0) { close(mFd); mFd = -1; } if (mEventFd >= 0) { close(mEventFd); mEventFd = -1; } }
inline bool queue_push_element(queue_t *queue, void * element) { // Push an element in the queue // If successfull, write 1 in the file descriptor. return list_push_element(queue->elements, element) && (eventfd_write(queue->eventfd, 1) != -1); }
static BOOL _purge(WINPR_COMM *pComm, const ULONG *pPurgeMask) { if ((*pPurgeMask & ~(SERIAL_PURGE_TXABORT | SERIAL_PURGE_RXABORT | SERIAL_PURGE_TXCLEAR | SERIAL_PURGE_RXCLEAR)) > 0) { CommLog_Print(WLOG_WARN, "Invalid purge mask: 0x%lX\n", *pPurgeMask); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* FIXME: currently relying too much on the fact the server * sends a single IRP_MJ_WRITE or IRP_MJ_READ at a time * (taking care though that one IRP_MJ_WRITE and one * IRP_MJ_READ can be sent simultaneously) */ if (*pPurgeMask & SERIAL_PURGE_TXABORT) { /* Purges all write (IRP_MJ_WRITE) requests. */ if (eventfd_write(pComm->fd_write_event, FREERDP_PURGE_TXABORT) < 0) { if (errno != EAGAIN) { CommLog_Print(WLOG_WARN, "eventfd_write failed, errno=[%d] %s", errno, strerror(errno)); } assert(errno == EAGAIN); /* no reader <=> no pending IRP_MJ_WRITE */ } } if (*pPurgeMask & SERIAL_PURGE_RXABORT) { /* Purges all read (IRP_MJ_READ) requests. */ if (eventfd_write(pComm->fd_read_event, FREERDP_PURGE_RXABORT) < 0) { if (errno != EAGAIN) { CommLog_Print(WLOG_WARN, "eventfd_write failed, errno=[%d] %s", errno, strerror(errno)); } assert(errno == EAGAIN); /* no reader <=> no pending IRP_MJ_READ */ } } if (*pPurgeMask & SERIAL_PURGE_TXCLEAR) { /* Purges the transmit buffer, if one exists. */ if (tcflush(pComm->fd, TCOFLUSH) < 0) { CommLog_Print(WLOG_WARN, "tcflush(TCOFLUSH) failure, errno=[%d] %s", errno, strerror(errno)); SetLastError(ERROR_CANCELLED); return FALSE; } } if (*pPurgeMask & SERIAL_PURGE_RXCLEAR) { /* Purges the receive buffer, if one exists. */ if (tcflush(pComm->fd, TCIFLUSH) < 0) { CommLog_Print(WLOG_WARN, "tcflush(TCIFLUSH) failure, errno=[%d] %s", errno, strerror(errno)); SetLastError(ERROR_CANCELLED); return FALSE; } } return TRUE; }