Annotation of Gnu-Mach/chips/nw_mk.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  * 
        !             6:  * Permission to use, copy, modify and distribute this software and its
        !             7:  * documentation is hereby granted, provided that both the copyright
        !             8:  * notice and this permission notice appear in all copies of the
        !             9:  * software, derivative works or modified versions, and any portions
        !            10:  * thereof, and that both notices appear in supporting documentation.
        !            11:  * 
        !            12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            15:  * 
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  * 
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Scienctxe
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  * 
        !            23:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            24:  * the rights to redistribute these changes.
        !            25:  */
        !            26: 
        !            27: /*** MACH KERNEL WRAPPER ***/
        !            28: 
        !            29: #ifndef STUB
        !            30: #include <kern/task.h>
        !            31: #include <kern/thread.h>
        !            32: #include <kern/sched_prim.h>
        !            33: #include <kern/eventcount.h>
        !            34: #include <kern/time_out.h>           
        !            35: #include <machine/machspl.h>           /* spl definitions */
        !            36: #include <vm/vm_kern.h>
        !            37: #include <chips/nc.h>
        !            38: #include <chips/nw_mk.h>
        !            39: 
        !            40: decl_simple_lock_data(, nw_simple_lock);
        !            41: u_int previous_spl;
        !            42: 
        !            43: #define nw_lock() \
        !            44:   previous_spl = splimp(); \
        !            45:   simple_lock(&nw_simple_lock)
        !            46: 
        !            47: #define nw_unlock() \
        !            48:   simple_unlock(&nw_simple_lock); \
        !            49:   splx(previous_spl)
        !            50: 
        !            51: typedef struct nw_pvs {
        !            52:   task_t owner;
        !            53:   char *buf_start;
        !            54:   char *buf_end;
        !            55:   struct nw_pvs *next;
        !            56: } nw_pv_s, *nw_pv_t;
        !            57: 
        !            58: typedef struct nw_waiters {
        !            59:   thread_t waiter;
        !            60:   struct nw_waiters *next;
        !            61: } nw_waiter_s, *nw_waiter_t;
        !            62: 
        !            63: typedef struct {
        !            64:   nw_pv_t pv;
        !            65:   thread_t sig_waiter;
        !            66:   nw_waiter_t rx_first;
        !            67:   nw_waiter_t rx_last;
        !            68:   nw_waiter_t tx_first;
        !            69:   nw_waiter_t tx_last;
        !            70: } nw_hecb, *nw_hecb_t;
        !            71: 
        !            72: #else
        !            73: #include "nc.h"
        !            74: #include "nw_mk.h"
        !            75: #endif
        !            76: 
        !            77: /*** Types and data structures ***/
        !            78: 
        !            79: int h_initialized = FALSE;
        !            80: nw_pv_s nw_pv[2*MAX_EP];
        !            81: nw_pv_t nw_free_pv;
        !            82: nw_waiter_s nw_waiter[2*MAX_EP];
        !            83: nw_waiter_t nw_free_waiter;
        !            84: nw_ep_owned_s nw_waited[3*MAX_EP];
        !            85: nw_ep_owned_t nw_free_waited;
        !            86: nw_hecb hect[MAX_EP];
        !            87: timer_elt_data_t nw_fast_timer, nw_slow_timer;
        !            88: 
        !            89: /*** Initialization ***/
        !            90: 
        !            91: void h_initialize() {
        !            92:   int ep, last_ep;
        !            93: 
        !            94:   if (!h_initialized) {
        !            95:     last_ep = sizeof(nw_pv)/sizeof(nw_pv_s) - 1;
        !            96:     for (ep = 0; ep < last_ep; ep++) {
        !            97:       nw_pv[ep].next = &nw_pv[ep+1];
        !            98:     }
        !            99:     nw_pv[last_ep].next = NULL;
        !           100:     nw_free_pv = &nw_pv[0];
        !           101:     last_ep = sizeof(nw_waiter)/sizeof(nw_waiter_s) - 1;
        !           102:     for (ep = 0; ep < last_ep; ep++) {
        !           103:       nw_waiter[ep].next = &nw_waiter[ep+1];
        !           104:     }
        !           105:     nw_waiter[last_ep].next = NULL;
        !           106:     nw_free_waiter = &nw_waiter[0];
        !           107:     last_ep = sizeof(nw_waited)/sizeof(nw_ep_owned_s) - 1;
        !           108:     for (ep = 0; ep < last_ep; ep++) {
        !           109:       nw_waited[ep].next = &nw_waited[ep+1];
        !           110:     }
        !           111:     nw_waited[last_ep].next = NULL;
        !           112:     nw_free_waited = &nw_waited[0];
        !           113:     last_ep = sizeof(hect)/sizeof(nw_hecb);
        !           114:     for (ep = 0; ep < last_ep; ep++) {
        !           115:       hect[ep].pv = NULL;
        !           116:       hect[ep].sig_waiter = NULL;
        !           117:       hect[ep].rx_first = NULL;
        !           118:       hect[ep].rx_last = NULL;
        !           119:       hect[ep].tx_first = NULL;
        !           120:       hect[ep].tx_last = NULL;
        !           121:     }
        !           122:     nw_fast_timer.fcn = mk_fast_sweep;
        !           123:     nw_fast_timer.param = NULL;
        !           124:     nw_fast_timer.set = TELT_UNSET;
        !           125:     nw_slow_timer.fcn = mk_slow_sweep;
        !           126:     nw_slow_timer.param = NULL;
        !           127: #if PRODUCTION
        !           128:     set_timeout(&nw_slow_timer, 2*hz);
        !           129: #endif
        !           130:     h_initialized = TRUE;
        !           131:   }
        !           132: }
        !           133: 
        !           134: /*** User-trappable functions ***/  
        !           135: 
        !           136: nw_result mk_update(mach_port_t master_port, nw_update_type up_type,
        !           137:                    int *up_info) {
        !           138:   nw_result rc;
        !           139: 
        !           140:   if (master_port == 0) {          /* XXX */
        !           141:     rc = NW_FAILURE;
        !           142:   } else {
        !           143:     nw_lock();
        !           144:     switch (up_type) {
        !           145:     case NW_HOST_ADDRESS_REGISTER:
        !           146:     case NW_HOST_ADDRESS_UNREGISTER:
        !           147:       if (invalid_user_access(current_task()->map, (vm_offset_t) up_info,
        !           148:                              (vm_offset_t) up_info + sizeof(nw_address_s) - 1,
        !           149:                              VM_PROT_READ | VM_PROT_WRITE)) {
        !           150:        rc = NW_INVALID_ARGUMENT;
        !           151:       } else {
        !           152:        rc = nc_update(up_type, up_info);
        !           153:       }
        !           154:       break;
        !           155:     case NW_INITIALIZE:
        !           156:       nc_initialize();
        !           157:       rc = NW_SUCCESS;
        !           158:       break;
        !           159:     default:
        !           160:       rc = NW_INVALID_ARGUMENT;
        !           161:     }
        !           162:     nw_unlock();
        !           163:   }
        !           164:   return rc;
        !           165: }
        !           166: 
        !           167: 
        !           168: 
        !           169: nw_result mk_lookup(nw_lookup_type lt, int *look_info) {
        !           170:   nw_result rc;
        !           171:   int max_size, dev;
        !           172:   
        !           173:   nw_lock();
        !           174:   switch (lt) {
        !           175:   case NW_HOST_ADDRESS_LOOKUP:
        !           176:     if (invalid_user_access(current_task()->map, (vm_offset_t) look_info,
        !           177:                            (vm_offset_t) look_info + sizeof(nw_address_s) - 1,
        !           178:                            VM_PROT_READ | VM_PROT_WRITE)) {
        !           179:       rc = NW_INVALID_ARGUMENT;
        !           180:     } else {
        !           181:       rc = nc_lookup(lt, look_info);
        !           182:     }
        !           183:     break;
        !           184:   case NW_STATUS:
        !           185:     max_size = sizeof(nw_device);
        !           186:     if (max_size < sizeof(nw_result))
        !           187:       max_size = sizeof(nw_result);
        !           188:     if (invalid_user_access(current_task()->map, (vm_offset_t) look_info,
        !           189:                            (vm_offset_t) look_info + max_size - 1,
        !           190:                            VM_PROT_READ | VM_PROT_WRITE) ||
        !           191:        (dev = look_info[0]) >= MAX_DEV || dev < 0) {
        !           192:       rc = NW_INVALID_ARGUMENT;
        !           193:     } else {
        !           194:       if (devct[dev].status != NW_SUCCESS) {
        !           195:        look_info[0] = (int) devct[dev].status;
        !           196:        rc = NW_SUCCESS;
        !           197:       } else {
        !           198:        rc = (*(devct[dev].entry->status)) (dev);
        !           199:       }
        !           200:     }
        !           201:     break;
        !           202:   default:
        !           203:     rc = NW_INVALID_ARGUMENT;
        !           204:   }
        !           205:   nw_unlock();
        !           206:   return rc;
        !           207: }
        !           208: 
        !           209: 
        !           210: nw_result mk_endpoint_allocate_internal(nw_ep_t epp, nw_protocol protocol,
        !           211:                                        nw_acceptance accept,
        !           212:                                        u_int buffer_size, boolean_t system) {
        !           213:   nw_result rc;
        !           214:   u_int ep;
        !           215:   vm_offset_t kernel_addr, user_addr;
        !           216:   nw_pv_t pv;
        !           217:   nw_ep_owned_t owned;
        !           218: 
        !           219:     ep = *epp;
        !           220:     if (buffer_size == 0)
        !           221:       buffer_size = 0x1000;
        !           222:     else
        !           223:       buffer_size = (buffer_size + 0xfff) & ~0xfff;
        !           224:     nw_lock();
        !           225:     if (ep >= MAX_EP || (pv = hect[ep].pv) != NULL) {
        !           226:       rc = NW_BAD_EP;
        !           227:     } else if (nw_free_pv == NULL || nw_free_waited == NULL) {
        !           228:       rc = NW_NO_EP;
        !           229:     } else if (projected_buffer_allocate(current_task()->map, buffer_size, 0,
        !           230:                                         &kernel_addr, &user_addr,
        !           231:                                         VM_PROT_READ | VM_PROT_WRITE,
        !           232:                                         VM_INHERIT_NONE) != KERN_SUCCESS) {
        !           233:       rc = NW_NO_RESOURCES;
        !           234:     } else {
        !           235:       rc = nc_endpoint_allocate(epp, protocol, accept,
        !           236:                                (char *) kernel_addr, buffer_size);
        !           237:       if (rc == NW_NO_EP && (ep = *epp) != 0) {
        !           238:        rc = (*(devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry->
        !           239:                         close)) (ep);
        !           240:        if (rc == NW_SYNCH) {
        !           241:          hect[ep].sig_waiter = current_thread();
        !           242:          assert_wait(0, TRUE);
        !           243:          simple_unlock(&nw_simple_lock);
        !           244:          thread_block((void (*)()) 0);
        !           245:        }
        !           246:        rc = nc_endpoint_deallocate(ep);
        !           247:        if (rc == NW_SUCCESS) {
        !           248:          nc_line_update(&ect[ep].conn->peer, 0);
        !           249:          rc = nc_endpoint_allocate(epp, protocol, accept,
        !           250:                                    (char *) kernel_addr, buffer_size);
        !           251:        }
        !           252:       }
        !           253:       if (rc == NW_SUCCESS) {
        !           254:        ep = *epp;
        !           255:        if (system) {
        !           256:          hect[ep].pv = NULL;
        !           257:        } else {
        !           258:          hect[ep].pv = nw_free_pv;
        !           259:          nw_free_pv = nw_free_pv->next;
        !           260:          hect[ep].pv->owner = current_task();
        !           261:          hect[ep].pv->buf_start = (char *) user_addr;
        !           262:          hect[ep].pv->buf_end = (char *) user_addr + buffer_size;
        !           263:          hect[ep].pv->next = NULL;
        !           264:        }
        !           265:        hect[ep].sig_waiter = NULL;
        !           266:        hect[ep].rx_first = NULL;
        !           267:        hect[ep].rx_last = NULL;
        !           268:        hect[ep].tx_first = NULL;
        !           269:        hect[ep].tx_last = NULL;
        !           270:        owned = nw_free_waited;
        !           271:        nw_free_waited = nw_free_waited->next;
        !           272:        owned->ep = ep;
        !           273:        owned->next = current_task()->nw_ep_owned;
        !           274:        current_task()->nw_ep_owned = owned;
        !           275:       } else {
        !           276:        projected_buffer_deallocate(current_task()->map, user_addr,
        !           277:                                    user_addr + buffer_size);
        !           278:       } 
        !           279:     }
        !           280:   nw_unlock();
        !           281:   return rc;
        !           282: }
        !           283: 
        !           284: 
        !           285: nw_result mk_endpoint_allocate(nw_ep_t epp, nw_protocol protocol,
        !           286:                               nw_acceptance accept, u_int buffer_size) {
        !           287:   nw_result rc;
        !           288: 
        !           289:   if (invalid_user_access(current_task()->map, (vm_offset_t) epp,
        !           290:                          (vm_offset_t) epp + sizeof(nw_ep) - 1,
        !           291:                          VM_PROT_READ | VM_PROT_WRITE) ||
        !           292:       (protocol != NW_RAW && protocol != NW_DATAGRAM &&
        !           293:        protocol != NW_SEQ_PACKET) || (accept != NW_NO_ACCEPT &&
        !           294:        accept != NW_APPL_ACCEPT && accept  != NW_AUTO_ACCEPT)) {
        !           295:     rc = NW_INVALID_ARGUMENT;
        !           296:   } else {
        !           297:     rc = mk_endpoint_allocate_internal(epp, protocol, accept,
        !           298:                                       buffer_size, FALSE);
        !           299:   }
        !           300:   return rc;
        !           301: }
        !           302: 
        !           303: nw_result mk_endpoint_deallocate_internal(nw_ep ep, task_t task,
        !           304:                                          boolean_t shutdown) {
        !           305:   nw_result rc;
        !           306:   nw_pv_t pv, pv_previous;
        !           307:   nw_ep_owned_t owned, owned_previous;
        !           308:   nw_waiter_t w, w_previous, w_next;
        !           309: 
        !           310:   nw_lock();
        !           311:   if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
        !           312:     rc = NW_BAD_EP;
        !           313:   } else {
        !           314:     pv_previous = NULL;
        !           315:     while (pv != NULL && pv->owner != task) {
        !           316:       pv_previous = pv;
        !           317:       pv = pv->next;
        !           318:     }
        !           319:     if (pv == NULL) {
        !           320:       rc = NW_PROT_VIOLATION;
        !           321:     } else {
        !           322:       if (projected_buffer_deallocate(task->map, pv->buf_start,
        !           323:                                      pv->buf_end) != KERN_SUCCESS) {
        !           324:        rc = NW_INCONSISTENCY;
        !           325:        printf("Endpoint deallocate: inconsistency p. buffer\n");
        !           326:       } else {
        !           327:        if (pv_previous == NULL)
        !           328:          hect[ep].pv = pv->next;
        !           329:        else
        !           330:          pv_previous->next = pv->next;
        !           331:        pv->next = nw_free_pv;
        !           332:        nw_free_pv = pv;
        !           333:        owned = task->nw_ep_owned;
        !           334:        owned_previous = NULL;
        !           335:        while (owned != NULL && owned->ep != ep) {
        !           336:          owned_previous = owned;
        !           337:          owned = owned->next;
        !           338:        }
        !           339:        if (owned == NULL) {
        !           340:          rc = NW_INCONSISTENCY;
        !           341:          printf("Endpoint deallocate: inconsistency owned\n");
        !           342:        } else {
        !           343:          if (owned_previous == NULL)
        !           344:            task->nw_ep_owned = owned->next;
        !           345:          else
        !           346:            owned_previous->next = owned->next;
        !           347:          owned->next = nw_free_waited;
        !           348:          nw_free_waited = owned;
        !           349:          if (hect[ep].sig_waiter != NULL &&
        !           350:              hect[ep].sig_waiter->task == task) {
        !           351: /*         if (!shutdown)*/
        !           352:              mk_deliver_result(hect[ep].sig_waiter, NW_ABORTED);
        !           353:            hect[ep].sig_waiter = NULL;
        !           354:          }
        !           355:          w = hect[ep].rx_first;
        !           356:          w_previous = NULL;
        !           357:          while (w != NULL) {
        !           358:            if (w->waiter->task == task) {
        !           359: /*           if (!shutdown)*/
        !           360:                mk_deliver_result(w->waiter, NULL);
        !           361:              w_next = w->next;
        !           362:              if (w_previous == NULL)
        !           363:                hect[ep].rx_first = w_next;
        !           364:              else
        !           365:                w_previous->next = w_next;
        !           366:              w->next = nw_free_waiter;
        !           367:              nw_free_waiter = w;
        !           368:              w = w_next;
        !           369:            } else {
        !           370:              w_previous = w;
        !           371:              w = w->next;
        !           372:            }
        !           373:          }
        !           374:          if (hect[ep].rx_first == NULL)
        !           375:            hect[ep].rx_last = NULL;
        !           376:          w = hect[ep].tx_first;
        !           377:          w_previous = NULL;
        !           378:          while (w != NULL) {
        !           379:            if (w->waiter->task == task) {
        !           380: /*           if (!shutdown)*/
        !           381:                mk_deliver_result(w->waiter, NW_ABORTED);
        !           382:              w_next = w->next;
        !           383:              if (w_previous == NULL)
        !           384:                hect[ep].tx_first = w_next;
        !           385:              else
        !           386:                w_previous->next = w_next;
        !           387:              w->next = nw_free_waiter;
        !           388:              nw_free_waiter = w;
        !           389:              w = w_next;
        !           390:            } else {
        !           391:              w_previous = w;
        !           392:              w = w->next;
        !           393:            }
        !           394:          }
        !           395:          if (hect[ep].tx_first == NULL)
        !           396:            hect[ep].tx_last = NULL;
        !           397:          if (hect[ep].pv == NULL) {
        !           398:            if (ect[ep].state != NW_UNCONNECTED) {
        !           399:              rc = (*(devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry->
        !           400:                         close)) (ep);
        !           401:              if (rc == NW_SYNCH) {
        !           402:                hect[ep].sig_waiter = current_thread();
        !           403:                assert_wait(0, TRUE);
        !           404:                simple_unlock(&nw_simple_lock);
        !           405:                thread_block((void (*)()) 0);
        !           406:              }
        !           407:            }
        !           408:            rc = nc_endpoint_deallocate(ep);
        !           409:          }
        !           410:        }
        !           411:       }
        !           412:     }
        !           413:   }
        !           414:   nw_unlock();
        !           415:   return rc;
        !           416: }
        !           417: 
        !           418: nw_result mk_endpoint_deallocate(nw_ep ep) {
        !           419: 
        !           420:   mk_endpoint_deallocate_internal(ep, current_task(), FALSE);
        !           421: }
        !           422: 
        !           423: 
        !           424: nw_buffer_t mk_buffer_allocate(nw_ep ep, u_int size) {
        !           425:   nw_buffer_t buf;
        !           426:   nw_pv_t pv;
        !           427: 
        !           428:   nw_lock();
        !           429:   if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
        !           430:     buf = NW_BUFFER_ERROR;
        !           431:   } else {
        !           432:     while (pv != NULL && pv->owner != current_task())
        !           433:       pv = pv->next;
        !           434:     if (pv == NULL) {
        !           435:       buf = NW_BUFFER_ERROR;
        !           436:     } else {
        !           437:       buf = nc_buffer_allocate(ep, size);
        !           438:       if (buf != NULL) {
        !           439:        buf = (nw_buffer_t) ((char *) buf - ect[ep].buf_start + pv->buf_start);
        !           440:       }
        !           441:     }
        !           442:   }
        !           443:   nw_unlock();
        !           444:   return buf;
        !           445: }
        !           446: 
        !           447: 
        !           448: 
        !           449: nw_result mk_buffer_deallocate(nw_ep ep, nw_buffer_t buffer) {
        !           450:   nw_result rc;
        !           451:   nw_pv_t pv;
        !           452: 
        !           453:   nw_lock();
        !           454:   if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
        !           455:     rc = NW_BAD_EP;
        !           456:   } else {
        !           457:     while (pv != NULL && pv->owner != current_task())
        !           458:       pv = pv->next;
        !           459:     if (pv == NULL) {
        !           460:       rc = NW_PROT_VIOLATION;
        !           461:     } else {
        !           462:       if ((char *) buffer < pv->buf_start ||
        !           463:          (char *) buffer + sizeof(nw_buffer_s) > pv->buf_end ||
        !           464:          !buffer->buf_used ||
        !           465:          (char *) buffer + buffer->buf_length > pv->buf_end) {
        !           466:        rc = NW_BAD_BUFFER;
        !           467:       } else {
        !           468:        buffer = (nw_buffer_t) ((char *) buffer - pv->buf_start +
        !           469:                                ect[ep].buf_start);
        !           470:        rc = nc_buffer_deallocate(ep, buffer);
        !           471:       }
        !           472:     }
        !           473:   }
        !           474:   nw_unlock();
        !           475:   return rc;
        !           476: }
        !           477: 
        !           478: 
        !           479: nw_result mk_connection_open_internal(nw_ep local_ep, nw_address_1 rem_addr_1,
        !           480:                                      nw_address_2 rem_addr_2, nw_ep remote_ep) {
        !           481:   nw_result rc;
        !           482:   
        !           483:   rc = (*devct[NW_DEVICE(rem_addr_1)].entry->open) (local_ep,
        !           484:                                                    rem_addr_1, rem_addr_2,
        !           485:                                                    remote_ep);
        !           486:   if (rc == NW_SYNCH) {
        !           487:     hect[local_ep].sig_waiter = current_thread();
        !           488:     assert_wait(0, TRUE);
        !           489:     simple_unlock(&nw_simple_lock);
        !           490:     thread_block((void (*)()) 0);
        !           491:   }
        !           492:   return rc;
        !           493: }
        !           494:   
        !           495: nw_result mk_connection_open(nw_ep local_ep, nw_address_1 rem_addr_1,
        !           496:                             nw_address_2 rem_addr_2, nw_ep remote_ep) {
        !           497:   nw_result rc;
        !           498:   nw_pv_t pv;
        !           499: 
        !           500:   nw_lock();
        !           501:   if (local_ep >= MAX_EP || (pv = hect[local_ep].pv) == NULL) {
        !           502:     rc = NW_BAD_EP;
        !           503:   } else {
        !           504:     while (pv != NULL && pv->owner != current_task())
        !           505:       pv = pv->next;
        !           506:     if (pv == NULL) {
        !           507:       rc = NW_PROT_VIOLATION;
        !           508:     } else {
        !           509:       rc = (*(devct[NW_DEVICE(rem_addr_1)].entry->open))
        !           510:              (local_ep, rem_addr_1, rem_addr_2, remote_ep);
        !           511:       if (rc == NW_SYNCH) {
        !           512:        hect[local_ep].sig_waiter = current_thread();
        !           513:        assert_wait(0, TRUE);
        !           514:        current_thread()->nw_ep_waited = NULL;
        !           515:        simple_unlock(&nw_simple_lock);
        !           516:        thread_block(mk_return);
        !           517:       }
        !           518:     }
        !           519:   }
        !           520:   nw_unlock();
        !           521:   return rc;
        !           522: }
        !           523: 
        !           524: 
        !           525: nw_result mk_connection_accept(nw_ep ep, nw_buffer_t msg,
        !           526:                               nw_ep_t new_epp) {
        !           527:   nw_result rc;
        !           528:   nw_pv_t pv;
        !           529: 
        !           530:   nw_lock();
        !           531:   if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
        !           532:     rc = NW_BAD_EP;
        !           533:   } else {
        !           534:     while (pv != NULL && pv->owner != current_task())
        !           535:       pv = pv->next;
        !           536:     if (pv == NULL) {
        !           537:       rc = NW_PROT_VIOLATION;
        !           538:     } else if ((char *) msg < pv->buf_start ||
        !           539:               (char *) msg + sizeof(nw_buffer_s) > pv->buf_end ||
        !           540:               !msg->buf_used ||
        !           541:               (char *) msg + msg->buf_length > pv->buf_end) {
        !           542:       rc = NW_BAD_BUFFER;
        !           543:     } else if (new_epp != NULL &&
        !           544:               (invalid_user_access(current_task()->map, (vm_offset_t) new_epp,
        !           545:                                   (vm_offset_t) new_epp + sizeof(nw_ep) - 1,
        !           546:                                   VM_PROT_READ | VM_PROT_WRITE) ||
        !           547:                (*new_epp != 0 && *new_epp != ep))) {
        !           548:       rc = NW_INVALID_ARGUMENT;
        !           549:     } else {
        !           550:       rc = (*(devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry->accept))
        !           551:              (ep, msg, new_epp);
        !           552:       if (rc == NW_SYNCH) {
        !           553:        hect[ep].sig_waiter = current_thread();
        !           554:        assert_wait(0, TRUE);
        !           555:        current_thread()->nw_ep_waited = NULL;
        !           556:        simple_unlock(&nw_simple_lock);
        !           557:        thread_block(mk_return);
        !           558:       }
        !           559:     }
        !           560:   }
        !           561:   nw_unlock();
        !           562:   return rc;
        !           563: }
        !           564: 
        !           565: nw_result mk_connection_close(nw_ep ep) {
        !           566:   nw_result rc;
        !           567:   nw_pv_t pv;
        !           568: 
        !           569:   nw_lock();
        !           570:   if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
        !           571:     rc = NW_BAD_EP;
        !           572:   } else {
        !           573:     while (pv != NULL && pv->owner != current_task())
        !           574:       pv = pv->next;
        !           575:     if (pv == NULL) {
        !           576:       rc = NW_PROT_VIOLATION;
        !           577:     } else {
        !           578:       rc = (*devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry->close)
        !           579:              (ep);
        !           580:       if (rc == NW_SYNCH) {
        !           581:        hect[ep].sig_waiter = current_thread();
        !           582:        assert_wait(0, TRUE);
        !           583:        current_thread()->nw_ep_waited = NULL;
        !           584:        simple_unlock(&nw_simple_lock);
        !           585:        thread_block(mk_return);
        !           586:       }
        !           587:     }
        !           588:   }
        !           589:   nw_unlock();
        !           590:   return rc;
        !           591: }
        !           592: 
        !           593: 
        !           594: nw_result mk_multicast_add(nw_ep local_ep, nw_address_1 rem_addr_1,
        !           595:                           nw_address_2 rem_addr_2, nw_ep remote_ep) {
        !           596:   nw_result rc;
        !           597:   nw_pv_t pv;
        !           598: 
        !           599:   nw_lock();
        !           600:   if (local_ep >= MAX_EP || (pv = hect[local_ep].pv) == NULL) {
        !           601:     rc = NW_BAD_EP;
        !           602:   } else {
        !           603:     while (pv != NULL && pv->owner != current_task())
        !           604:       pv = pv->next;
        !           605:     if (pv == NULL) {
        !           606:       rc = NW_PROT_VIOLATION;
        !           607:     } else {
        !           608:       rc = (*(devct[NW_DEVICE(rem_addr_1)].entry->add))
        !           609:              (local_ep, rem_addr_1, rem_addr_2, remote_ep);
        !           610:       if (rc == NW_SYNCH) {
        !           611:        hect[local_ep].sig_waiter = current_thread();
        !           612:        assert_wait(0, TRUE);
        !           613:        current_thread()->nw_ep_waited = NULL;
        !           614:        simple_unlock(&nw_simple_lock);
        !           615:        thread_block(mk_return);
        !           616:       }
        !           617:     }
        !           618:   }
        !           619:   nw_unlock();
        !           620:   return rc;
        !           621: }
        !           622: 
        !           623: 
        !           624: nw_result mk_multicast_drop(nw_ep local_ep, nw_address_1 rem_addr_1,
        !           625:                            nw_address_2 rem_addr_2, nw_ep remote_ep) {
        !           626:   nw_result rc;
        !           627:   nw_pv_t pv;
        !           628: 
        !           629:   nw_lock();
        !           630:   if (local_ep >= MAX_EP || (pv = hect[local_ep].pv) == NULL) {
        !           631:     rc = NW_BAD_EP;
        !           632:   } else {
        !           633:     while (pv != NULL && pv->owner != current_task())
        !           634:       pv = pv->next;
        !           635:     if (pv == NULL) {
        !           636:       rc = NW_PROT_VIOLATION;
        !           637:     } else {
        !           638:       rc = (*(devct[NW_DEVICE(rem_addr_1)].entry->drop))
        !           639:              (local_ep, rem_addr_1, rem_addr_2, remote_ep);
        !           640:       if (rc == NW_SYNCH) {
        !           641:        hect[local_ep].sig_waiter = current_thread();
        !           642:        assert_wait(0, TRUE);
        !           643:        current_thread()->nw_ep_waited = NULL;
        !           644:        simple_unlock(&nw_simple_lock);
        !           645:        thread_block(mk_return);
        !           646:       }
        !           647:     }
        !           648:   }
        !           649:   nw_unlock();
        !           650:   return rc;
        !           651: }
        !           652: 
        !           653: 
        !           654: nw_result mk_endpoint_status(nw_ep ep, nw_state_t state,
        !           655:                             nw_peer_t peer) {
        !           656:   nw_result rc;
        !           657:   nw_pv_t pv;
        !           658: 
        !           659:   nw_lock();
        !           660:   if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
        !           661:     rc = NW_BAD_EP;
        !           662:   } else {
        !           663:     while (pv != NULL && pv->owner != current_task())
        !           664:       pv = pv->next;
        !           665:     if (pv == NULL) {
        !           666:       rc = NW_PROT_VIOLATION;
        !           667:     } else {
        !           668:       if (invalid_user_access(current_task()->map, (vm_offset_t) state,
        !           669:                              (vm_offset_t) state + sizeof(nw_state) - 1,
        !           670:                              VM_PROT_WRITE) ||
        !           671:          invalid_user_access(current_task()->map, (vm_offset_t) peer,
        !           672:                              (vm_offset_t) peer + sizeof(nw_peer_s) - 1,
        !           673:                              VM_PROT_WRITE)) {
        !           674:        rc = NW_INVALID_ARGUMENT;
        !           675:       } else {
        !           676:        rc = nc_endpoint_status(ep, state, peer);
        !           677:       }
        !           678:     }
        !           679:   }
        !           680:   nw_unlock();
        !           681:   return rc;
        !           682: }
        !           683: 
        !           684: 
        !           685: nw_result mk_send(nw_ep ep, nw_buffer_t msg, nw_options options) {
        !           686:   nw_result rc;
        !           687:   nw_pv_t pv;
        !           688:   nw_ep sender;
        !           689:   int dev;
        !           690:   nw_ecb_t ecb;
        !           691:   nw_tx_header_t header, first_header, previous_header;
        !           692:   nw_hecb_t hecb;
        !           693:   nw_waiter_t w;
        !           694: 
        !           695:   nw_lock();
        !           696:   if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
        !           697:     rc = NW_BAD_EP;
        !           698:   } else {
        !           699:     while (pv != NULL && pv->owner != current_task())
        !           700:       pv = pv->next;
        !           701:     if (pv == NULL) {
        !           702:       rc = NW_PROT_VIOLATION;
        !           703:     } else {
        !           704:       ecb = &ect[ep];
        !           705:       if (ecb->state == NW_INEXISTENT ||
        !           706:          (ecb->protocol == NW_SEQ_PACKET && ecb->conn == NULL)) {
        !           707:        rc = NW_BAD_EP;
        !           708:       } else {
        !           709:        first_header = header = nc_tx_header_allocate();
        !           710:        previous_header = NULL;
        !           711:        rc = NW_SUCCESS;
        !           712:        while (header != NULL) {
        !           713:          if ((char *) msg < pv->buf_start ||
        !           714:              (char *) msg + sizeof(nw_buffer_s) > pv->buf_end ||
        !           715:              ((int) msg & 0x3) || (msg->block_offset & 0x3) ||
        !           716:              (msg->block_length & 0x3) || !msg->buf_used ||
        !           717:              (char *) msg + msg->buf_length > pv->buf_end ||
        !           718:              msg->block_offset + msg->block_length > msg->buf_length) {
        !           719:            rc = NW_BAD_BUFFER;
        !           720:            break;
        !           721:          } else {
        !           722:            if (previous_header == NULL) {
        !           723:              if (ecb->protocol == NW_SEQ_PACKET)
        !           724:                header->peer = ecb->conn->peer;
        !           725:              else
        !           726:                header->peer = msg->peer;
        !           727:            } else {
        !           728:              previous_header->next = header;
        !           729:            }
        !           730:            header->buffer = (nw_buffer_t) ((char *) msg - pv->buf_start +
        !           731:                                            ecb->buf_start);
        !           732:            header->block = (char *) header->buffer + msg->block_offset;
        !           733:            if (!msg->block_deallocate)
        !           734:              header->buffer = NULL;
        !           735:            header->msg_length = 0;
        !           736:            header->block_length = msg->block_length;
        !           737:            first_header->msg_length += header->block_length;
        !           738:            header->next = NULL;
        !           739:            if (msg->buf_next == NULL)
        !           740:              break;
        !           741:            msg = msg->buf_next;
        !           742:            previous_header = header;
        !           743:            header = nc_tx_header_allocate();
        !           744:          }
        !           745:        }
        !           746:        if (header == NULL) {
        !           747:          nc_tx_header_deallocate(first_header);
        !           748:          rc = NW_NO_RESOURCES;
        !           749:        } else if (rc == NW_SUCCESS) {
        !           750:          dev = NW_DEVICE(first_header->peer.rem_addr_1);
        !           751:          if (ecb->protocol != NW_DATAGRAM ||
        !           752:              devct[dev].type != NW_CONNECTION_ORIENTED) {
        !           753:            sender = first_header->peer.local_ep;
        !           754:            rc = NW_SUCCESS;
        !           755:          } else {
        !           756:            sender = nc_line_lookup(&first_header->peer);
        !           757:            if (sender == -1) {
        !           758:              rc = NW_BAD_ADDRESS;
        !           759:            } else if (sender > 0) {
        !           760:              rc = NW_SUCCESS;
        !           761:            } else {
        !           762:              rc = mk_endpoint_allocate_internal(&sender, NW_LINE,
        !           763:                                                 NW_AUTO_ACCEPT, 0, TRUE);
        !           764:              if (rc == NW_SUCCESS) {
        !           765:                rc = mk_connection_open_internal(sender,
        !           766:                                        first_header->peer.rem_addr_1,
        !           767:                                        first_header->peer.rem_addr_2,
        !           768:                                        MASTER_LINE_EP);
        !           769:                if (rc == NW_SUCCESS) 
        !           770:                  nc_line_update(&first_header->peer, sender);
        !           771:              }
        !           772:            }
        !           773:          }
        !           774:          if (rc == NW_SUCCESS) {
        !           775:            first_header->sender = sender;
        !           776:            first_header->options = options;
        !           777:            rc = (*(devct[dev].entry->send)) (sender, first_header, options);
        !           778:            if ((rc == NW_SYNCH || rc == NW_QUEUED) &&
        !           779:                nw_free_waiter != NULL) {
        !           780:              w = nw_free_waiter;
        !           781:              nw_free_waiter = w->next;
        !           782:              w->waiter = current_thread();
        !           783:              w->next = NULL;
        !           784:              hecb = &hect[sender];
        !           785:              if (hecb->tx_last == NULL) {
        !           786:                hecb->tx_first = hecb->tx_last = w;
        !           787:              } else {
        !           788:                hecb->tx_last = hecb->tx_last->next = w;
        !           789:              }
        !           790:              assert_wait(0, TRUE);
        !           791:              current_thread()->nw_ep_waited = NULL;
        !           792:              simple_unlock(&nw_simple_lock);
        !           793:              thread_block(mk_return);
        !           794:            }
        !           795:          }
        !           796:        }
        !           797:       }
        !           798:     }
        !           799:   }
        !           800:   nw_unlock();
        !           801:   return rc;
        !           802: }
        !           803: 
        !           804: 
        !           805: nw_buffer_t mk_receive(nw_ep ep, int time_out) {
        !           806:   nw_buffer_t rc;
        !           807:   nw_pv_t pv;
        !           808:   nw_ecb_t ecb;
        !           809:   nw_rx_header_t header;
        !           810:   nw_hecb_t hecb;
        !           811:   nw_waiter_t w;
        !           812:   nw_ep_owned_t waited;
        !           813: 
        !           814:   nw_lock();
        !           815:   if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
        !           816:     rc = NW_BUFFER_ERROR;
        !           817:   } else {
        !           818:     while (pv != NULL && pv->owner != current_task())
        !           819:       pv = pv->next;
        !           820:     if (pv == NULL) {
        !           821:       rc = NW_BUFFER_ERROR;
        !           822:     } else {
        !           823:       ecb = &ect[ep];
        !           824:       header = ecb->rx_first;
        !           825:       if (header != NULL) {
        !           826:        rc = (nw_buffer_t) ((char *) header->buffer - ecb->buf_start +
        !           827:                             pv->buf_start);
        !           828:        ecb->rx_first = header->next;
        !           829:        if (ecb->rx_first == NULL)
        !           830:          ecb->rx_last = NULL;
        !           831:        nc_rx_header_deallocate(header);
        !           832:       } else if (time_out != 0 && nw_free_waiter != NULL &&
        !           833:                 (time_out == -1 || nw_free_waited != NULL)) {
        !           834:        w = nw_free_waiter;
        !           835:        nw_free_waiter = w->next;
        !           836:        w->waiter = current_thread();
        !           837:        w->next = NULL;
        !           838:        hecb = &hect[ep];
        !           839:        if (hecb->rx_last == NULL)
        !           840:          hecb->rx_first = hecb->rx_last = w;
        !           841:        else
        !           842:          hecb->rx_last = hecb->rx_last->next = w;
        !           843:        assert_wait(0, TRUE);
        !           844:        if (time_out != -1) {
        !           845:          waited = nw_free_waited;
        !           846:          nw_free_waited = waited->next;
        !           847:          waited->ep = ep;
        !           848:          waited->next = NULL;
        !           849:          current_thread()->nw_ep_waited = waited;
        !           850:          current_thread()->wait_result = NULL;
        !           851:          if (!current_thread()->timer.set) 
        !           852:            thread_set_timeout(time_out);
        !           853:        } else {
        !           854:          current_thread()->nw_ep_waited = NULL;
        !           855:        }
        !           856:        simple_unlock(&nw_simple_lock);
        !           857:        thread_block(mk_return);
        !           858:       } else {
        !           859:        rc = NULL;
        !           860:       }
        !           861:     }
        !           862:   }
        !           863:   nw_unlock();
        !           864:   return rc;
        !           865: }
        !           866: 
        !           867: 
        !           868: nw_buffer_t mk_rpc(nw_ep ep, nw_buffer_t msg, nw_options options,
        !           869:                   int time_out) {
        !           870:   nw_buffer_t rc;
        !           871:   nw_result nrc;
        !           872:   nw_ep sender;
        !           873:   int dev;
        !           874:   nw_pv_t pv;
        !           875:   nw_ecb_t ecb;
        !           876:   nw_tx_header_t header, first_header, previous_header;
        !           877:   nw_hecb_t hecb;
        !           878:   nw_waiter_t w;
        !           879:   nw_ep_owned_t waited;
        !           880: 
        !           881:   nw_lock();
        !           882:   if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
        !           883:     rc = NW_BUFFER_ERROR;
        !           884:   } else {
        !           885:     while (pv != NULL && pv->owner != current_task())
        !           886:       pv = pv->next;
        !           887:     if (pv == NULL) {
        !           888:       rc = NW_BUFFER_ERROR;
        !           889:     } else {
        !           890:       ecb = &ect[ep];
        !           891:       if (ecb->state == NW_INEXISTENT ||
        !           892:          (ecb->protocol == NW_SEQ_PACKET && ecb->conn == NULL)) {
        !           893:        rc = NW_BUFFER_ERROR;
        !           894:       } else {
        !           895:        first_header = header = nc_tx_header_allocate();
        !           896:        previous_header = NULL;
        !           897:        rc = NULL;
        !           898:        while (header != NULL) {
        !           899:          if ((char *) msg < pv->buf_start ||
        !           900:              (char *) msg + sizeof(nw_buffer_s) > pv->buf_end ||
        !           901:              ((int) msg & 0x3) || (msg->block_offset & 0x3) ||
        !           902:              (msg->block_length & 0x3) || !msg->buf_used ||
        !           903:              (char *) msg + msg->buf_length > pv->buf_end ||
        !           904:              msg->block_offset + msg->block_length > msg->buf_length) {
        !           905:            rc = NW_BUFFER_ERROR;
        !           906:            break;
        !           907:          } else {
        !           908:            if (previous_header == NULL) {
        !           909:              if (ecb->protocol == NW_SEQ_PACKET)
        !           910:                header->peer = ecb->conn->peer;
        !           911:              else
        !           912:                header->peer = msg->peer;
        !           913:            } else {
        !           914:              previous_header->next = header;
        !           915:            }
        !           916:            header->buffer = (nw_buffer_t) ((char *) msg - pv->buf_start +
        !           917:                                            ecb->buf_start);
        !           918:            header->block = (char *) header->buffer + msg->block_offset;
        !           919:            if (!msg->block_deallocate)
        !           920:              header->buffer = NULL;
        !           921:            header->msg_length = 0;
        !           922:            header->block_length = msg->block_length;
        !           923:            first_header->msg_length += header->block_length;
        !           924:            header->next = NULL;
        !           925:            if (msg->buf_next == NULL)
        !           926:              break;
        !           927:            msg = msg->buf_next;
        !           928:            previous_header = header;
        !           929:            header = nc_tx_header_allocate();
        !           930:          }
        !           931:        }
        !           932:        if (header == NULL) {
        !           933:          nc_tx_header_deallocate(first_header);
        !           934:          rc = NW_BUFFER_ERROR;
        !           935:        } else if (rc != NW_BUFFER_ERROR) {
        !           936:          dev = NW_DEVICE(first_header->peer.rem_addr_1);
        !           937:          if (ecb->protocol != NW_DATAGRAM ||
        !           938:              devct[dev].type != NW_CONNECTION_ORIENTED) {
        !           939:            sender = first_header->peer.local_ep;
        !           940:            nrc = NW_SUCCESS;
        !           941:          } else {
        !           942:            sender = nc_line_lookup(&first_header->peer);
        !           943:            if (sender == -1) {
        !           944:              nrc = NW_BAD_ADDRESS;
        !           945:            } else if (sender > 0) {
        !           946:              nrc = NW_SUCCESS;
        !           947:            } else {
        !           948:              nrc = mk_endpoint_allocate_internal(&sender, NW_LINE,
        !           949:                                                  NW_AUTO_ACCEPT, 0, TRUE);
        !           950:              if (nrc == NW_SUCCESS) {
        !           951:                nrc = mk_connection_open_internal(sender,
        !           952:                                        first_header->peer.rem_addr_1,
        !           953:                                        first_header->peer.rem_addr_2,
        !           954:                                        MASTER_LINE_EP);
        !           955:                if (nrc == NW_SUCCESS) 
        !           956:                  nc_line_update(&first_header->peer, sender);
        !           957:              }
        !           958:            }
        !           959:          }
        !           960:          if (nrc == NW_SUCCESS) {
        !           961:            first_header->sender = sender;
        !           962:            first_header->options = options;
        !           963:            rc = (*(devct[dev].entry->rpc)) (sender, first_header, options);
        !           964:            if (rc != NULL && rc != NW_BUFFER_ERROR) {
        !           965:              rc = (nw_buffer_t) ((char *) rc - ecb->buf_start +
        !           966:                                  pv->buf_start);
        !           967:            } else if (rc == NULL && time_out != 0 && nw_free_waiter != NULL &&
        !           968:                       (time_out == -1 || nw_free_waited != NULL)) {
        !           969:              w = nw_free_waiter;
        !           970:              nw_free_waiter = w->next;
        !           971:              w->waiter = current_thread();
        !           972:              w->next = NULL;
        !           973:              hecb = &hect[ep];
        !           974:              if (hecb->rx_last == NULL)
        !           975:                hecb->rx_first = hecb->rx_last = w;
        !           976:              else
        !           977:                hecb->rx_last = hecb->rx_last->next = w;
        !           978:              assert_wait(0, TRUE);
        !           979:              if (time_out != -1) {
        !           980:                waited = nw_free_waited;
        !           981:                nw_free_waited = waited->next;
        !           982:                waited->ep = ep;
        !           983:                waited->next = NULL;
        !           984:                current_thread()->nw_ep_waited = waited;
        !           985:                current_thread()->wait_result = NULL;
        !           986:                if (!current_thread()->timer.set) 
        !           987:                  thread_set_timeout(time_out);
        !           988:              } else {
        !           989:                current_thread()->nw_ep_waited = NULL;
        !           990:              }
        !           991:              simple_unlock(&nw_simple_lock);
        !           992:              thread_block(mk_return);
        !           993:            }
        !           994:          }
        !           995:        }
        !           996:       }
        !           997:     }
        !           998:   }
        !           999:   nw_unlock();
        !          1000:   return rc;
        !          1001: }
        !          1002: 
        !          1003: nw_buffer_t mk_select(u_int nep, nw_ep_t epp, int time_out) {
        !          1004:   nw_buffer_t rc;
        !          1005:   nw_pv_t pv;
        !          1006:   int i;
        !          1007:   nw_ep ep;
        !          1008:   nw_ecb_t ecb;
        !          1009:   nw_rx_header_t header;
        !          1010:   nw_hecb_t hecb;
        !          1011:   nw_waiter_t w, w_next;
        !          1012:   nw_ep_owned_t waited;
        !          1013: 
        !          1014:   if (invalid_user_access(current_task()->map, (vm_offset_t) epp,
        !          1015:                          (vm_offset_t) epp + nep*sizeof(nw_ep) - 1,
        !          1016:                          VM_PROT_READ)) {
        !          1017:     rc = NW_BUFFER_ERROR;
        !          1018:   } else {
        !          1019:     nw_lock();
        !          1020:     for (i = 0; i < nep; i++) {
        !          1021:       ep = epp[i];
        !          1022:       if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
        !          1023:        rc = NW_BUFFER_ERROR;
        !          1024:        break;
        !          1025:       } else {
        !          1026:        while (pv != NULL && pv->owner != current_task())
        !          1027:          pv = pv->next;
        !          1028:        if (pv == NULL) {
        !          1029:          rc = NW_BUFFER_ERROR;
        !          1030:          break;
        !          1031:        } else {
        !          1032:          ecb = &ect[ep];
        !          1033:          header = ecb->rx_first;
        !          1034:          if (header != NULL) {
        !          1035:            rc = (nw_buffer_t) ((char *) header->buffer - ecb->buf_start +
        !          1036:                                 pv->buf_start);
        !          1037:            ecb->rx_first = header->next;
        !          1038:            if (ecb->rx_first == NULL)
        !          1039:              ecb->rx_last = NULL;
        !          1040:            nc_rx_header_deallocate(header);
        !          1041:            break;
        !          1042:          }
        !          1043:        }
        !          1044:       }
        !          1045:     }
        !          1046:     if (i == nep) {
        !          1047:       if (time_out == 0) {
        !          1048:        rc = NULL;
        !          1049:       } else {
        !          1050:        w = nw_free_waiter;
        !          1051:        waited = nw_free_waited;
        !          1052:        i = 0;
        !          1053:        while (i < nep &&
        !          1054:               nw_free_waiter != NULL && nw_free_waited != NULL) {
        !          1055:          nw_free_waiter = nw_free_waiter->next;
        !          1056:          nw_free_waited = nw_free_waited->next;
        !          1057:          i++;
        !          1058:        }
        !          1059:        if (i < nep) {
        !          1060:          nw_free_waiter = w;
        !          1061:          nw_free_waited = waited;
        !          1062:          rc = NW_BUFFER_ERROR;
        !          1063:        } else {
        !          1064:          current_thread()->nw_ep_waited = waited;
        !          1065:          for (i = 0; i < nep; i++) {
        !          1066:            ep = epp[i];
        !          1067:            waited->ep = ep;
        !          1068:            if (i < nep-1)
        !          1069:              waited = waited->next;
        !          1070:            else
        !          1071:              waited->next = NULL;
        !          1072:            w->waiter = current_thread();
        !          1073:            w_next = w->next;
        !          1074:            w->next = NULL;
        !          1075:            hecb = &hect[ep];
        !          1076:            if (hecb->rx_last == NULL)
        !          1077:              hecb->rx_first = hecb->rx_last = w;
        !          1078:            else
        !          1079:              hecb->rx_last = hecb->rx_last->next = w;
        !          1080:            w = w_next;
        !          1081:          }
        !          1082:          assert_wait(0, TRUE);
        !          1083:          if (time_out != -1) {
        !          1084:            current_thread()->wait_result = NULL;
        !          1085:            if (!current_thread()->timer.set) 
        !          1086:              thread_set_timeout(time_out);
        !          1087:          }
        !          1088:          simple_unlock(&nw_simple_lock);
        !          1089:          thread_block(mk_return);
        !          1090:        }
        !          1091:       }
        !          1092:     }
        !          1093:     nw_unlock();
        !          1094:   }
        !          1095:   return rc;
        !          1096: }
        !          1097: 
        !          1098: 
        !          1099: /*** System-dependent support ***/
        !          1100: 
        !          1101: void mk_endpoint_collect(task_t task) {
        !          1102:   
        !          1103:   while (task->nw_ep_owned != NULL) {
        !          1104:     mk_endpoint_deallocate_internal(task->nw_ep_owned->ep, task, TRUE);
        !          1105:   }
        !          1106: }
        !          1107: 
        !          1108: void mk_waited_collect(thread_t thread) {
        !          1109:   nw_hecb_t hecb;
        !          1110:   nw_waiter_t w, w_previous;
        !          1111:   nw_ep_owned_t waited, waited_previous;
        !          1112: 
        !          1113:   waited = thread->nw_ep_waited;
        !          1114:   if (waited != NULL) {
        !          1115:     while (waited != NULL) {
        !          1116:       hecb = &hect[waited->ep];
        !          1117:       w = hecb->rx_first;
        !          1118:       w_previous = NULL;
        !          1119:       while (w != NULL && w->waiter != thread) {
        !          1120:        w_previous = w;
        !          1121:        w = w->next;
        !          1122:       }
        !          1123:       if (w != NULL) {
        !          1124:        if (w_previous == NULL)
        !          1125:          hecb->rx_first = w->next;
        !          1126:        else
        !          1127:          w_previous->next = w->next;
        !          1128:        if (w->next == NULL)
        !          1129:          hecb->rx_last = w_previous;
        !          1130:        w->next = nw_free_waiter;
        !          1131:        nw_free_waiter = w;
        !          1132:       }
        !          1133:       waited_previous = waited;
        !          1134:       waited = waited->next;
        !          1135:     }
        !          1136:     waited_previous->next = nw_free_waited;
        !          1137:     nw_free_waited = thread->nw_ep_waited;
        !          1138:     thread->nw_ep_waited = NULL;
        !          1139:   }
        !          1140: }
        !          1141: 
        !          1142: void mk_return() {
        !          1143: 
        !          1144:   thread_syscall_return(current_thread()->wait_result);
        !          1145: }
        !          1146:   
        !          1147: 
        !          1148: boolean_t mk_deliver_result(thread_t thread, int result) {
        !          1149:   boolean_t rc;
        !          1150:   int state, s;
        !          1151:   
        !          1152:   s = splsched();
        !          1153:   thread_lock(thread);
        !          1154:   state = thread->state;
        !          1155: 
        !          1156:   reset_timeout_check(&thread->timer);
        !          1157: 
        !          1158:   switch (state & TH_SCHED_STATE) {
        !          1159:   case          TH_WAIT | TH_SUSP | TH_UNINT:
        !          1160:   case          TH_WAIT           | TH_UNINT:
        !          1161:   case          TH_WAIT:
        !          1162:     /*
        !          1163:      *      Sleeping and not suspendable - put on run queue.
        !          1164:      */
        !          1165:     thread->state = (state &~ TH_WAIT) | TH_RUN;
        !          1166:     thread->wait_result = (kern_return_t) result;
        !          1167:     simpler_thread_setrun(thread, TRUE);
        !          1168:     rc = TRUE;
        !          1169:     break;
        !          1170:     
        !          1171:   case          TH_WAIT | TH_SUSP:
        !          1172:   case TH_RUN | TH_WAIT:
        !          1173:   case TH_RUN | TH_WAIT | TH_SUSP:
        !          1174:   case TH_RUN | TH_WAIT           | TH_UNINT:
        !          1175:   case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
        !          1176:     /*
        !          1177:      *      Either already running, or suspended.
        !          1178:      */
        !          1179:     thread->state = state &~ TH_WAIT;
        !          1180:     thread->wait_result = (kern_return_t) result;
        !          1181:     rc = FALSE;
        !          1182:     break;
        !          1183: 
        !          1184:   default:
        !          1185:     /*
        !          1186:      *      Not waiting.
        !          1187:      */
        !          1188:     rc = FALSE;
        !          1189:     break;
        !          1190:   }
        !          1191:   thread_unlock(thread);
        !          1192:   splx(s);
        !          1193:   return rc;
        !          1194: }
        !          1195: 
        !          1196: 
        !          1197: boolean_t nc_deliver_result(nw_ep ep, nw_delivery type, int result) {
        !          1198:   boolean_t rc;
        !          1199:   nw_hecb_t hecb;
        !          1200:   nw_ecb_t ecb;
        !          1201:   nw_waiter_t w;
        !          1202:   thread_t thread;
        !          1203:   task_t task;
        !          1204:   nw_pv_t pv;
        !          1205:   nw_buffer_t buf;
        !          1206:   nw_rx_header_t rx_header;
        !          1207:   nw_tx_header_t tx_header;
        !          1208:   nw_ep lep;
        !          1209: 
        !          1210:   hecb = &hect[ep];
        !          1211:   ecb = &ect[ep];
        !          1212: 
        !          1213:   thread = NULL;
        !          1214:   if (type == NW_RECEIVE || type == NW_RECEIVE_URGENT) {
        !          1215:     w = hecb->rx_first;
        !          1216:     if (w != NULL) {
        !          1217:       thread = w->waiter;
        !          1218:       hecb->rx_first = w->next;
        !          1219:       if (hecb->rx_first == NULL)
        !          1220:        hecb->rx_last = NULL;
        !          1221:       w->next = nw_free_waiter;
        !          1222:       nw_free_waiter = w;
        !          1223:       task = thread->task;
        !          1224:       pv = hecb->pv;
        !          1225:       while (pv != NULL && pv->owner != task)
        !          1226:        pv = pv->next;
        !          1227:       if (pv == NULL) {
        !          1228:        rc = FALSE;
        !          1229:       } else {
        !          1230:        buf = (nw_buffer_t) ((char *) result - ecb->buf_start + pv->buf_start);
        !          1231:        rc = mk_deliver_result(thread, (int) buf);
        !          1232:       }
        !          1233:     } else {
        !          1234:       rx_header = nc_rx_header_allocate();
        !          1235:       if (rx_header == NULL) {
        !          1236:        rc = FALSE;
        !          1237:       } else {
        !          1238:        rx_header->buffer = (nw_buffer_t) result;
        !          1239:        if (type == NW_RECEIVE) {
        !          1240:          rx_header->next = NULL;
        !          1241:          if (ecb->rx_last == NULL)
        !          1242:            ecb->rx_first = rx_header;
        !          1243:          else
        !          1244:            ecb->rx_last->next = rx_header;
        !          1245:          ecb->rx_last = rx_header;
        !          1246:        } else {
        !          1247:          rx_header->next = ecb->rx_first;
        !          1248:          if (ecb->rx_first == NULL)
        !          1249:            ecb->rx_last = rx_header;
        !          1250:          ecb->rx_first = rx_header;
        !          1251:        }
        !          1252:        rc = TRUE;
        !          1253:       } 
        !          1254:     }
        !          1255:   } else if (type == NW_SEND) {
        !          1256:     w = hecb->tx_first;
        !          1257:     if (w == NULL) {
        !          1258:       rc = FALSE;
        !          1259:     } else {
        !          1260:       thread = w->waiter;
        !          1261:       hecb->tx_first = w->next;
        !          1262:       if (hecb->tx_first == NULL)
        !          1263:        hecb->tx_last = NULL;
        !          1264:       w->next = nw_free_waiter;
        !          1265:       nw_free_waiter = w;
        !          1266:       rc = mk_deliver_result(thread, result);
        !          1267:     }
        !          1268:     tx_header = ect[ep].tx_initial;
        !          1269:     if (result == NW_SUCCESS) {
        !          1270:       lep = tx_header->peer.local_ep;
        !          1271:       while (tx_header != NULL) {
        !          1272:        if (tx_header->buffer != NULL)
        !          1273:          nc_buffer_deallocate(lep, tx_header->buffer);
        !          1274:        tx_header = tx_header->next;
        !          1275:       }
        !          1276:     }
        !          1277:     nc_tx_header_deallocate(ect[ep].tx_initial);
        !          1278:     ect[ep].tx_initial = ect[ep].tx_current = NULL;
        !          1279:   } else if (type == NW_SIGNAL) {
        !          1280:     thread = hecb->sig_waiter;
        !          1281:     hecb->sig_waiter = NULL;
        !          1282:     if (thread == NULL) {
        !          1283:       rc = FALSE;
        !          1284:     } else {
        !          1285:       rc = mk_deliver_result(thread, result);
        !          1286:     }
        !          1287:   }
        !          1288:   return rc;
        !          1289: }
        !          1290:     
        !          1291: int mk_fast_sweep() {
        !          1292: 
        !          1293:   nw_lock();
        !          1294:   nc_fast_sweep();
        !          1295:   nw_unlock();
        !          1296:   return 0;
        !          1297: }
        !          1298: 
        !          1299: void h_fast_timer_set() {
        !          1300:   
        !          1301: #ifdef PRODUCTION
        !          1302:   if (!nw_fast_timer.set)
        !          1303:     set_timeout(&nw_fast_timer, 1);
        !          1304: #endif
        !          1305: }
        !          1306: 
        !          1307: void h_fast_timer_reset() {
        !          1308: 
        !          1309:   if (nw_fast_timer.set)
        !          1310:     reset_timeout(&nw_fast_timer);
        !          1311: }
        !          1312: 
        !          1313: int mk_slow_sweep() {
        !          1314: 
        !          1315: #ifdef PRODUCTION
        !          1316:   nw_lock();
        !          1317:   nc_slow_sweep();
        !          1318:   nw_unlock();
        !          1319:   set_timeout(&nw_slow_timer, 2*hz);
        !          1320:   return 0;
        !          1321: #endif
        !          1322: }
        !          1323: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.