1ed6f5d66Smrg/* 2ed6f5d66Smrg * Copyright © 2013 Keith Packard 3ed6f5d66Smrg * 4ed6f5d66Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5ed6f5d66Smrg * documentation for any purpose is hereby granted without fee, provided that 6ed6f5d66Smrg * the above copyright notice appear in all copies and that both that copyright 7ed6f5d66Smrg * notice and this permission notice appear in supporting documentation, and 8ed6f5d66Smrg * that the name of the copyright holders not be used in advertising or 9ed6f5d66Smrg * publicity pertaining to distribution of the software without specific, 10ed6f5d66Smrg * written prior permission. The copyright holders make no representations 11ed6f5d66Smrg * about the suitability of this software for any purpose. It is provided "as 12ed6f5d66Smrg * is" without express or implied warranty. 13ed6f5d66Smrg * 14ed6f5d66Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15ed6f5d66Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16ed6f5d66Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17ed6f5d66Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18ed6f5d66Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19ed6f5d66Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20ed6f5d66Smrg * OF THIS SOFTWARE. 21ed6f5d66Smrg */ 22ed6f5d66Smrg 23ed6f5d66Smrg#if HAVE_CONFIG_H 24ed6f5d66Smrg#include "config.h" 25ed6f5d66Smrg#endif 26ed6f5d66Smrg 27ed6f5d66Smrg#include "xshmfenceint.h" 28ed6f5d66Smrg 29ed6f5d66Smrg/** 30ed6f5d66Smrg * xshmfence_trigger: 31ed6f5d66Smrg * @f: An X fence 32ed6f5d66Smrg * 33ed6f5d66Smrg * Set @f to triggered, waking all waiters. 34ed6f5d66Smrg * 35ed6f5d66Smrg * Return value: 0 on success and -1 on error (in which case, errno 36ed6f5d66Smrg * will be set as appropriate). 37ed6f5d66Smrg **/ 38ed6f5d66Smrgint 39ed6f5d66Smrgxshmfence_trigger(struct xshmfence *f) { 40ed6f5d66Smrg pthread_mutex_lock(&f->lock); 41ed6f5d66Smrg if (f->value == 0) { 42ed6f5d66Smrg f->value = 1; 43ed6f5d66Smrg if (f->waiting) { 44ed6f5d66Smrg f->waiting = 0; 45ed6f5d66Smrg pthread_cond_broadcast(&f->wakeup); 46ed6f5d66Smrg } 47ed6f5d66Smrg } 48ed6f5d66Smrg pthread_mutex_unlock(&f->lock); 49ed6f5d66Smrg return 0; 50ed6f5d66Smrg} 51ed6f5d66Smrg 52ed6f5d66Smrg/** 53ed6f5d66Smrg * xshmfence_await: 54ed6f5d66Smrg * @f: An X fence 55ed6f5d66Smrg * 56ed6f5d66Smrg * Wait for @f to be triggered. If @f is already triggered, this 57ed6f5d66Smrg * function returns immediately. 58ed6f5d66Smrg * 59ed6f5d66Smrg * Return value: 0 on success and -1 on error (in which case, errno 60ed6f5d66Smrg * will be set as appropriate). 61ed6f5d66Smrg **/ 62ed6f5d66Smrgint 63ed6f5d66Smrgxshmfence_await(struct xshmfence *f) { 64ed6f5d66Smrg pthread_mutex_lock(&f->lock); 65ed6f5d66Smrg while (f->value == 0) { 66ed6f5d66Smrg f->waiting = 1; 67ed6f5d66Smrg pthread_cond_wait(&f->wakeup, &f->lock); 68ed6f5d66Smrg } 69ed6f5d66Smrg pthread_mutex_unlock(&f->lock); 70ed6f5d66Smrg return 0; 71ed6f5d66Smrg} 72ed6f5d66Smrg 73ed6f5d66Smrg/** 74ed6f5d66Smrg * xshmfence_query: 75ed6f5d66Smrg * @f: An X fence 76ed6f5d66Smrg * 77ed6f5d66Smrg * Return value: 1 if @f is triggered, else returns 0. 78ed6f5d66Smrg **/ 79ed6f5d66Smrgint 80ed6f5d66Smrgxshmfence_query(struct xshmfence *f) { 81ed6f5d66Smrg int value; 82ed6f5d66Smrg 83ed6f5d66Smrg pthread_mutex_lock(&f->lock); 84ed6f5d66Smrg value = f->value; 85ed6f5d66Smrg pthread_mutex_unlock(&f->lock); 86ed6f5d66Smrg return value; 87ed6f5d66Smrg} 88ed6f5d66Smrg 89ed6f5d66Smrg/** 90ed6f5d66Smrg * xshmfence_reset: 91ed6f5d66Smrg * @f: An X fence 92ed6f5d66Smrg * 93ed6f5d66Smrg * Reset @f to untriggered. If @f is already untriggered, 94ed6f5d66Smrg * this function has no effect. 95ed6f5d66Smrg **/ 96ed6f5d66Smrgvoid 97ed6f5d66Smrgxshmfence_reset(struct xshmfence *f) { 98ed6f5d66Smrg 99ed6f5d66Smrg pthread_mutex_lock(&f->lock); 100ed6f5d66Smrg f->value = 0; 101ed6f5d66Smrg pthread_mutex_unlock(&f->lock); 102ed6f5d66Smrg} 103ed6f5d66Smrg 104ed6f5d66Smrg/** 105ed6f5d66Smrg * xshmfence_init: 106ed6f5d66Smrg * @fd: An fd for an X fence 107ed6f5d66Smrg * 108ed6f5d66Smrg * Initialize the fence when first allocated 109ed6f5d66Smrg **/ 110ed6f5d66Smrg 111ed6f5d66Smrgvoid 112ed6f5d66Smrgxshmfence_init(int fd) 113ed6f5d66Smrg{ 114ed6f5d66Smrg struct xshmfence *f = xshmfence_map_shm(fd); 115ed6f5d66Smrg pthread_mutexattr_t mutex_attr; 116ed6f5d66Smrg pthread_condattr_t cond_attr; 117ed6f5d66Smrg 118ed6f5d66Smrg if (!f) 119ed6f5d66Smrg return; 120ed6f5d66Smrg 121ed6f5d66Smrg pthread_mutexattr_init(&mutex_attr); 122ed6f5d66Smrg pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); 123ed6f5d66Smrg pthread_mutex_init(&f->lock, &mutex_attr); 124ed6f5d66Smrg 125ed6f5d66Smrg pthread_condattr_init(&cond_attr); 126ed6f5d66Smrg pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); 127ed6f5d66Smrg pthread_cond_init(&f->wakeup, &cond_attr); 128ed6f5d66Smrg f->value = 0; 129ed6f5d66Smrg f->waiting = 0; 130ed6f5d66Smrg xshmfence_unmap_shm(f); 131ed6f5d66Smrg} 132