|
|
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.