 aafd758410
			
		
	
	
		aafd758410
		
	
	
	
	
		
			
			Clean up includes so that osdep.h is included first and headers which it implies are not included manually. This commit was created with scripts/clean-includes. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1454089805-5470-6-git-send-email-peter.maydell@linaro.org
		
			
				
	
	
		
			79 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			79 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Recursive FIFO lock
 | |
|  *
 | |
|  * Copyright Red Hat, Inc. 2013
 | |
|  *
 | |
|  * Authors:
 | |
|  *  Stefan Hajnoczi   <stefanha@redhat.com>
 | |
|  *
 | |
|  * This work is licensed under the terms of the GNU LGPL, version 2 or later.
 | |
|  * See the COPYING.LIB file in the top-level directory.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include "qemu/osdep.h"
 | |
| #include "qemu/rfifolock.h"
 | |
| 
 | |
| void rfifolock_init(RFifoLock *r, void (*cb)(void *), void *opaque)
 | |
| {
 | |
|     qemu_mutex_init(&r->lock);
 | |
|     r->head = 0;
 | |
|     r->tail = 0;
 | |
|     qemu_cond_init(&r->cond);
 | |
|     r->nesting = 0;
 | |
|     r->cb = cb;
 | |
|     r->cb_opaque = opaque;
 | |
| }
 | |
| 
 | |
| void rfifolock_destroy(RFifoLock *r)
 | |
| {
 | |
|     qemu_cond_destroy(&r->cond);
 | |
|     qemu_mutex_destroy(&r->lock);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Theory of operation:
 | |
|  *
 | |
|  * In order to ensure FIFO ordering, implement a ticketlock.  Threads acquiring
 | |
|  * the lock enqueue themselves by incrementing the tail index.  When the lock
 | |
|  * is unlocked, the head is incremented and waiting threads are notified.
 | |
|  *
 | |
|  * Recursive locking does not take a ticket since the head is only incremented
 | |
|  * when the outermost recursive caller unlocks.
 | |
|  */
 | |
| void rfifolock_lock(RFifoLock *r)
 | |
| {
 | |
|     qemu_mutex_lock(&r->lock);
 | |
| 
 | |
|     /* Take a ticket */
 | |
|     unsigned int ticket = r->tail++;
 | |
| 
 | |
|     if (r->nesting > 0 && qemu_thread_is_self(&r->owner_thread)) {
 | |
|         r->tail--; /* put ticket back, we're nesting */
 | |
|     } else {
 | |
|         while (ticket != r->head) {
 | |
|             /* Invoke optional contention callback */
 | |
|             if (r->cb) {
 | |
|                 r->cb(r->cb_opaque);
 | |
|             }
 | |
|             qemu_cond_wait(&r->cond, &r->lock);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     qemu_thread_get_self(&r->owner_thread);
 | |
|     r->nesting++;
 | |
|     qemu_mutex_unlock(&r->lock);
 | |
| }
 | |
| 
 | |
| void rfifolock_unlock(RFifoLock *r)
 | |
| {
 | |
|     qemu_mutex_lock(&r->lock);
 | |
|     assert(r->nesting > 0);
 | |
|     assert(qemu_thread_is_self(&r->owner_thread));
 | |
|     if (--r->nesting == 0) {
 | |
|         r->head++;
 | |
|         qemu_cond_broadcast(&r->cond);
 | |
|     }
 | |
|     qemu_mutex_unlock(&r->lock);
 | |
| }
 |