1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright 2009 VMware, Inc.
4848b8605Smrg * All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the
8848b8605Smrg * "Software"), to deal in the Software without restriction, including
9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish,
10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to
11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to
12848b8605Smrg * the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice (including the
15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions
16848b8605Smrg * of the Software.
17848b8605Smrg *
18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25848b8605Smrg *
26848b8605Smrg **************************************************************************/
27848b8605Smrg
28848b8605Smrg
29848b8605Smrg#include "pipe/p_screen.h"
30848b8605Smrg#include "util/u_memory.h"
31848b8605Smrg#include "lp_debug.h"
32848b8605Smrg#include "lp_fence.h"
33848b8605Smrg
34848b8605Smrg
35848b8605Smrg/**
36848b8605Smrg * Create a new fence object.
37848b8605Smrg *
38848b8605Smrg * The rank will be the number of bins in the scene.  Whenever a rendering
39848b8605Smrg * thread hits a fence command, it'll increment the fence counter.  When
40848b8605Smrg * the counter == the rank, the fence is finished.
41848b8605Smrg *
42848b8605Smrg * \param rank  the expected finished value of the fence counter.
43848b8605Smrg */
44848b8605Smrgstruct lp_fence *
45848b8605Smrglp_fence_create(unsigned rank)
46848b8605Smrg{
47848b8605Smrg   static int fence_id;
48848b8605Smrg   struct lp_fence *fence = CALLOC_STRUCT(lp_fence);
49848b8605Smrg
50848b8605Smrg   if (!fence)
51848b8605Smrg      return NULL;
52848b8605Smrg
53848b8605Smrg   pipe_reference_init(&fence->reference, 1);
54848b8605Smrg
55b8e80941Smrg   (void) mtx_init(&fence->mutex, mtx_plain);
56b8e80941Smrg   cnd_init(&fence->signalled);
57848b8605Smrg
58848b8605Smrg   fence->id = fence_id++;
59848b8605Smrg   fence->rank = rank;
60848b8605Smrg
61848b8605Smrg   if (LP_DEBUG & DEBUG_FENCE)
62848b8605Smrg      debug_printf("%s %d\n", __FUNCTION__, fence->id);
63848b8605Smrg
64848b8605Smrg   return fence;
65848b8605Smrg}
66848b8605Smrg
67848b8605Smrg
68848b8605Smrg/** Destroy a fence.  Called when refcount hits zero. */
69848b8605Smrgvoid
70848b8605Smrglp_fence_destroy(struct lp_fence *fence)
71848b8605Smrg{
72848b8605Smrg   if (LP_DEBUG & DEBUG_FENCE)
73848b8605Smrg      debug_printf("%s %d\n", __FUNCTION__, fence->id);
74848b8605Smrg
75b8e80941Smrg   mtx_destroy(&fence->mutex);
76b8e80941Smrg   cnd_destroy(&fence->signalled);
77848b8605Smrg   FREE(fence);
78848b8605Smrg}
79848b8605Smrg
80848b8605Smrg
81848b8605Smrg/**
82848b8605Smrg * Called by the rendering threads to increment the fence counter.
83848b8605Smrg * When the counter == the rank, the fence is finished.
84848b8605Smrg */
85848b8605Smrgvoid
86848b8605Smrglp_fence_signal(struct lp_fence *fence)
87848b8605Smrg{
88848b8605Smrg   if (LP_DEBUG & DEBUG_FENCE)
89848b8605Smrg      debug_printf("%s %d\n", __FUNCTION__, fence->id);
90848b8605Smrg
91b8e80941Smrg   mtx_lock(&fence->mutex);
92848b8605Smrg
93848b8605Smrg   fence->count++;
94848b8605Smrg   assert(fence->count <= fence->rank);
95848b8605Smrg
96848b8605Smrg   if (LP_DEBUG & DEBUG_FENCE)
97848b8605Smrg      debug_printf("%s count=%u rank=%u\n", __FUNCTION__,
98848b8605Smrg                   fence->count, fence->rank);
99848b8605Smrg
100848b8605Smrg   /* Wakeup all threads waiting on the mutex:
101848b8605Smrg    */
102b8e80941Smrg   cnd_broadcast(&fence->signalled);
103848b8605Smrg
104b8e80941Smrg   mtx_unlock(&fence->mutex);
105848b8605Smrg}
106848b8605Smrg
107848b8605Smrgboolean
108848b8605Smrglp_fence_signalled(struct lp_fence *f)
109848b8605Smrg{
110848b8605Smrg   return f->count == f->rank;
111848b8605Smrg}
112848b8605Smrg
113848b8605Smrgvoid
114848b8605Smrglp_fence_wait(struct lp_fence *f)
115848b8605Smrg{
116848b8605Smrg   if (LP_DEBUG & DEBUG_FENCE)
117848b8605Smrg      debug_printf("%s %d\n", __FUNCTION__, f->id);
118848b8605Smrg
119b8e80941Smrg   mtx_lock(&f->mutex);
120848b8605Smrg   assert(f->issued);
121848b8605Smrg   while (f->count < f->rank) {
122b8e80941Smrg      cnd_wait(&f->signalled, &f->mutex);
123848b8605Smrg   }
124b8e80941Smrg   mtx_unlock(&f->mutex);
125848b8605Smrg}
126848b8605Smrg
127848b8605Smrg
128b8e80941Smrgboolean
129b8e80941Smrglp_fence_timedwait(struct lp_fence *f, uint64_t timeout)
130b8e80941Smrg{
131b8e80941Smrg   struct timespec ts;
132b8e80941Smrg   int ret;
133b8e80941Smrg
134b8e80941Smrg   timespec_get(&ts, TIME_UTC);
135b8e80941Smrg
136b8e80941Smrg   ts.tv_nsec += timeout % 1000000000L;
137b8e80941Smrg   ts.tv_sec += timeout / 1000000000L;
138b8e80941Smrg   if (ts.tv_nsec >= 1000000000L) {
139b8e80941Smrg      ts.tv_sec++;
140b8e80941Smrg      ts.tv_nsec -= 1000000000L;
141b8e80941Smrg   }
142b8e80941Smrg
143b8e80941Smrg   if (LP_DEBUG & DEBUG_FENCE)
144b8e80941Smrg      debug_printf("%s %d\n", __FUNCTION__, f->id);
145b8e80941Smrg
146b8e80941Smrg   mtx_lock(&f->mutex);
147b8e80941Smrg   assert(f->issued);
148b8e80941Smrg   while (f->count < f->rank) {
149b8e80941Smrg      ret = cnd_timedwait(&f->signalled, &f->mutex, &ts);
150b8e80941Smrg      if (ret != thrd_success)
151b8e80941Smrg         break;
152b8e80941Smrg   }
153b8e80941Smrg   const boolean result = (f->count >= f->rank);
154b8e80941Smrg   mtx_unlock(&f->mutex);
155b8e80941Smrg   return result;
156b8e80941Smrg}
157