Annotation of Gnu-Mach/chips/nw_mk.c, revision 1.1.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.