From patchwork Sat Mar 18 08:55:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: wm4 X-Patchwork-Id: 2996 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.50.79 with SMTP id y76csp609687vsy; Sat, 18 Mar 2017 01:56:31 -0700 (PDT) X-Received: by 10.223.180.68 with SMTP id v4mr15653348wrd.37.1489827391435; Sat, 18 Mar 2017 01:56:31 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id r71si6499017wmd.141.2017.03.18.01.56.31; Sat, 18 Mar 2017 01:56:31 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@googlemail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id ECB47688372; Sat, 18 Mar 2017 10:56:02 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm0-f68.google.com (mail-wm0-f68.google.com [74.125.82.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A6F28688302 for ; Sat, 18 Mar 2017 10:55:56 +0200 (EET) Received: by mail-wm0-f68.google.com with SMTP id n11so6531832wma.0 for ; Sat, 18 Mar 2017 01:56:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=vkhJHyw0vBAWv1lx29CqRLmCnnnlYo7ePJZJUexgVUw=; b=KuDqkhee+xUT8XvZQoLoEwe4HZrIj04+1YavSBmL0KACODppvwnuNFWNnAqTIvu38s ChUg1FEs9qwsUgU4Cn92ShZiAwo7zMa6T3GtYjwg9qiBP/tiQQkTTxmwt5KpwETOyp6o zM26nGF1UQWOB0U3JwCfmeAO8FKURnS+NNd2g4IDwGZlFgfbWS/sYbCzZU7Rz7umFVNj VXxcGE9pNVRwGq6mvK858hzXnvlcGYHaLEsciiPufJDXvJZXSowvfsSwtJovvf5kmS67 iytJbq279/bL4Bvj/70WWVYx6+4aXPpT4kJzdlg+hlElEXfdhIyn6Svt0lE//BjUth+3 cgdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=vkhJHyw0vBAWv1lx29CqRLmCnnnlYo7ePJZJUexgVUw=; b=KwyZWE57gRqOCEBPDc5LLP9zooqVHkejyfcNvO8cvakvjLB+RVV1x37Ik/MAx9tqMD PLpJ/0EJH80IYNzglhsD/HIg4TpVKdZSP2pJUSwfulHM9hPQjh/k74rsUgsRPt4jXHcw KYTwZpbggB2dX7GrYuecG0P8OaG9SpN0zAZV1JR9apijLrahKqMoChE3AihIoC+jR5GS XXpp+9YFmf5DiWghO0eEI49p4WbpI+bm8MiagSpXXfRgAtzpe2l12dm26loLoQK3uDVW Vo5yqw2eIX4lZhj7XW0IHjaE/6mHZNwxfWYqZoaUtfAXpb8MPire8UZr6TMnle7T7Qbl MdYA== X-Gm-Message-State: AFeK/H1sZsCP2UaTEHNq5mbR4op+0/CDWGBVvDUOIgl7q8dOwlu5huXITNhjT7l1bwJmCg== X-Received: by 10.28.50.6 with SMTP id y6mr1849445wmy.112.1489827373702; Sat, 18 Mar 2017 01:56:13 -0700 (PDT) Received: from localhost.localdomain (p4FF02CC6.dip0.t-ipconnect.de. [79.240.44.198]) by smtp.googlemail.com with ESMTPSA id p12sm12879637wrb.46.2017.03.18.01.56.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Mar 2017 01:56:12 -0700 (PDT) From: wm4 To: ffmpeg-devel@ffmpeg.org Date: Sat, 18 Mar 2017 09:55:58 +0100 Message-Id: <20170318085606.26011-2-nfxjfg@googlemail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170318085606.26011-1-nfxjfg@googlemail.com> References: <20170318085606.26011-1-nfxjfg@googlemail.com> Subject: [FFmpeg-devel] [PATCH 1/9] pthread_frame: use atomics for PerThreadContext.state X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: wm4 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Anton Khirnov Merges Libav commit 64a31b28. Signed-off-by: wm4 --- libavcodec/pthread_frame.c | 84 ++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 272587f53c..bd250002a3 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -24,6 +24,7 @@ #include "config.h" +#include #include #include "avcodec.h" @@ -43,6 +44,25 @@ #include "libavutil/opt.h" #include "libavutil/thread.h" +enum { + ///< Set when the thread is awaiting a packet. + STATE_INPUT_READY, + ///< Set before the codec has called ff_thread_finish_setup(). + STATE_SETTING_UP, + /** + * Set when the codec calls get_buffer(). + * State is returned to STATE_SETTING_UP afterwards. + */ + STATE_GET_BUFFER, + /** + * Set when the codec calls get_format(). + * State is returned to STATE_SETTING_UP afterwards. + */ + STATE_GET_FORMAT, + ///< Set after the codec has called ff_thread_finish_setup(). + STATE_SETUP_FINISHED, +}; + /** * Context used by codec threads and stored in their AVCodecInternal thread_ctx. */ @@ -66,19 +86,7 @@ typedef struct PerThreadContext { int got_frame; ///< The output of got_picture_ptr from the last avcodec_decode_video() call. int result; ///< The result of the last codec decode/encode() call. - enum { - STATE_INPUT_READY, ///< Set when the thread is awaiting a packet. - STATE_SETTING_UP, ///< Set before the codec has called ff_thread_finish_setup(). - STATE_GET_BUFFER, /**< - * Set when the codec calls get_buffer(). - * State is returned to STATE_SETTING_UP afterwards. - */ - STATE_GET_FORMAT, /**< - * Set when the codec calls get_format(). - * State is returned to STATE_SETTING_UP afterwards. - */ - STATE_SETUP_FINISHED ///< Set after the codec has called ff_thread_finish_setup(). - } state; + atomic_int state; /** * Array of frames passed to ff_thread_release_buffer(). @@ -133,8 +141,8 @@ static attribute_align_arg void *frame_worker_thread(void *arg) pthread_mutex_lock(&p->mutex); while (1) { - while (p->state == STATE_INPUT_READY && !p->die) - pthread_cond_wait(&p->input_cond, &p->mutex); + while (atomic_load(&p->state) == STATE_INPUT_READY && !p->die) + pthread_cond_wait(&p->input_cond, &p->mutex); if (p->die) break; @@ -152,7 +160,8 @@ static attribute_align_arg void *frame_worker_thread(void *arg) av_frame_unref(p->frame); } - if (p->state == STATE_SETTING_UP) ff_thread_finish_setup(avctx); + if (atomic_load(&p->state) == STATE_SETTING_UP) + ff_thread_finish_setup(avctx); pthread_mutex_lock(&p->progress_mutex); #if 0 //BUFREF-FIXME @@ -162,7 +171,7 @@ static attribute_align_arg void *frame_worker_thread(void *arg) p->progress[i][1] = INT_MAX; } #endif - p->state = STATE_INPUT_READY; + atomic_store(&p->state, STATE_INPUT_READY); pthread_cond_broadcast(&p->progress_cond); pthread_cond_signal(&p->output_cond); @@ -323,9 +332,9 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt) if (prev_thread) { int err; - if (prev_thread->state == STATE_SETTING_UP) { + if (atomic_load(&prev_thread->state) == STATE_SETTING_UP) { pthread_mutex_lock(&prev_thread->progress_mutex); - while (prev_thread->state == STATE_SETTING_UP) + while (atomic_load(&prev_thread->state) == STATE_SETTING_UP) pthread_cond_wait(&prev_thread->progress_cond, &prev_thread->progress_mutex); pthread_mutex_unlock(&prev_thread->progress_mutex); } @@ -345,7 +354,7 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt) return ret; } - p->state = STATE_SETTING_UP; + atomic_store(&p->state, STATE_SETTING_UP); pthread_cond_signal(&p->input_cond); pthread_mutex_unlock(&p->mutex); @@ -358,13 +367,13 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt) if (!p->avctx->thread_safe_callbacks && ( p->avctx->get_format != avcodec_default_get_format || p->avctx->get_buffer2 != avcodec_default_get_buffer2)) { - while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) { + while (atomic_load(&p->state) != STATE_SETUP_FINISHED && atomic_load(&p->state) != STATE_INPUT_READY) { int call_done = 1; pthread_mutex_lock(&p->progress_mutex); - while (p->state == STATE_SETTING_UP) + while (atomic_load(&p->state) == STATE_SETTING_UP) pthread_cond_wait(&p->progress_cond, &p->progress_mutex); - switch (p->state) { + switch (atomic_load_explicit(&p->state, memory_order_acquire)) { case STATE_GET_BUFFER: p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags); break; @@ -376,7 +385,7 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt) break; } if (call_done) { - p->state = STATE_SETTING_UP; + atomic_store(&p->state, STATE_SETTING_UP); pthread_cond_signal(&p->progress_cond); } pthread_mutex_unlock(&p->progress_mutex); @@ -431,9 +440,9 @@ int ff_thread_decode_frame(AVCodecContext *avctx, do { p = &fctx->threads[finished++]; - if (p->state != STATE_INPUT_READY) { + if (atomic_load(&p->state) != STATE_INPUT_READY) { pthread_mutex_lock(&p->progress_mutex); - while (p->state != STATE_INPUT_READY) + while (atomic_load_explicit(&p->state, memory_order_relaxed) != STATE_INPUT_READY) pthread_cond_wait(&p->output_cond, &p->progress_mutex); pthread_mutex_unlock(&p->progress_mutex); } @@ -516,11 +525,12 @@ void ff_thread_finish_setup(AVCodecContext *avctx) { if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return; pthread_mutex_lock(&p->progress_mutex); - if(p->state == STATE_SETUP_FINISHED){ + if(atomic_load(&p->state) == STATE_SETUP_FINISHED){ av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n"); } - p->state = STATE_SETUP_FINISHED; + atomic_store(&p->state, STATE_SETUP_FINISHED); + pthread_cond_broadcast(&p->progress_cond); pthread_mutex_unlock(&p->progress_mutex); } @@ -533,9 +543,9 @@ static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count for (i = 0; i < thread_count; i++) { PerThreadContext *p = &fctx->threads[i]; - if (p->state != STATE_INPUT_READY) { + if (atomic_load(&p->state) != STATE_INPUT_READY) { pthread_mutex_lock(&p->progress_mutex); - while (p->state != STATE_INPUT_READY) + while (atomic_load(&p->state) != STATE_INPUT_READY) pthread_cond_wait(&p->output_cond, &p->progress_mutex); pthread_mutex_unlock(&p->progress_mutex); } @@ -753,7 +763,7 @@ void ff_thread_flush(AVCodecContext *avctx) int ff_thread_can_start_frame(AVCodecContext *avctx) { PerThreadContext *p = avctx->internal->thread_ctx; - if ((avctx->active_thread_type&FF_THREAD_FRAME) && p->state != STATE_SETTING_UP && + if ((avctx->active_thread_type&FF_THREAD_FRAME) && atomic_load(&p->state) != STATE_SETTING_UP && (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { return 0; } @@ -772,7 +782,7 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int if (!(avctx->active_thread_type & FF_THREAD_FRAME)) return ff_get_buffer(avctx, f->f, flags); - if (p->state != STATE_SETTING_UP && + if (atomic_load(&p->state) != STATE_SETTING_UP && (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n"); return -1; @@ -797,10 +807,10 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int pthread_mutex_lock(&p->progress_mutex); p->requested_frame = f->f; p->requested_flags = flags; - p->state = STATE_GET_BUFFER; + atomic_store_explicit(&p->state, STATE_GET_BUFFER, memory_order_release); pthread_cond_broadcast(&p->progress_cond); - while (p->state != STATE_SETTING_UP) + while (atomic_load(&p->state) != STATE_SETTING_UP) pthread_cond_wait(&p->progress_cond, &p->progress_mutex); err = p->result; @@ -825,16 +835,16 @@ enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixe if (!(avctx->active_thread_type & FF_THREAD_FRAME) || avctx->thread_safe_callbacks || avctx->get_format == avcodec_default_get_format) return ff_get_format(avctx, fmt); - if (p->state != STATE_SETTING_UP) { + if (atomic_load(&p->state) != STATE_SETTING_UP) { av_log(avctx, AV_LOG_ERROR, "get_format() cannot be called after ff_thread_finish_setup()\n"); return -1; } pthread_mutex_lock(&p->progress_mutex); p->available_formats = fmt; - p->state = STATE_GET_FORMAT; + atomic_store(&p->state, STATE_GET_FORMAT); pthread_cond_broadcast(&p->progress_cond); - while (p->state != STATE_SETTING_UP) + while (atomic_load(&p->state) != STATE_SETTING_UP) pthread_cond_wait(&p->progress_cond, &p->progress_mutex); res = p->result_format;