|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University.
4: * Copyright (c) 1993,1994 The University of Utah and
5: * the Computer Systems Laboratory (CSL).
6: * All rights reserved.
7: *
8: * Permission to use, copy, modify and distribute this software and its
9: * documentation is hereby granted, provided that both the copyright
10: * notice and this permission notice appear in all copies of the
11: * software, derivative works or modified versions, and any portions
12: * thereof, and that both notices appear in supporting documentation.
13: *
14: * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
15: * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
16: * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
17: * THIS SOFTWARE.
18: *
19: * Carnegie Mellon requests users of this software to return to
20: *
21: * Software Distribution Coordinator or [email protected]
22: * School of Computer Science
23: * Carnegie Mellon University
24: * Pittsburgh PA 15213-3890
25: *
26: * any improvements or extensions that they make and grant Carnegie Mellon
27: * the rights to redistribute these changes.
28: */
29: /*
30: * File: ipc/ipc_entry.c
31: * Author: Rich Draves
32: * Date: 1989
33: *
34: * Primitive functions to manipulate translation entries.
35: */
36:
37: #include <mach/kern_return.h>
38: #include <mach/port.h>
39: #include <kern/assert.h>
40: #include <kern/sched_prim.h>
41: #include <kern/zalloc.h>
42: #include <ipc/port.h>
43: #include <ipc/ipc_types.h>
44: #include <ipc/ipc_entry.h>
45: #include <ipc/ipc_space.h>
46: #include <ipc/ipc_splay.h>
47: #include <ipc/ipc_hash.h>
48: #include <ipc/ipc_table.h>
49: #include <ipc/ipc_object.h>
50:
51: zone_t ipc_tree_entry_zone;
52:
53: /*
54: * Routine: ipc_entry_tree_collision
55: * Purpose:
56: * Checks if "name" collides with an allocated name
57: * in the space's tree. That is, returns TRUE
58: * if the splay tree contains a name with the same
59: * index as "name".
60: * Conditions:
61: * The space is locked (read or write) and active.
62: */
63:
64: boolean_t
65: ipc_entry_tree_collision(
66: ipc_space_t space,
67: mach_port_t name)
68: {
69: mach_port_index_t index;
70: mach_port_t lower, upper;
71:
72: assert(space->is_active);
73:
74: /*
75: * Check if we collide with the next smaller name
76: * or the next larger name.
77: */
78:
79: ipc_splay_tree_bounds(&space->is_tree, name, &lower, &upper);
80:
81: index = MACH_PORT_INDEX(name);
82: return (((lower != ~0) && (MACH_PORT_INDEX(lower) == index)) ||
83: ((upper != 0) && (MACH_PORT_INDEX(upper) == index)));
84: }
85:
86: /*
87: * Routine: ipc_entry_lookup
88: * Purpose:
89: * Searches for an entry, given its name.
90: * Conditions:
91: * The space must be read or write locked throughout.
92: * The space must be active.
93: */
94:
95: ipc_entry_t
96: ipc_entry_lookup(space, name)
97: ipc_space_t space;
98: mach_port_t name;
99: {
100: mach_port_index_t index;
101: ipc_entry_t entry;
102:
103: assert(space->is_active);
104:
105: index = MACH_PORT_INDEX(name);
106: if (index < space->is_table_size) {
107: entry = &space->is_table[index];
108: if (IE_BITS_GEN(entry->ie_bits) != MACH_PORT_GEN(name))
109: if (entry->ie_bits & IE_BITS_COLLISION) {
110: assert(space->is_tree_total > 0);
111: goto tree_lookup;
112: } else
113: entry = IE_NULL;
114: else if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
115: entry = IE_NULL;
116: } else if (space->is_tree_total == 0)
117: entry = IE_NULL;
118: else
119: tree_lookup:
120: entry = (ipc_entry_t)
121: ipc_splay_tree_lookup(&space->is_tree, name);
122:
123: assert((entry == IE_NULL) || IE_BITS_TYPE(entry->ie_bits));
124: return entry;
125: }
126:
127: /*
128: * Routine: ipc_entry_get
129: * Purpose:
130: * Tries to allocate an entry out of the space.
131: * Conditions:
132: * The space is write-locked and active throughout.
133: * An object may be locked. Will not allocate memory.
134: * Returns:
135: * KERN_SUCCESS A free entry was found.
136: * KERN_NO_SPACE No entry allocated.
137: */
138:
139: kern_return_t
140: ipc_entry_get(space, namep, entryp)
141: ipc_space_t space;
142: mach_port_t *namep;
143: ipc_entry_t *entryp;
144: {
145: ipc_entry_t table;
146: mach_port_index_t first_free;
147: mach_port_t new_name;
148: ipc_entry_t free_entry;
149:
150: assert(space->is_active);
151:
152: table = space->is_table;
153: first_free = table->ie_next;
154:
155: if (first_free == 0)
156: return KERN_NO_SPACE;
157:
158: free_entry = &table[first_free];
159: table->ie_next = free_entry->ie_next;
160:
161: /*
162: * Initialize the new entry. We need only
163: * increment the generation number and clear ie_request.
164: */
165:
166: {
167: mach_port_gen_t gen;
168:
169: assert((free_entry->ie_bits &~ IE_BITS_GEN_MASK) == 0);
170: gen = free_entry->ie_bits + IE_BITS_GEN_ONE;
171: free_entry->ie_bits = gen;
172: free_entry->ie_request = 0;
173: new_name = MACH_PORT_MAKE(first_free, gen);
174: }
175:
176: /*
177: * The new name can't be MACH_PORT_NULL because index
178: * is non-zero. It can't be MACH_PORT_DEAD because
179: * the table isn't allowed to grow big enough.
180: * (See comment in ipc/ipc_table.h.)
181: */
182:
183: assert(MACH_PORT_VALID(new_name));
184: assert(free_entry->ie_object == IO_NULL);
185:
186: *namep = new_name;
187: *entryp = free_entry;
188: return KERN_SUCCESS;
189: }
190:
191: /*
192: * Routine: ipc_entry_alloc
193: * Purpose:
194: * Allocate an entry out of the space.
195: * Conditions:
196: * The space is not locked before, but it is write-locked after
197: * if the call is successful. May allocate memory.
198: * Returns:
199: * KERN_SUCCESS An entry was allocated.
200: * KERN_INVALID_TASK The space is dead.
201: * KERN_NO_SPACE No room for an entry in the space.
202: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory for an entry.
203: */
204:
205: kern_return_t
206: ipc_entry_alloc(
207: ipc_space_t space,
208: mach_port_t *namep,
209: ipc_entry_t *entryp)
210: {
211: kern_return_t kr;
212:
213: is_write_lock(space);
214:
215: for (;;) {
216: if (!space->is_active) {
217: is_write_unlock(space);
218: return KERN_INVALID_TASK;
219: }
220:
221: kr = ipc_entry_get(space, namep, entryp);
222: if (kr == KERN_SUCCESS)
223: return kr;
224:
225: kr = ipc_entry_grow_table(space);
226: if (kr != KERN_SUCCESS)
227: return kr; /* space is unlocked */
228: }
229: }
230:
231: /*
232: * Routine: ipc_entry_alloc_name
233: * Purpose:
234: * Allocates/finds an entry with a specific name.
235: * If an existing entry is returned, its type will be nonzero.
236: * Conditions:
237: * The space is not locked before, but it is write-locked after
238: * if the call is successful. May allocate memory.
239: * Returns:
240: * KERN_SUCCESS Found existing entry with same name.
241: * KERN_SUCCESS Allocated a new entry.
242: * KERN_INVALID_TASK The space is dead.
243: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
244: */
245:
246: kern_return_t
247: ipc_entry_alloc_name(
248: ipc_space_t space,
249: mach_port_t name,
250: ipc_entry_t *entryp)
251: {
252: mach_port_index_t index = MACH_PORT_INDEX(name);
253: mach_port_gen_t gen = MACH_PORT_GEN(name);
254: ipc_tree_entry_t tree_entry = ITE_NULL;
255:
256: assert(MACH_PORT_VALID(name));
257:
258:
259: is_write_lock(space);
260:
261: for (;;) {
262: ipc_entry_t entry;
263: ipc_tree_entry_t tentry;
264: ipc_table_size_t its;
265:
266: if (!space->is_active) {
267: is_write_unlock(space);
268: if (tree_entry) ite_free(tree_entry);
269: return KERN_INVALID_TASK;
270: }
271:
272: /*
273: * If we are under the table cutoff,
274: * there are three cases:
275: * 1) The entry is inuse, for the same name
276: * 2) The entry is inuse, for a different name
277: * 3) The entry is free
278: */
279:
280: if ((0 < index) && (index < space->is_table_size)) {
281: ipc_entry_t table = space->is_table;
282:
283: entry = &table[index];
284:
285: if (IE_BITS_TYPE(entry->ie_bits)) {
286: if (IE_BITS_GEN(entry->ie_bits) == gen) {
287: *entryp = entry;
288: if (tree_entry) ite_free(tree_entry);
289: return KERN_SUCCESS;
290: }
291: } else {
292: mach_port_index_t free_index, next_index;
293:
294: /*
295: * Rip the entry out of the free list.
296: */
297:
298: for (free_index = 0;
299: (next_index = table[free_index].ie_next)
300: != index;
301: free_index = next_index)
302: continue;
303:
304: table[free_index].ie_next =
305: table[next_index].ie_next;
306:
307: entry->ie_bits = gen;
308: assert(entry->ie_object == IO_NULL);
309: entry->ie_request = 0;
310:
311: *entryp = entry;
312: if (tree_entry) ite_free(tree_entry);
313: return KERN_SUCCESS;
314: }
315: }
316:
317: /*
318: * Before trying to allocate any memory,
319: * check if the entry already exists in the tree.
320: * This avoids spurious resource errors.
321: * The splay tree makes a subsequent lookup/insert
322: * of the same name cheap, so this costs little.
323: */
324:
325: if ((space->is_tree_total > 0) &&
326: ((tentry = ipc_splay_tree_lookup(&space->is_tree, name))
327: != ITE_NULL)) {
328: assert(tentry->ite_space == space);
329: assert(IE_BITS_TYPE(tentry->ite_bits));
330:
331: *entryp = &tentry->ite_entry;
332: if (tree_entry) ite_free(tree_entry);
333: return KERN_SUCCESS;
334: }
335:
336: its = space->is_table_next;
337:
338: /*
339: * Check if the table should be grown.
340: *
341: * Note that if space->is_table_size == its->its_size,
342: * then we won't ever try to grow the table.
343: *
344: * Note that we are optimistically assuming that name
345: * doesn't collide with any existing names. (So if
346: * it were entered into the tree, is_tree_small would
347: * be incremented.) This is OK, because even in that
348: * case, we don't lose memory by growing the table.
349: */
350:
351: if ((space->is_table_size <= index) &&
352: (index < its->its_size) &&
353: (((its->its_size - space->is_table_size) *
354: sizeof(struct ipc_entry)) <
355: ((space->is_tree_small + 1) *
356: sizeof(struct ipc_tree_entry)))) {
357: kern_return_t kr;
358:
359: /*
360: * Can save space by growing the table.
361: * Because the space will be unlocked,
362: * we must restart.
363: */
364:
365: kr = ipc_entry_grow_table(space);
366: assert(kr != KERN_NO_SPACE);
367: if (kr != KERN_SUCCESS) {
368: /* space is unlocked */
369: if (tree_entry) ite_free(tree_entry);
370: return kr;
371: }
372:
373: continue;
374: }
375:
376: /*
377: * If a splay-tree entry was allocated previously,
378: * go ahead and insert it into the tree.
379: */
380:
381: if (tree_entry != ITE_NULL) {
382: space->is_tree_total++;
383:
384: if (index < space->is_table_size)
385: space->is_table[index].ie_bits |=
386: IE_BITS_COLLISION;
387: else if ((index < its->its_size) &&
388: !ipc_entry_tree_collision(space, name))
389: space->is_tree_small++;
390:
391: ipc_splay_tree_insert(&space->is_tree,
392: name, tree_entry);
393:
394: tree_entry->ite_bits = 0;
395: tree_entry->ite_object = IO_NULL;
396: tree_entry->ite_request = 0;
397: tree_entry->ite_space = space;
398: *entryp = &tree_entry->ite_entry;
399: return KERN_SUCCESS;
400: }
401:
402: /*
403: * Allocate a tree entry and try again.
404: */
405:
406: is_write_unlock(space);
407: tree_entry = ite_alloc();
408: if (tree_entry == ITE_NULL)
409: return KERN_RESOURCE_SHORTAGE;
410: is_write_lock(space);
411: }
412: }
413:
414: /*
415: * Routine: ipc_entry_dealloc
416: * Purpose:
417: * Deallocates an entry from a space.
418: * Conditions:
419: * The space must be write-locked throughout.
420: * The space must be active.
421: */
422:
423: void
424: ipc_entry_dealloc(
425: ipc_space_t space,
426: mach_port_t name,
427: ipc_entry_t entry)
428: {
429: ipc_entry_t table;
430: ipc_entry_num_t size;
431: mach_port_index_t index;
432:
433: assert(space->is_active);
434: assert(entry->ie_object == IO_NULL);
435: assert(entry->ie_request == 0);
436:
437: index = MACH_PORT_INDEX(name);
438: table = space->is_table;
439: size = space->is_table_size;
440:
441: if ((index < size) && (entry == &table[index])) {
442: assert(IE_BITS_GEN(entry->ie_bits) == MACH_PORT_GEN(name));
443:
444: if (entry->ie_bits & IE_BITS_COLLISION) {
445: struct ipc_splay_tree small, collisions;
446: ipc_tree_entry_t tentry;
447: mach_port_t tname;
448: boolean_t pick;
449: ipc_entry_bits_t bits;
450: ipc_object_t obj;
451:
452: /* must move an entry from tree to table */
453:
454: ipc_splay_tree_split(&space->is_tree,
455: MACH_PORT_MAKE(index+1, 0),
456: &collisions);
457: ipc_splay_tree_split(&collisions,
458: MACH_PORT_MAKE(index, 0),
459: &small);
460:
461: pick = ipc_splay_tree_pick(&collisions,
462: &tname, &tentry);
463: assert(pick);
464: assert(MACH_PORT_INDEX(tname) == index);
465:
466: bits = tentry->ite_bits;
467: entry->ie_bits = bits | MACH_PORT_GEN(tname);
468: entry->ie_object = obj = tentry->ite_object;
469: entry->ie_request = tentry->ite_request;
470: assert(tentry->ite_space == space);
471:
472: if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND) {
473: ipc_hash_global_delete(space, obj,
474: tname, tentry);
475: ipc_hash_local_insert(space, obj,
476: index, entry);
477: }
478:
479: ipc_splay_tree_delete(&collisions, tname, tentry);
480:
481: assert(space->is_tree_total > 0);
482: space->is_tree_total--;
483:
484: /* check if collision bit should still be on */
485:
486: pick = ipc_splay_tree_pick(&collisions,
487: &tname, &tentry);
488: if (pick) {
489: entry->ie_bits |= IE_BITS_COLLISION;
490: ipc_splay_tree_join(&space->is_tree,
491: &collisions);
492: }
493:
494: ipc_splay_tree_join(&space->is_tree, &small);
495: } else {
496: entry->ie_bits &= IE_BITS_GEN_MASK;
497: entry->ie_next = table->ie_next;
498: table->ie_next = index;
499: }
500: } else {
501: ipc_tree_entry_t tentry = (ipc_tree_entry_t) entry;
502:
503: assert(tentry->ite_space == space);
504:
505: ipc_splay_tree_delete(&space->is_tree, name, tentry);
506:
507: assert(space->is_tree_total > 0);
508: space->is_tree_total--;
509:
510: if (index < size) {
511: ipc_entry_t ientry = &table[index];
512:
513: assert(ientry->ie_bits & IE_BITS_COLLISION);
514:
515: if (!ipc_entry_tree_collision(space, name))
516: ientry->ie_bits &= ~IE_BITS_COLLISION;
517: } else if ((index < space->is_table_next->its_size) &&
518: !ipc_entry_tree_collision(space, name)) {
519: assert(space->is_tree_small > 0);
520: space->is_tree_small--;
521: }
522: }
523: }
524:
525: /*
526: * Routine: ipc_entry_grow_table
527: * Purpose:
528: * Grows the table in a space.
529: * Conditions:
530: * The space must be write-locked and active before.
531: * If successful, it is also returned locked.
532: * Allocates memory.
533: * Returns:
534: * KERN_SUCCESS Grew the table.
535: * KERN_SUCCESS Somebody else grew the table.
536: * KERN_SUCCESS The space died.
537: * KERN_NO_SPACE Table has maximum size already.
538: * KERN_RESOURCE_SHORTAGE Couldn't allocate a new table.
539: */
540:
541: kern_return_t
542: ipc_entry_grow_table(space)
543: ipc_space_t space;
544: {
545: ipc_entry_num_t osize, size, nsize;
546:
547: do {
548: ipc_entry_t otable, table;
549: ipc_table_size_t oits, its, nits;
550: mach_port_index_t i, free_index;
551:
552: assert(space->is_active);
553:
554: if (space->is_growing) {
555: /*
556: * Somebody else is growing the table.
557: * We just wait for them to finish.
558: */
559:
560: assert_wait((event_t) space, FALSE);
561: is_write_unlock(space);
562: thread_block((void (*)()) 0);
563: is_write_lock(space);
564: return KERN_SUCCESS;
565: }
566:
567: otable = space->is_table;
568: its = space->is_table_next;
569: size = its->its_size;
570: oits = its - 1;
571: osize = oits->its_size;
572: nits = its + 1;
573: nsize = nits->its_size;
574:
575: if (osize == size) {
576: is_write_unlock(space);
577: return KERN_NO_SPACE;
578: }
579:
580: assert((osize < size) && (size <= nsize));
581:
582: /*
583: * OK, we'll attempt to grow the table.
584: * The realloc requires that the old table
585: * remain in existence.
586: */
587:
588: space->is_growing = TRUE;
589: is_write_unlock(space);
590: if (it_entries_reallocable(oits))
591: table = it_entries_realloc(oits, otable, its);
592: else
593: table = it_entries_alloc(its);
594: is_write_lock(space);
595: space->is_growing = FALSE;
596:
597: /*
598: * We need to do a wakeup on the space,
599: * to rouse waiting threads. We defer
600: * this until the space is unlocked,
601: * because we don't want them to spin.
602: */
603:
604: if (table == IE_NULL) {
605: is_write_unlock(space);
606: thread_wakeup((event_t) space);
607: return KERN_RESOURCE_SHORTAGE;
608: }
609:
610: if (!space->is_active) {
611: /*
612: * The space died while it was unlocked.
613: */
614:
615: is_write_unlock(space);
616: thread_wakeup((event_t) space);
617: it_entries_free(its, table);
618: is_write_lock(space);
619: return KERN_SUCCESS;
620: }
621:
622: assert(space->is_table == otable);
623: assert(space->is_table_next == its);
624: assert(space->is_table_size == osize);
625:
626: space->is_table = table;
627: space->is_table_size = size;
628: space->is_table_next = nits;
629:
630: /*
631: * If we did a realloc, it remapped the data.
632: * Otherwise we copy by hand first. Then we have
633: * to clear the index fields in the old part and
634: * zero the new part.
635: */
636:
637: if (!it_entries_reallocable(oits))
638: (void) memcpy((void *) table, (const void *) otable,
639: osize * sizeof(struct ipc_entry));
640:
641: for (i = 0; i < osize; i++)
642: table[i].ie_index = 0;
643:
644: (void) memset((void *) (table + osize), 0,
645: (size - osize) * sizeof(struct ipc_entry));
646:
647: /*
648: * Put old entries into the reverse hash table.
649: */
650:
651: for (i = 0; i < osize; i++) {
652: ipc_entry_t entry = &table[i];
653:
654: if (IE_BITS_TYPE(entry->ie_bits) ==
655: MACH_PORT_TYPE_SEND)
656: ipc_hash_local_insert(space, entry->ie_object,
657: i, entry);
658: }
659:
660: /*
661: * If there are entries in the splay tree,
662: * then we have work to do:
663: * 1) transfer entries to the table
664: * 2) update is_tree_small
665: */
666:
667: if (space->is_tree_total > 0) {
668: mach_port_index_t index;
669: boolean_t delete;
670: struct ipc_splay_tree ignore;
671: struct ipc_splay_tree move;
672: struct ipc_splay_tree small;
673: ipc_entry_num_t nosmall;
674: ipc_tree_entry_t tentry;
675:
676: /*
677: * The splay tree divides into four regions,
678: * based on the index of the entries:
679: * 1) 0 <= index < osize
680: * 2) osize <= index < size
681: * 3) size <= index < nsize
682: * 4) nsize <= index
683: *
684: * Entries in the first part are ignored.
685: * Entries in the second part, that don't
686: * collide, are moved into the table.
687: * Entries in the third part, that don't
688: * collide, are counted for is_tree_small.
689: * Entries in the fourth part are ignored.
690: */
691:
692: ipc_splay_tree_split(&space->is_tree,
693: MACH_PORT_MAKE(nsize, 0),
694: &small);
695: ipc_splay_tree_split(&small,
696: MACH_PORT_MAKE(size, 0),
697: &move);
698: ipc_splay_tree_split(&move,
699: MACH_PORT_MAKE(osize, 0),
700: &ignore);
701:
702: /* move entries into the table */
703:
704: for (tentry = ipc_splay_traverse_start(&move);
705: tentry != ITE_NULL;
706: tentry = ipc_splay_traverse_next(&move, delete)) {
707: mach_port_t name;
708: mach_port_gen_t gen;
709: mach_port_type_t type;
710: ipc_entry_bits_t bits;
711: ipc_object_t obj;
712: ipc_entry_t entry;
713:
714: name = tentry->ite_name;
715: gen = MACH_PORT_GEN(name);
716: index = MACH_PORT_INDEX(name);
717:
718: assert(tentry->ite_space == space);
719: assert((osize <= index) && (index < size));
720:
721: entry = &table[index];
722:
723: /* collision with previously moved entry? */
724:
725: bits = entry->ie_bits;
726: if (bits != 0) {
727: assert(IE_BITS_TYPE(bits));
728: assert(IE_BITS_GEN(bits) != gen);
729:
730: entry->ie_bits =
731: bits | IE_BITS_COLLISION;
732: delete = FALSE;
733: continue;
734: }
735:
736: bits = tentry->ite_bits;
737: type = IE_BITS_TYPE(bits);
738: assert(type != MACH_PORT_TYPE_NONE);
739:
740: entry->ie_bits = bits | gen;
741: entry->ie_object = obj = tentry->ite_object;
742: entry->ie_request = tentry->ite_request;
743:
744: if (type == MACH_PORT_TYPE_SEND) {
745: ipc_hash_global_delete(space, obj,
746: name, tentry);
747: ipc_hash_local_insert(space, obj,
748: index, entry);
749: }
750:
751: space->is_tree_total--;
752: delete = TRUE;
753: }
754: ipc_splay_traverse_finish(&move);
755:
756: /* count entries for is_tree_small */
757:
758: nosmall = 0; index = 0;
759: for (tentry = ipc_splay_traverse_start(&small);
760: tentry != ITE_NULL;
761: tentry = ipc_splay_traverse_next(&small, FALSE)) {
762: mach_port_index_t nindex;
763:
764: nindex = MACH_PORT_INDEX(tentry->ite_name);
765:
766: if (nindex != index) {
767: nosmall++;
768: index = nindex;
769: }
770: }
771: ipc_splay_traverse_finish(&small);
772:
773: assert(nosmall <= (nsize - size));
774: assert(nosmall <= space->is_tree_total);
775: space->is_tree_small = nosmall;
776:
777: /* put the splay tree back together */
778:
779: ipc_splay_tree_join(&space->is_tree, &small);
780: ipc_splay_tree_join(&space->is_tree, &move);
781: ipc_splay_tree_join(&space->is_tree, &ignore);
782: }
783:
784: /*
785: * Add entries in the new part which still aren't used
786: * to the free list. Add them in reverse order,
787: * and set the generation number to -1, so that
788: * early allocations produce "natural" names.
789: */
790:
791: free_index = table[0].ie_next;
792: for (i = size-1; i >= osize; --i) {
793: ipc_entry_t entry = &table[i];
794:
795: if (entry->ie_bits == 0) {
796: entry->ie_bits = IE_BITS_GEN_MASK;
797: entry->ie_next = free_index;
798: free_index = i;
799: }
800: }
801: table[0].ie_next = free_index;
802:
803: /*
804: * Now we need to free the old table.
805: * If the space dies or grows while unlocked,
806: * then we can quit here.
807: */
808:
809: is_write_unlock(space);
810: thread_wakeup((event_t) space);
811: it_entries_free(oits, otable);
812: is_write_lock(space);
813: if (!space->is_active || (space->is_table_next != nits))
814: return KERN_SUCCESS;
815:
816: /*
817: * We might have moved enough entries from
818: * the splay tree into the table that
819: * the table can be profitably grown again.
820: *
821: * Note that if size == nsize, then
822: * space->is_tree_small == 0.
823: */
824: } while ((space->is_tree_small > 0) &&
825: (((nsize - size) * sizeof(struct ipc_entry)) <
826: (space->is_tree_small * sizeof(struct ipc_tree_entry))));
827:
828: return KERN_SUCCESS;
829: }
830:
831:
832: #if MACH_KDB
833: #include <ddb/db_output.h>
834: #include <kern/task.h>
835:
836: #define printf kdbprintf
837:
838: ipc_entry_t db_ipc_object_by_name(
839: task_t task,
840: mach_port_t name);
841:
842:
843: ipc_entry_t
844: db_ipc_object_by_name(
845: task_t task,
846: mach_port_t name)
847: {
848: ipc_space_t space = task->itk_space;
849: ipc_entry_t entry;
850:
851:
852: entry = ipc_entry_lookup(space, name);
853: if(entry != IE_NULL) {
854: iprintf("(task 0x%x, name 0x%x) ==> object 0x%x",
855: entry->ie_object);
856: return (ipc_entry_t) entry->ie_object;
857: }
858: return entry;
859: }
860: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.