coroutine-lock: convert CoQueue to use QemuLockable
There are cases in which a queued coroutine must be restarted from non-coroutine context (with qemu_co_enter_next). In this cases, qemu_co_enter_next also needs to be thread-safe, but it cannot use a CoMutex and so cannot qemu_co_queue_wait. Use QemuLockable so that the CoQueue can interchangeably use CoMutex or QemuMutex. Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <20180203153935.8056-4-pbonzini@redhat.com> Reviewed-by: Fam Zheng <famz@redhat.com> Signed-off-by: Fam Zheng <famz@redhat.com>
This commit is contained in:
		
							parent
							
								
									e70372fcaf
								
							
						
					
					
						commit
						1a957cf9c4
					
				@ -183,7 +183,9 @@ void qemu_co_queue_init(CoQueue *queue);
 | 
				
			|||||||
 * caller of the coroutine.  The mutex is unlocked during the wait and
 | 
					 * caller of the coroutine.  The mutex is unlocked during the wait and
 | 
				
			||||||
 * locked again afterwards.
 | 
					 * locked again afterwards.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void coroutine_fn qemu_co_queue_wait(CoQueue *queue, CoMutex *mutex);
 | 
					#define qemu_co_queue_wait(queue, lock) \
 | 
				
			||||||
 | 
					    qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock))
 | 
				
			||||||
 | 
					void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Restarts the next coroutine in the CoQueue and removes it from the queue.
 | 
					 * Restarts the next coroutine in the CoQueue and removes it from the queue.
 | 
				
			||||||
@ -271,4 +273,6 @@ void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void coroutine_fn yield_until_fd_readable(int fd);
 | 
					void coroutine_fn yield_until_fd_readable(int fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "qemu/lockable.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* QEMU_COROUTINE_H */
 | 
					#endif /* QEMU_COROUTINE_H */
 | 
				
			||||||
 | 
				
			|||||||
@ -40,13 +40,13 @@ void qemu_co_queue_init(CoQueue *queue)
 | 
				
			|||||||
    QSIMPLEQ_INIT(&queue->entries);
 | 
					    QSIMPLEQ_INIT(&queue->entries);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void coroutine_fn qemu_co_queue_wait(CoQueue *queue, CoMutex *mutex)
 | 
					void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Coroutine *self = qemu_coroutine_self();
 | 
					    Coroutine *self = qemu_coroutine_self();
 | 
				
			||||||
    QSIMPLEQ_INSERT_TAIL(&queue->entries, self, co_queue_next);
 | 
					    QSIMPLEQ_INSERT_TAIL(&queue->entries, self, co_queue_next);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (mutex) {
 | 
					    if (lock) {
 | 
				
			||||||
        qemu_co_mutex_unlock(mutex);
 | 
					        qemu_lockable_unlock(lock);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* There is no race condition here.  Other threads will call
 | 
					    /* There is no race condition here.  Other threads will call
 | 
				
			||||||
@ -60,9 +60,11 @@ void coroutine_fn qemu_co_queue_wait(CoQueue *queue, CoMutex *mutex)
 | 
				
			|||||||
    /* TODO: OSv implements wait morphing here, where the wakeup
 | 
					    /* TODO: OSv implements wait morphing here, where the wakeup
 | 
				
			||||||
     * primitive automatically places the woken coroutine on the
 | 
					     * primitive automatically places the woken coroutine on the
 | 
				
			||||||
     * mutex's queue.  This avoids the thundering herd effect.
 | 
					     * mutex's queue.  This avoids the thundering herd effect.
 | 
				
			||||||
 | 
					     * This could be implemented for CoMutexes, but not really for
 | 
				
			||||||
 | 
					     * other cases of QemuLockable.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    if (mutex) {
 | 
					    if (lock) {
 | 
				
			||||||
        qemu_co_mutex_lock(mutex);
 | 
					        qemu_lockable_lock(lock);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user