diff options
Diffstat (limited to 'chips/nw_mk.c')
-rw-r--r-- | chips/nw_mk.c | 1323 |
1 files changed, 0 insertions, 1323 deletions
diff --git a/chips/nw_mk.c b/chips/nw_mk.c deleted file mode 100644 index 067cf7d..0000000 --- a/chips/nw_mk.c +++ /dev/null @@ -1,1323 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Scienctxe - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ - -/*** MACH KERNEL WRAPPER ***/ - -#ifndef STUB -#include <kern/task.h> -#include <kern/thread.h> -#include <kern/sched_prim.h> -#include <kern/eventcount.h> -#include <kern/time_out.h> -#include <machine/machspl.h> /* spl definitions */ -#include <vm/vm_kern.h> -#include <chips/nc.h> -#include <chips/nw_mk.h> - -decl_simple_lock_data(, nw_simple_lock); -u_int previous_spl; - -#define nw_lock() \ - previous_spl = splimp(); \ - simple_lock(&nw_simple_lock) - -#define nw_unlock() \ - simple_unlock(&nw_simple_lock); \ - splx(previous_spl) - -typedef struct nw_pvs { - task_t owner; - char *buf_start; - char *buf_end; - struct nw_pvs *next; -} nw_pv_s, *nw_pv_t; - -typedef struct nw_waiters { - thread_t waiter; - struct nw_waiters *next; -} nw_waiter_s, *nw_waiter_t; - -typedef struct { - nw_pv_t pv; - thread_t sig_waiter; - nw_waiter_t rx_first; - nw_waiter_t rx_last; - nw_waiter_t tx_first; - nw_waiter_t tx_last; -} nw_hecb, *nw_hecb_t; - -#else -#include "nc.h" -#include "nw_mk.h" -#endif - -/*** Types and data structures ***/ - -int h_initialized = FALSE; -nw_pv_s nw_pv[2*MAX_EP]; -nw_pv_t nw_free_pv; -nw_waiter_s nw_waiter[2*MAX_EP]; -nw_waiter_t nw_free_waiter; -nw_ep_owned_s nw_waited[3*MAX_EP]; -nw_ep_owned_t nw_free_waited; -nw_hecb hect[MAX_EP]; -timer_elt_data_t nw_fast_timer, nw_slow_timer; - -/*** Initialization ***/ - -void h_initialize() { - int ep, last_ep; - - if (!h_initialized) { - last_ep = sizeof(nw_pv)/sizeof(nw_pv_s) - 1; - for (ep = 0; ep < last_ep; ep++) { - nw_pv[ep].next = &nw_pv[ep+1]; - } - nw_pv[last_ep].next = NULL; - nw_free_pv = &nw_pv[0]; - last_ep = sizeof(nw_waiter)/sizeof(nw_waiter_s) - 1; - for (ep = 0; ep < last_ep; ep++) { - nw_waiter[ep].next = &nw_waiter[ep+1]; - } - nw_waiter[last_ep].next = NULL; - nw_free_waiter = &nw_waiter[0]; - last_ep = sizeof(nw_waited)/sizeof(nw_ep_owned_s) - 1; - for (ep = 0; ep < last_ep; ep++) { - nw_waited[ep].next = &nw_waited[ep+1]; - } - nw_waited[last_ep].next = NULL; - nw_free_waited = &nw_waited[0]; - last_ep = sizeof(hect)/sizeof(nw_hecb); - for (ep = 0; ep < last_ep; ep++) { - hect[ep].pv = NULL; - hect[ep].sig_waiter = NULL; - hect[ep].rx_first = NULL; - hect[ep].rx_last = NULL; - hect[ep].tx_first = NULL; - hect[ep].tx_last = NULL; - } - nw_fast_timer.fcn = mk_fast_sweep; - nw_fast_timer.param = NULL; - nw_fast_timer.set = TELT_UNSET; - nw_slow_timer.fcn = mk_slow_sweep; - nw_slow_timer.param = NULL; -#if PRODUCTION - set_timeout(&nw_slow_timer, 2*hz); -#endif - h_initialized = TRUE; - } -} - -/*** User-trappable functions ***/ - -nw_result mk_update(mach_port_t master_port, nw_update_type up_type, - int *up_info) { - nw_result rc; - - if (master_port == 0) { /* XXX */ - rc = NW_FAILURE; - } else { - nw_lock(); - switch (up_type) { - case NW_HOST_ADDRESS_REGISTER: - case NW_HOST_ADDRESS_UNREGISTER: - if (invalid_user_access(current_task()->map, (vm_offset_t) up_info, - (vm_offset_t) up_info + sizeof(nw_address_s) - 1, - VM_PROT_READ | VM_PROT_WRITE)) { - rc = NW_INVALID_ARGUMENT; - } else { - rc = nc_update(up_type, up_info); - } - break; - case NW_INITIALIZE: - nc_initialize(); - rc = NW_SUCCESS; - break; - default: - rc = NW_INVALID_ARGUMENT; - } - nw_unlock(); - } - return rc; -} - - - -nw_result mk_lookup(nw_lookup_type lt, int *look_info) { - nw_result rc; - int max_size, dev; - - nw_lock(); - switch (lt) { - case NW_HOST_ADDRESS_LOOKUP: - if (invalid_user_access(current_task()->map, (vm_offset_t) look_info, - (vm_offset_t) look_info + sizeof(nw_address_s) - 1, - VM_PROT_READ | VM_PROT_WRITE)) { - rc = NW_INVALID_ARGUMENT; - } else { - rc = nc_lookup(lt, look_info); - } - break; - case NW_STATUS: - max_size = sizeof(nw_device); - if (max_size < sizeof(nw_result)) - max_size = sizeof(nw_result); - if (invalid_user_access(current_task()->map, (vm_offset_t) look_info, - (vm_offset_t) look_info + max_size - 1, - VM_PROT_READ | VM_PROT_WRITE) || - (dev = look_info[0]) >= MAX_DEV || dev < 0) { - rc = NW_INVALID_ARGUMENT; - } else { - if (devct[dev].status != NW_SUCCESS) { - look_info[0] = (int) devct[dev].status; - rc = NW_SUCCESS; - } else { - rc = (*(devct[dev].entry->status)) (dev); - } - } - break; - default: - rc = NW_INVALID_ARGUMENT; - } - nw_unlock(); - return rc; -} - - -nw_result mk_endpoint_allocate_internal(nw_ep_t epp, nw_protocol protocol, - nw_acceptance accept, - u_int buffer_size, boolean_t system) { - nw_result rc; - u_int ep; - vm_offset_t kernel_addr, user_addr; - nw_pv_t pv; - nw_ep_owned_t owned; - - ep = *epp; - if (buffer_size == 0) - buffer_size = 0x1000; - else - buffer_size = (buffer_size + 0xfff) & ~0xfff; - nw_lock(); - if (ep >= MAX_EP || (pv = hect[ep].pv) != NULL) { - rc = NW_BAD_EP; - } else if (nw_free_pv == NULL || nw_free_waited == NULL) { - rc = NW_NO_EP; - } else if (projected_buffer_allocate(current_task()->map, buffer_size, 0, - &kernel_addr, &user_addr, - VM_PROT_READ | VM_PROT_WRITE, - VM_INHERIT_NONE) != KERN_SUCCESS) { - rc = NW_NO_RESOURCES; - } else { - rc = nc_endpoint_allocate(epp, protocol, accept, - (char *) kernel_addr, buffer_size); - if (rc == NW_NO_EP && (ep = *epp) != 0) { - rc = (*(devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry-> - close)) (ep); - if (rc == NW_SYNCH) { - hect[ep].sig_waiter = current_thread(); - assert_wait(0, TRUE); - simple_unlock(&nw_simple_lock); - thread_block((void (*)()) 0); - } - rc = nc_endpoint_deallocate(ep); - if (rc == NW_SUCCESS) { - nc_line_update(&ect[ep].conn->peer, 0); - rc = nc_endpoint_allocate(epp, protocol, accept, - (char *) kernel_addr, buffer_size); - } - } - if (rc == NW_SUCCESS) { - ep = *epp; - if (system) { - hect[ep].pv = NULL; - } else { - hect[ep].pv = nw_free_pv; - nw_free_pv = nw_free_pv->next; - hect[ep].pv->owner = current_task(); - hect[ep].pv->buf_start = (char *) user_addr; - hect[ep].pv->buf_end = (char *) user_addr + buffer_size; - hect[ep].pv->next = NULL; - } - hect[ep].sig_waiter = NULL; - hect[ep].rx_first = NULL; - hect[ep].rx_last = NULL; - hect[ep].tx_first = NULL; - hect[ep].tx_last = NULL; - owned = nw_free_waited; - nw_free_waited = nw_free_waited->next; - owned->ep = ep; - owned->next = current_task()->nw_ep_owned; - current_task()->nw_ep_owned = owned; - } else { - projected_buffer_deallocate(current_task()->map, user_addr, - user_addr + buffer_size); - } - } - nw_unlock(); - return rc; -} - - -nw_result mk_endpoint_allocate(nw_ep_t epp, nw_protocol protocol, - nw_acceptance accept, u_int buffer_size) { - nw_result rc; - - if (invalid_user_access(current_task()->map, (vm_offset_t) epp, - (vm_offset_t) epp + sizeof(nw_ep) - 1, - VM_PROT_READ | VM_PROT_WRITE) || - (protocol != NW_RAW && protocol != NW_DATAGRAM && - protocol != NW_SEQ_PACKET) || (accept != NW_NO_ACCEPT && - accept != NW_APPL_ACCEPT && accept != NW_AUTO_ACCEPT)) { - rc = NW_INVALID_ARGUMENT; - } else { - rc = mk_endpoint_allocate_internal(epp, protocol, accept, - buffer_size, FALSE); - } - return rc; -} - -nw_result mk_endpoint_deallocate_internal(nw_ep ep, task_t task, - boolean_t shutdown) { - nw_result rc; - nw_pv_t pv, pv_previous; - nw_ep_owned_t owned, owned_previous; - nw_waiter_t w, w_previous, w_next; - - nw_lock(); - if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) { - rc = NW_BAD_EP; - } else { - pv_previous = NULL; - while (pv != NULL && pv->owner != task) { - pv_previous = pv; - pv = pv->next; - } - if (pv == NULL) { - rc = NW_PROT_VIOLATION; - } else { - if (projected_buffer_deallocate(task->map, pv->buf_start, - pv->buf_end) != KERN_SUCCESS) { - rc = NW_INCONSISTENCY; - printf("Endpoint deallocate: inconsistency p. buffer\n"); - } else { - if (pv_previous == NULL) - hect[ep].pv = pv->next; - else - pv_previous->next = pv->next; - pv->next = nw_free_pv; - nw_free_pv = pv; - owned = task->nw_ep_owned; - owned_previous = NULL; - while (owned != NULL && owned->ep != ep) { - owned_previous = owned; - owned = owned->next; - } - if (owned == NULL) { - rc = NW_INCONSISTENCY; - printf("Endpoint deallocate: inconsistency owned\n"); - } else { - if (owned_previous == NULL) - task->nw_ep_owned = owned->next; - else - owned_previous->next = owned->next; - owned->next = nw_free_waited; - nw_free_waited = owned; - if (hect[ep].sig_waiter != NULL && - hect[ep].sig_waiter->task == task) { -/* if (!shutdown)*/ - mk_deliver_result(hect[ep].sig_waiter, NW_ABORTED); - hect[ep].sig_waiter = NULL; - } - w = hect[ep].rx_first; - w_previous = NULL; - while (w != NULL) { - if (w->waiter->task == task) { -/* if (!shutdown)*/ - mk_deliver_result(w->waiter, NULL); - w_next = w->next; - if (w_previous == NULL) - hect[ep].rx_first = w_next; - else - w_previous->next = w_next; - w->next = nw_free_waiter; - nw_free_waiter = w; - w = w_next; - } else { - w_previous = w; - w = w->next; - } - } - if (hect[ep].rx_first == NULL) - hect[ep].rx_last = NULL; - w = hect[ep].tx_first; - w_previous = NULL; - while (w != NULL) { - if (w->waiter->task == task) { -/* if (!shutdown)*/ - mk_deliver_result(w->waiter, NW_ABORTED); - w_next = w->next; - if (w_previous == NULL) - hect[ep].tx_first = w_next; - else - w_previous->next = w_next; - w->next = nw_free_waiter; - nw_free_waiter = w; - w = w_next; - } else { - w_previous = w; - w = w->next; - } - } - if (hect[ep].tx_first == NULL) - hect[ep].tx_last = NULL; - if (hect[ep].pv == NULL) { - if (ect[ep].state != NW_UNCONNECTED) { - rc = (*(devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry-> - close)) (ep); - if (rc == NW_SYNCH) { - hect[ep].sig_waiter = current_thread(); - assert_wait(0, TRUE); - simple_unlock(&nw_simple_lock); - thread_block((void (*)()) 0); - } - } - rc = nc_endpoint_deallocate(ep); - } - } - } - } - } - nw_unlock(); - return rc; -} - -nw_result mk_endpoint_deallocate(nw_ep ep) { - - mk_endpoint_deallocate_internal(ep, current_task(), FALSE); -} - - -nw_buffer_t mk_buffer_allocate(nw_ep ep, u_int size) { - nw_buffer_t buf; - nw_pv_t pv; - - nw_lock(); - if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) { - buf = NW_BUFFER_ERROR; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - buf = NW_BUFFER_ERROR; - } else { - buf = nc_buffer_allocate(ep, size); - if (buf != NULL) { - buf = (nw_buffer_t) ((char *) buf - ect[ep].buf_start + pv->buf_start); - } - } - } - nw_unlock(); - return buf; -} - - - -nw_result mk_buffer_deallocate(nw_ep ep, nw_buffer_t buffer) { - nw_result rc; - nw_pv_t pv; - - nw_lock(); - if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) { - rc = NW_BAD_EP; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - rc = NW_PROT_VIOLATION; - } else { - if ((char *) buffer < pv->buf_start || - (char *) buffer + sizeof(nw_buffer_s) > pv->buf_end || - !buffer->buf_used || - (char *) buffer + buffer->buf_length > pv->buf_end) { - rc = NW_BAD_BUFFER; - } else { - buffer = (nw_buffer_t) ((char *) buffer - pv->buf_start + - ect[ep].buf_start); - rc = nc_buffer_deallocate(ep, buffer); - } - } - } - nw_unlock(); - return rc; -} - - -nw_result mk_connection_open_internal(nw_ep local_ep, nw_address_1 rem_addr_1, - nw_address_2 rem_addr_2, nw_ep remote_ep) { - nw_result rc; - - rc = (*devct[NW_DEVICE(rem_addr_1)].entry->open) (local_ep, - rem_addr_1, rem_addr_2, - remote_ep); - if (rc == NW_SYNCH) { - hect[local_ep].sig_waiter = current_thread(); - assert_wait(0, TRUE); - simple_unlock(&nw_simple_lock); - thread_block((void (*)()) 0); - } - return rc; -} - -nw_result mk_connection_open(nw_ep local_ep, nw_address_1 rem_addr_1, - nw_address_2 rem_addr_2, nw_ep remote_ep) { - nw_result rc; - nw_pv_t pv; - - nw_lock(); - if (local_ep >= MAX_EP || (pv = hect[local_ep].pv) == NULL) { - rc = NW_BAD_EP; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - rc = NW_PROT_VIOLATION; - } else { - rc = (*(devct[NW_DEVICE(rem_addr_1)].entry->open)) - (local_ep, rem_addr_1, rem_addr_2, remote_ep); - if (rc == NW_SYNCH) { - hect[local_ep].sig_waiter = current_thread(); - assert_wait(0, TRUE); - current_thread()->nw_ep_waited = NULL; - simple_unlock(&nw_simple_lock); - thread_block(mk_return); - } - } - } - nw_unlock(); - return rc; -} - - -nw_result mk_connection_accept(nw_ep ep, nw_buffer_t msg, - nw_ep_t new_epp) { - nw_result rc; - nw_pv_t pv; - - nw_lock(); - if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) { - rc = NW_BAD_EP; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - rc = NW_PROT_VIOLATION; - } else if ((char *) msg < pv->buf_start || - (char *) msg + sizeof(nw_buffer_s) > pv->buf_end || - !msg->buf_used || - (char *) msg + msg->buf_length > pv->buf_end) { - rc = NW_BAD_BUFFER; - } else if (new_epp != NULL && - (invalid_user_access(current_task()->map, (vm_offset_t) new_epp, - (vm_offset_t) new_epp + sizeof(nw_ep) - 1, - VM_PROT_READ | VM_PROT_WRITE) || - (*new_epp != 0 && *new_epp != ep))) { - rc = NW_INVALID_ARGUMENT; - } else { - rc = (*(devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry->accept)) - (ep, msg, new_epp); - if (rc == NW_SYNCH) { - hect[ep].sig_waiter = current_thread(); - assert_wait(0, TRUE); - current_thread()->nw_ep_waited = NULL; - simple_unlock(&nw_simple_lock); - thread_block(mk_return); - } - } - } - nw_unlock(); - return rc; -} - -nw_result mk_connection_close(nw_ep ep) { - nw_result rc; - nw_pv_t pv; - - nw_lock(); - if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) { - rc = NW_BAD_EP; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - rc = NW_PROT_VIOLATION; - } else { - rc = (*devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry->close) - (ep); - if (rc == NW_SYNCH) { - hect[ep].sig_waiter = current_thread(); - assert_wait(0, TRUE); - current_thread()->nw_ep_waited = NULL; - simple_unlock(&nw_simple_lock); - thread_block(mk_return); - } - } - } - nw_unlock(); - return rc; -} - - -nw_result mk_multicast_add(nw_ep local_ep, nw_address_1 rem_addr_1, - nw_address_2 rem_addr_2, nw_ep remote_ep) { - nw_result rc; - nw_pv_t pv; - - nw_lock(); - if (local_ep >= MAX_EP || (pv = hect[local_ep].pv) == NULL) { - rc = NW_BAD_EP; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - rc = NW_PROT_VIOLATION; - } else { - rc = (*(devct[NW_DEVICE(rem_addr_1)].entry->add)) - (local_ep, rem_addr_1, rem_addr_2, remote_ep); - if (rc == NW_SYNCH) { - hect[local_ep].sig_waiter = current_thread(); - assert_wait(0, TRUE); - current_thread()->nw_ep_waited = NULL; - simple_unlock(&nw_simple_lock); - thread_block(mk_return); - } - } - } - nw_unlock(); - return rc; -} - - -nw_result mk_multicast_drop(nw_ep local_ep, nw_address_1 rem_addr_1, - nw_address_2 rem_addr_2, nw_ep remote_ep) { - nw_result rc; - nw_pv_t pv; - - nw_lock(); - if (local_ep >= MAX_EP || (pv = hect[local_ep].pv) == NULL) { - rc = NW_BAD_EP; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - rc = NW_PROT_VIOLATION; - } else { - rc = (*(devct[NW_DEVICE(rem_addr_1)].entry->drop)) - (local_ep, rem_addr_1, rem_addr_2, remote_ep); - if (rc == NW_SYNCH) { - hect[local_ep].sig_waiter = current_thread(); - assert_wait(0, TRUE); - current_thread()->nw_ep_waited = NULL; - simple_unlock(&nw_simple_lock); - thread_block(mk_return); - } - } - } - nw_unlock(); - return rc; -} - - -nw_result mk_endpoint_status(nw_ep ep, nw_state_t state, - nw_peer_t peer) { - nw_result rc; - nw_pv_t pv; - - nw_lock(); - if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) { - rc = NW_BAD_EP; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - rc = NW_PROT_VIOLATION; - } else { - if (invalid_user_access(current_task()->map, (vm_offset_t) state, - (vm_offset_t) state + sizeof(nw_state) - 1, - VM_PROT_WRITE) || - invalid_user_access(current_task()->map, (vm_offset_t) peer, - (vm_offset_t) peer + sizeof(nw_peer_s) - 1, - VM_PROT_WRITE)) { - rc = NW_INVALID_ARGUMENT; - } else { - rc = nc_endpoint_status(ep, state, peer); - } - } - } - nw_unlock(); - return rc; -} - - -nw_result mk_send(nw_ep ep, nw_buffer_t msg, nw_options options) { - nw_result rc; - nw_pv_t pv; - nw_ep sender; - int dev; - nw_ecb_t ecb; - nw_tx_header_t header, first_header, previous_header; - nw_hecb_t hecb; - nw_waiter_t w; - - nw_lock(); - if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) { - rc = NW_BAD_EP; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - rc = NW_PROT_VIOLATION; - } else { - ecb = &ect[ep]; - if (ecb->state == NW_INEXISTENT || - (ecb->protocol == NW_SEQ_PACKET && ecb->conn == NULL)) { - rc = NW_BAD_EP; - } else { - first_header = header = nc_tx_header_allocate(); - previous_header = NULL; - rc = NW_SUCCESS; - while (header != NULL) { - if ((char *) msg < pv->buf_start || - (char *) msg + sizeof(nw_buffer_s) > pv->buf_end || - ((int) msg & 0x3) || (msg->block_offset & 0x3) || - (msg->block_length & 0x3) || !msg->buf_used || - (char *) msg + msg->buf_length > pv->buf_end || - msg->block_offset + msg->block_length > msg->buf_length) { - rc = NW_BAD_BUFFER; - break; - } else { - if (previous_header == NULL) { - if (ecb->protocol == NW_SEQ_PACKET) - header->peer = ecb->conn->peer; - else - header->peer = msg->peer; - } else { - previous_header->next = header; - } - header->buffer = (nw_buffer_t) ((char *) msg - pv->buf_start + - ecb->buf_start); - header->block = (char *) header->buffer + msg->block_offset; - if (!msg->block_deallocate) - header->buffer = NULL; - header->msg_length = 0; - header->block_length = msg->block_length; - first_header->msg_length += header->block_length; - header->next = NULL; - if (msg->buf_next == NULL) - break; - msg = msg->buf_next; - previous_header = header; - header = nc_tx_header_allocate(); - } - } - if (header == NULL) { - nc_tx_header_deallocate(first_header); - rc = NW_NO_RESOURCES; - } else if (rc == NW_SUCCESS) { - dev = NW_DEVICE(first_header->peer.rem_addr_1); - if (ecb->protocol != NW_DATAGRAM || - devct[dev].type != NW_CONNECTION_ORIENTED) { - sender = first_header->peer.local_ep; - rc = NW_SUCCESS; - } else { - sender = nc_line_lookup(&first_header->peer); - if (sender == -1) { - rc = NW_BAD_ADDRESS; - } else if (sender > 0) { - rc = NW_SUCCESS; - } else { - rc = mk_endpoint_allocate_internal(&sender, NW_LINE, - NW_AUTO_ACCEPT, 0, TRUE); - if (rc == NW_SUCCESS) { - rc = mk_connection_open_internal(sender, - first_header->peer.rem_addr_1, - first_header->peer.rem_addr_2, - MASTER_LINE_EP); - if (rc == NW_SUCCESS) - nc_line_update(&first_header->peer, sender); - } - } - } - if (rc == NW_SUCCESS) { - first_header->sender = sender; - first_header->options = options; - rc = (*(devct[dev].entry->send)) (sender, first_header, options); - if ((rc == NW_SYNCH || rc == NW_QUEUED) && - nw_free_waiter != NULL) { - w = nw_free_waiter; - nw_free_waiter = w->next; - w->waiter = current_thread(); - w->next = NULL; - hecb = &hect[sender]; - if (hecb->tx_last == NULL) { - hecb->tx_first = hecb->tx_last = w; - } else { - hecb->tx_last = hecb->tx_last->next = w; - } - assert_wait(0, TRUE); - current_thread()->nw_ep_waited = NULL; - simple_unlock(&nw_simple_lock); - thread_block(mk_return); - } - } - } - } - } - } - nw_unlock(); - return rc; -} - - -nw_buffer_t mk_receive(nw_ep ep, int time_out) { - nw_buffer_t rc; - nw_pv_t pv; - nw_ecb_t ecb; - nw_rx_header_t header; - nw_hecb_t hecb; - nw_waiter_t w; - nw_ep_owned_t waited; - - nw_lock(); - if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) { - rc = NW_BUFFER_ERROR; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - rc = NW_BUFFER_ERROR; - } else { - ecb = &ect[ep]; - header = ecb->rx_first; - if (header != NULL) { - rc = (nw_buffer_t) ((char *) header->buffer - ecb->buf_start + - pv->buf_start); - ecb->rx_first = header->next; - if (ecb->rx_first == NULL) - ecb->rx_last = NULL; - nc_rx_header_deallocate(header); - } else if (time_out != 0 && nw_free_waiter != NULL && - (time_out == -1 || nw_free_waited != NULL)) { - w = nw_free_waiter; - nw_free_waiter = w->next; - w->waiter = current_thread(); - w->next = NULL; - hecb = &hect[ep]; - if (hecb->rx_last == NULL) - hecb->rx_first = hecb->rx_last = w; - else - hecb->rx_last = hecb->rx_last->next = w; - assert_wait(0, TRUE); - if (time_out != -1) { - waited = nw_free_waited; - nw_free_waited = waited->next; - waited->ep = ep; - waited->next = NULL; - current_thread()->nw_ep_waited = waited; - current_thread()->wait_result = NULL; - if (!current_thread()->timer.set) - thread_set_timeout(time_out); - } else { - current_thread()->nw_ep_waited = NULL; - } - simple_unlock(&nw_simple_lock); - thread_block(mk_return); - } else { - rc = NULL; - } - } - } - nw_unlock(); - return rc; -} - - -nw_buffer_t mk_rpc(nw_ep ep, nw_buffer_t msg, nw_options options, - int time_out) { - nw_buffer_t rc; - nw_result nrc; - nw_ep sender; - int dev; - nw_pv_t pv; - nw_ecb_t ecb; - nw_tx_header_t header, first_header, previous_header; - nw_hecb_t hecb; - nw_waiter_t w; - nw_ep_owned_t waited; - - nw_lock(); - if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) { - rc = NW_BUFFER_ERROR; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - rc = NW_BUFFER_ERROR; - } else { - ecb = &ect[ep]; - if (ecb->state == NW_INEXISTENT || - (ecb->protocol == NW_SEQ_PACKET && ecb->conn == NULL)) { - rc = NW_BUFFER_ERROR; - } else { - first_header = header = nc_tx_header_allocate(); - previous_header = NULL; - rc = NULL; - while (header != NULL) { - if ((char *) msg < pv->buf_start || - (char *) msg + sizeof(nw_buffer_s) > pv->buf_end || - ((int) msg & 0x3) || (msg->block_offset & 0x3) || - (msg->block_length & 0x3) || !msg->buf_used || - (char *) msg + msg->buf_length > pv->buf_end || - msg->block_offset + msg->block_length > msg->buf_length) { - rc = NW_BUFFER_ERROR; - break; - } else { - if (previous_header == NULL) { - if (ecb->protocol == NW_SEQ_PACKET) - header->peer = ecb->conn->peer; - else - header->peer = msg->peer; - } else { - previous_header->next = header; - } - header->buffer = (nw_buffer_t) ((char *) msg - pv->buf_start + - ecb->buf_start); - header->block = (char *) header->buffer + msg->block_offset; - if (!msg->block_deallocate) - header->buffer = NULL; - header->msg_length = 0; - header->block_length = msg->block_length; - first_header->msg_length += header->block_length; - header->next = NULL; - if (msg->buf_next == NULL) - break; - msg = msg->buf_next; - previous_header = header; - header = nc_tx_header_allocate(); - } - } - if (header == NULL) { - nc_tx_header_deallocate(first_header); - rc = NW_BUFFER_ERROR; - } else if (rc != NW_BUFFER_ERROR) { - dev = NW_DEVICE(first_header->peer.rem_addr_1); - if (ecb->protocol != NW_DATAGRAM || - devct[dev].type != NW_CONNECTION_ORIENTED) { - sender = first_header->peer.local_ep; - nrc = NW_SUCCESS; - } else { - sender = nc_line_lookup(&first_header->peer); - if (sender == -1) { - nrc = NW_BAD_ADDRESS; - } else if (sender > 0) { - nrc = NW_SUCCESS; - } else { - nrc = mk_endpoint_allocate_internal(&sender, NW_LINE, - NW_AUTO_ACCEPT, 0, TRUE); - if (nrc == NW_SUCCESS) { - nrc = mk_connection_open_internal(sender, - first_header->peer.rem_addr_1, - first_header->peer.rem_addr_2, - MASTER_LINE_EP); - if (nrc == NW_SUCCESS) - nc_line_update(&first_header->peer, sender); - } - } - } - if (nrc == NW_SUCCESS) { - first_header->sender = sender; - first_header->options = options; - rc = (*(devct[dev].entry->rpc)) (sender, first_header, options); - if (rc != NULL && rc != NW_BUFFER_ERROR) { - rc = (nw_buffer_t) ((char *) rc - ecb->buf_start + - pv->buf_start); - } else if (rc == NULL && time_out != 0 && nw_free_waiter != NULL && - (time_out == -1 || nw_free_waited != NULL)) { - w = nw_free_waiter; - nw_free_waiter = w->next; - w->waiter = current_thread(); - w->next = NULL; - hecb = &hect[ep]; - if (hecb->rx_last == NULL) - hecb->rx_first = hecb->rx_last = w; - else - hecb->rx_last = hecb->rx_last->next = w; - assert_wait(0, TRUE); - if (time_out != -1) { - waited = nw_free_waited; - nw_free_waited = waited->next; - waited->ep = ep; - waited->next = NULL; - current_thread()->nw_ep_waited = waited; - current_thread()->wait_result = NULL; - if (!current_thread()->timer.set) - thread_set_timeout(time_out); - } else { - current_thread()->nw_ep_waited = NULL; - } - simple_unlock(&nw_simple_lock); - thread_block(mk_return); - } - } - } - } - } - } - nw_unlock(); - return rc; -} - -nw_buffer_t mk_select(u_int nep, nw_ep_t epp, int time_out) { - nw_buffer_t rc; - nw_pv_t pv; - int i; - nw_ep ep; - nw_ecb_t ecb; - nw_rx_header_t header; - nw_hecb_t hecb; - nw_waiter_t w, w_next; - nw_ep_owned_t waited; - - if (invalid_user_access(current_task()->map, (vm_offset_t) epp, - (vm_offset_t) epp + nep*sizeof(nw_ep) - 1, - VM_PROT_READ)) { - rc = NW_BUFFER_ERROR; - } else { - nw_lock(); - for (i = 0; i < nep; i++) { - ep = epp[i]; - if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) { - rc = NW_BUFFER_ERROR; - break; - } else { - while (pv != NULL && pv->owner != current_task()) - pv = pv->next; - if (pv == NULL) { - rc = NW_BUFFER_ERROR; - break; - } else { - ecb = &ect[ep]; - header = ecb->rx_first; - if (header != NULL) { - rc = (nw_buffer_t) ((char *) header->buffer - ecb->buf_start + - pv->buf_start); - ecb->rx_first = header->next; - if (ecb->rx_first == NULL) - ecb->rx_last = NULL; - nc_rx_header_deallocate(header); - break; - } - } - } - } - if (i == nep) { - if (time_out == 0) { - rc = NULL; - } else { - w = nw_free_waiter; - waited = nw_free_waited; - i = 0; - while (i < nep && - nw_free_waiter != NULL && nw_free_waited != NULL) { - nw_free_waiter = nw_free_waiter->next; - nw_free_waited = nw_free_waited->next; - i++; - } - if (i < nep) { - nw_free_waiter = w; - nw_free_waited = waited; - rc = NW_BUFFER_ERROR; - } else { - current_thread()->nw_ep_waited = waited; - for (i = 0; i < nep; i++) { - ep = epp[i]; - waited->ep = ep; - if (i < nep-1) - waited = waited->next; - else - waited->next = NULL; - w->waiter = current_thread(); - w_next = w->next; - w->next = NULL; - hecb = &hect[ep]; - if (hecb->rx_last == NULL) - hecb->rx_first = hecb->rx_last = w; - else - hecb->rx_last = hecb->rx_last->next = w; - w = w_next; - } - assert_wait(0, TRUE); - if (time_out != -1) { - current_thread()->wait_result = NULL; - if (!current_thread()->timer.set) - thread_set_timeout(time_out); - } - simple_unlock(&nw_simple_lock); - thread_block(mk_return); - } - } - } - nw_unlock(); - } - return rc; -} - - -/*** System-dependent support ***/ - -void mk_endpoint_collect(task_t task) { - - while (task->nw_ep_owned != NULL) { - mk_endpoint_deallocate_internal(task->nw_ep_owned->ep, task, TRUE); - } -} - -void mk_waited_collect(thread_t thread) { - nw_hecb_t hecb; - nw_waiter_t w, w_previous; - nw_ep_owned_t waited, waited_previous; - - waited = thread->nw_ep_waited; - if (waited != NULL) { - while (waited != NULL) { - hecb = &hect[waited->ep]; - w = hecb->rx_first; - w_previous = NULL; - while (w != NULL && w->waiter != thread) { - w_previous = w; - w = w->next; - } - if (w != NULL) { - if (w_previous == NULL) - hecb->rx_first = w->next; - else - w_previous->next = w->next; - if (w->next == NULL) - hecb->rx_last = w_previous; - w->next = nw_free_waiter; - nw_free_waiter = w; - } - waited_previous = waited; - waited = waited->next; - } - waited_previous->next = nw_free_waited; - nw_free_waited = thread->nw_ep_waited; - thread->nw_ep_waited = NULL; - } -} - -void mk_return() { - - thread_syscall_return(current_thread()->wait_result); -} - - -boolean_t mk_deliver_result(thread_t thread, int result) { - boolean_t rc; - int state, s; - - s = splsched(); - thread_lock(thread); - state = thread->state; - - reset_timeout_check(&thread->timer); - - switch (state & TH_SCHED_STATE) { - case TH_WAIT | TH_SUSP | TH_UNINT: - case TH_WAIT | TH_UNINT: - case TH_WAIT: - /* - * Sleeping and not suspendable - put on run queue. - */ - thread->state = (state &~ TH_WAIT) | TH_RUN; - thread->wait_result = (kern_return_t) result; - simpler_thread_setrun(thread, TRUE); - rc = TRUE; - break; - - case TH_WAIT | TH_SUSP: - case TH_RUN | TH_WAIT: - case TH_RUN | TH_WAIT | TH_SUSP: - case TH_RUN | TH_WAIT | TH_UNINT: - case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT: - /* - * Either already running, or suspended. - */ - thread->state = state &~ TH_WAIT; - thread->wait_result = (kern_return_t) result; - rc = FALSE; - break; - - default: - /* - * Not waiting. - */ - rc = FALSE; - break; - } - thread_unlock(thread); - splx(s); - return rc; -} - - -boolean_t nc_deliver_result(nw_ep ep, nw_delivery type, int result) { - boolean_t rc; - nw_hecb_t hecb; - nw_ecb_t ecb; - nw_waiter_t w; - thread_t thread; - task_t task; - nw_pv_t pv; - nw_buffer_t buf; - nw_rx_header_t rx_header; - nw_tx_header_t tx_header; - nw_ep lep; - - hecb = &hect[ep]; - ecb = &ect[ep]; - - thread = NULL; - if (type == NW_RECEIVE || type == NW_RECEIVE_URGENT) { - w = hecb->rx_first; - if (w != NULL) { - thread = w->waiter; - hecb->rx_first = w->next; - if (hecb->rx_first == NULL) - hecb->rx_last = NULL; - w->next = nw_free_waiter; - nw_free_waiter = w; - task = thread->task; - pv = hecb->pv; - while (pv != NULL && pv->owner != task) - pv = pv->next; - if (pv == NULL) { - rc = FALSE; - } else { - buf = (nw_buffer_t) ((char *) result - ecb->buf_start + pv->buf_start); - rc = mk_deliver_result(thread, (int) buf); - } - } else { - rx_header = nc_rx_header_allocate(); - if (rx_header == NULL) { - rc = FALSE; - } else { - rx_header->buffer = (nw_buffer_t) result; - if (type == NW_RECEIVE) { - rx_header->next = NULL; - if (ecb->rx_last == NULL) - ecb->rx_first = rx_header; - else - ecb->rx_last->next = rx_header; - ecb->rx_last = rx_header; - } else { - rx_header->next = ecb->rx_first; - if (ecb->rx_first == NULL) - ecb->rx_last = rx_header; - ecb->rx_first = rx_header; - } - rc = TRUE; - } - } - } else if (type == NW_SEND) { - w = hecb->tx_first; - if (w == NULL) { - rc = FALSE; - } else { - thread = w->waiter; - hecb->tx_first = w->next; - if (hecb->tx_first == NULL) - hecb->tx_last = NULL; - w->next = nw_free_waiter; - nw_free_waiter = w; - rc = mk_deliver_result(thread, result); - } - tx_header = ect[ep].tx_initial; - if (result == NW_SUCCESS) { - lep = tx_header->peer.local_ep; - while (tx_header != NULL) { - if (tx_header->buffer != NULL) - nc_buffer_deallocate(lep, tx_header->buffer); - tx_header = tx_header->next; - } - } - nc_tx_header_deallocate(ect[ep].tx_initial); - ect[ep].tx_initial = ect[ep].tx_current = NULL; - } else if (type == NW_SIGNAL) { - thread = hecb->sig_waiter; - hecb->sig_waiter = NULL; - if (thread == NULL) { - rc = FALSE; - } else { - rc = mk_deliver_result(thread, result); - } - } - return rc; -} - -int mk_fast_sweep() { - - nw_lock(); - nc_fast_sweep(); - nw_unlock(); - return 0; -} - -void h_fast_timer_set() { - -#ifdef PRODUCTION - if (!nw_fast_timer.set) - set_timeout(&nw_fast_timer, 1); -#endif -} - -void h_fast_timer_reset() { - - if (nw_fast_timer.set) - reset_timeout(&nw_fast_timer); -} - -int mk_slow_sweep() { - -#ifdef PRODUCTION - nw_lock(); - nc_slow_sweep(); - nw_unlock(); - set_timeout(&nw_slow_timer, 2*hz); - return 0; -#endif -} - |