diff options
author | Zheng Da <zhengda1936@gmail.com> | 2010-02-08 08:58:53 +0100 |
---|---|---|
committer | Zheng Da <zhengda1936@gmail.com> | 2010-02-08 08:58:53 +0100 |
commit | 5ea9105dff5f22606026afcd88b178110282b224 (patch) | |
tree | 7e42a5240018310fca4e805a4df95a01c44c75e2 /libmachdev/ds_routines.c | |
parent | aff295710ea0b575c556f10981d1ae740e192969 (diff) |
remove io done thread.
eliminate a potential race condition in thread_wait and thread_wakeup.
Diffstat (limited to 'libmachdev/ds_routines.c')
-rw-r--r-- | libmachdev/ds_routines.c | 362 |
1 files changed, 0 insertions, 362 deletions
diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index c647b8e9..857f64c5 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -448,362 +448,6 @@ ds_device_map (device_t dev, vm_prot_t prot, vm_offset_t offset, return D_INVALID_OPERATION; } -boolean_t -ds_open_done(ior) - register io_req_t ior; -{ - kern_return_t result; - register mach_device_t device; - - device = ior->io_device; - result = ior->io_error; - - if (result != D_SUCCESS) { - /* - * Open failed. Deallocate port and device. - */ -// dev_port_remove(device); -// ipc_port_dealloc_kernel(device->port); - - device_lock(device); - device->state = DEV_STATE_INIT; - if (device->io_wait) { - device->io_wait = FALSE; -// thread_wakeup((event_t)device); - } - device_unlock(device); - -// mach_device_deallocate(device); - device = MACH_DEVICE_NULL; - } - else { - /* - * Open succeeded. - */ - device_lock(device); - device->state = DEV_STATE_OPEN; - device->open_count = 1; - if (device->io_wait) { - device->io_wait = FALSE; -// thread_wakeup((event_t)device); - } - device_unlock(device); - - /* donate device reference to get port */ - } - /* - * Must explicitly convert device to port, since - * device_reply interface is built as 'user' side - * (thus cannot get translation). - */ - if (MACH_PORT_VALID(ior->io_reply_port)) { - (void) ds_device_open_reply(ior->io_reply_port, - ior->io_reply_port_type, - result, - mach_convert_device_to_port(device)); - } -// else -// mach_device_deallocate(device); - - mach_device_deallocate (device); - return (TRUE); -} - -boolean_t ds_read_done(ior) - io_req_t ior; -{ - vm_offset_t start_data, end_data; - vm_offset_t start_sent, end_sent; - register vm_size_t size_read; - - if (ior->io_error) - size_read = 0; - else - size_read = ior->io_count - ior->io_residual; - - start_data = (vm_offset_t)ior->io_data; - end_data = start_data + size_read; - - start_sent = (ior->io_op & IO_INBAND) ? start_data : - trunc_page(start_data); - end_sent = (ior->io_op & IO_INBAND) ? - start_data + ior->io_alloc_size : round_page(end_data); - - /* - * Zero memory that the device did not fill. - */ - if (start_sent < start_data) - memset((char *)start_sent, 0, start_data - start_sent); - if (end_sent > end_data) - memset((char *)end_data, 0, end_sent - end_data); - - - /* - * Touch the data being returned, to mark it dirty. - * If the pages were filled by DMA, the pmap module - * may think that they are clean. - */ - { - register vm_offset_t touch; - register int c; - - for (touch = start_sent; touch < end_sent; touch += PAGE_SIZE) { - c = *(volatile char *)touch; - *(volatile char *)touch = c; - } - } - - /* - * Send the data to the reply port - this - * unwires and deallocates it. - */ - if (ior->io_op & IO_INBAND) { - (void)ds_device_read_reply_inband(ior->io_reply_port, - ior->io_reply_port_type, - ior->io_error, - (char *) start_data, - size_read); - } else { -// vm_map_copy_t copy; -// kern_return_t kr; -// -// kr = vm_map_copyin_page_list(kernel_map, start_data, -// size_read, TRUE, TRUE, -// ©, FALSE); -// -// if (kr != KERN_SUCCESS) -// panic("read_done: vm_map_copyin_page_list failed"); - - (void)ds_device_read_reply(ior->io_reply_port, - ior->io_reply_port_type, - ior->io_error, - (char *) start_data, - size_read); - } - - /* - * Free any memory that was allocated but not sent. - */ - if (ior->io_count != 0) { - if (ior->io_op & IO_INBAND) { - if (ior->io_alloc_size > 0) - free (ior->io_data); -// zfree(io_inband_zone, (vm_offset_t)ior->io_data); - } else { - register vm_offset_t end_alloc; - - end_alloc = start_sent + round_page(ior->io_alloc_size); - if (end_alloc > end_sent) - vm_deallocate(mach_task_self (), - end_sent, - end_alloc - end_sent); - } - } - - mach_device_deallocate(ior->io_device); - - return (TRUE); -} - -/* - * Allocate wired-down memory for device read. - */ -kern_return_t device_read_alloc(ior, size) - register io_req_t ior; - register vm_size_t size; -{ - vm_offset_t addr; - kern_return_t kr; - - /* - * Nothing to do if no data. - */ - if (ior->io_count == 0) - return (KERN_SUCCESS); - - if (ior->io_op & IO_INBAND) { - ior->io_data = (io_buf_ptr_t) malloc(sizeof(io_buf_ptr_inband_t)); - ior->io_alloc_size = sizeof(io_buf_ptr_inband_t); - } else { - size = round_page(size); - kr = vm_allocate (mach_task_self (), &addr, size, TRUE); -// kr = kmem_alloc(kernel_map, &addr, size); - if (kr != KERN_SUCCESS) - return (kr); - - ior->io_data = (io_buf_ptr_t) addr; - ior->io_alloc_size = size; - } - - return (KERN_SUCCESS); -} - -struct thread_wait -{ - struct condition cond; - struct mutex mutex; - int v; -}; - -static struct thread_wait io_done_wait; - -void thread_wait_init (struct thread_wait *t) -{ - mutex_init (&t->mutex); - condition_init (&t->cond); - t->v = 0; -} - -void thread_block (struct thread_wait *t) -{ - mutex_lock (&t->mutex); - t->v = 1; - while (t->v) - hurd_condition_wait (&t->cond, &t->mutex); - mutex_unlock (&t->mutex); -} - -void thread_wakeup (struct thread_wait *t) -{ - mutex_lock (&t->mutex); - t->v = 0; - condition_signal (&t->cond); - mutex_unlock (&t->mutex); -} - -queue_head_t io_done_list; -struct mutex io_done_list_lock; - -#define splio splsched /* XXX must block ALL io devices */ - -void iodone(ior) - register io_req_t ior; -{ - /* - * If this ior was loaned to us, return it directly. - */ - if (ior->io_op & IO_LOANED) { - (*ior->io_done)(ior); - return; - } - /* - * If !IO_CALL, some thread is waiting for this. Must lock - * structure to interlock correctly with iowait(). Else can - * toss on queue for io_done thread to call completion. - */ - // TODO need a lock here? -// s = splio(); - if ((ior->io_op & IO_CALL) == 0) { - ior_lock(ior); - ior->io_op |= IO_DONE; - ior->io_op &= ~IO_WANTED; - ior_unlock(ior); -// thread_wakeup((event_t)ior); - } else { - ior->io_op |= IO_DONE; - mutex_lock (&io_done_list_lock); - enqueue_tail(&io_done_list, (queue_entry_t)ior); - thread_wakeup (&io_done_wait); -// thread_wakeup((event_t)&io_done_list); - mutex_unlock (&io_done_list_lock); - } -// splx(s); -} - -void wakeup_io_done_thread () -{ - thread_wakeup (&io_done_wait); -} - -void io_done_thread_continue() -{ - for (;;) { - extern void free_skbuffs (); - register io_req_t ior; - - free_skbuffs (); - mutex_lock(&io_done_list_lock); - while ((ior = (io_req_t)dequeue_head(&io_done_list)) != 0) { - mutex_unlock(&io_done_list_lock); - - if ((*ior->io_done)(ior)) { - /* - * IO done - free io_req_elt - */ - io_req_free(ior); - } - /* else routine has re-queued it somewhere */ - - mutex_lock(&io_done_list_lock); - } - -// assert_wait(&io_done_list, FALSE); - mutex_unlock(&io_done_list_lock); -// counter(c_io_done_thread_block++); -// thread_block(io_done_thread_continue); - thread_block (&io_done_wait); - } -} - - -void -wire_thread() -{ - kern_return_t kr; - mach_port_t priv_host_port; - - kr = get_privileged_ports (&priv_host_port, NULL); - if (kr != KERN_SUCCESS) - panic("get privileged port: %d", kr); - - kr = thread_wire(priv_host_port, - mach_thread_self(), - TRUE); - if (kr != KERN_SUCCESS) - panic("wire_thread: %d", kr); -} - -void -thread_set_own_priority (int priority) -{ - kern_return_t kr; - mach_port_t priv_host_port; - mach_port_t pset, psetcntl; - - kr = get_privileged_ports (&priv_host_port, NULL); - if (kr != KERN_SUCCESS) - panic("get privileged port: %d", kr); - - kr = thread_get_assignment (mach_thread_self (), &pset); - if (kr != KERN_SUCCESS) - panic("thread get assignment: %d", kr); - kr = host_processor_set_priv (priv_host_port, pset, &psetcntl); - if (kr != KERN_SUCCESS) - panic("processor set priv: %d", kr); - kr = thread_max_priority (mach_thread_self (), psetcntl, 0); - if (kr != KERN_SUCCESS) - panic("set thread max priority: %d", kr); - kr = thread_priority (mach_thread_self (), 0, FALSE); - if (kr != KERN_SUCCESS) - panic("set thread priority: %d", kr); -} - -static any_t io_done_thread(any_t unused) -{ - /* - * Set thread privileges and highest priority. - */ -// current_thread()->vm_privilege = TRUE; -// stack_privilege(current_thread()); - wire_thread (); - - thread_set_own_priority(0); - - io_done_thread_continue(); - /*NOTREACHED*/ - return 0; -} - int create_device_port (int size, void *result) { return ports_create_port (dev_class, port_bucket, @@ -814,18 +458,12 @@ void mach_device_init() { int i; - queue_init(&io_done_list); - mutex_init (&io_done_list_lock); - thread_wait_init (&io_done_wait); - port_bucket = ports_create_bucket (); dev_class = ports_create_class (0, 0); for (i = 0; i < NUM_EMULATION; i++) { emulation_list[i]->init(); } - - cthread_detach (cthread_fork (io_done_thread, 0)); } static int |