|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.