|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: *
25: */
26: /*
27: * File: kern/sync_lock.c
28: * Author: Joseph CaraDonna
29: *
30: * Contains RT distributed lock synchronization services.
31: */
32:
33: #include <kern/etap_macros.h>
34: #include <kern/misc_protos.h>
35: #include <kern/sync_lock.h>
36: #include <kern/sched_prim.h>
37: #include <kern/ipc_kobject.h>
38: #include <kern/ipc_sync.h>
39: #include <kern/etap_macros.h>
40: #include <kern/thread.h>
41: #include <kern/task.h>
42: #include <ipc/ipc_port.h>
43: #include <ipc/ipc_space.h>
44:
45: /*
46: * Ulock ownership MACROS
47: *
48: * Assumes: ulock internal lock is held
49: */
50:
51: #define ulock_ownership_set(ul, th) \
52: MACRO_BEGIN \
53: thread_act_t _th_act; \
54: _th_act = (th)->top_act; \
55: act_lock(_th_act); \
56: enqueue (&_th_act->held_ulocks, (queue_entry_t) (ul)); \
57: act_unlock(_th_act); \
58: (ul)->holder = _th_act; \
59: MACRO_END
60:
61: #define ulock_ownership_clear(ul) \
62: MACRO_BEGIN \
63: thread_act_t _th_act; \
64: _th_act = (ul)->holder; \
65: if (_th_act->active) { \
66: act_lock(_th_act); \
67: remqueue(&_th_act->held_ulocks, \
68: (queue_entry_t) (ul)); \
69: act_unlock(_th_act); \
70: } else { \
71: remqueue(&_th_act->held_ulocks, \
72: (queue_entry_t) (ul)); \
73: } \
74: (ul)->holder = THR_ACT_NULL; \
75: MACRO_END
76:
77: /*
78: * Lock set ownership MACROS
79: */
80:
81: #define lock_set_ownership_set(ls, t) \
82: MACRO_BEGIN \
83: task_lock((t)); \
84: enqueue_head(&(t)->lock_set_list, (queue_entry_t) (ls));\
85: (t)->lock_sets_owned++; \
86: task_unlock((t)); \
87: (ls)->owner = (t); \
88: MACRO_END
89:
90: #define lock_set_ownership_clear(ls, t) \
91: MACRO_BEGIN \
92: task_lock((t)); \
93: remqueue(&(t)->lock_set_list, (queue_entry_t) (ls)); \
94: (t)->lock_sets_owned--; \
95: task_unlock((t)); \
96: MACRO_END
97:
98: unsigned int lock_set_event;
99: #define LOCK_SET_EVENT ((event_t)&lock_set_event)
100:
101: unsigned int lock_set_handoff;
102: #define LOCK_SET_HANDOFF ((event_t)&lock_set_handoff)
103:
104: /*
105: * ROUTINE: lock_set_create [exported]
106: *
107: * Creates a lock set.
108: * The port representing the lock set is returned as a parameter.
109: */
110: kern_return_t
111: lock_set_create (
112: task_t task,
113: lock_set_t *new_lock_set,
114: int n_ulocks,
115: int policy)
116: {
117: lock_set_t lock_set = LOCK_SET_NULL;
118: ulock_t ulock;
119: int size;
120: int x;
121:
122: *new_lock_set = LOCK_SET_NULL;
123:
124: if (task == TASK_NULL || n_ulocks <= 0 || policy > SYNC_POLICY_MAX)
125: return KERN_INVALID_ARGUMENT;
126:
127: size = sizeof(struct lock_set) + (sizeof(struct ulock) * (n_ulocks-1));
128: lock_set = (lock_set_t) kalloc (size);
129:
130: if (lock_set == LOCK_SET_NULL)
131: return KERN_RESOURCE_SHORTAGE;
132:
133:
134: lock_set_lock_init(lock_set);
135: lock_set->n_ulocks = n_ulocks;
136: lock_set->ref_count = 1;
137:
138: /*
139: * Create and initialize the lock set port
140: */
141: lock_set->port = ipc_port_alloc_kernel();
142: if (lock_set->port == IP_NULL) {
143: /* This will deallocate the lock set */
144: lock_set_dereference(lock_set);
145: return KERN_RESOURCE_SHORTAGE;
146: }
147:
148: ipc_kobject_set (lock_set->port,
149: (ipc_kobject_t) lock_set,
150: IKOT_LOCK_SET);
151:
152: /*
153: * Initialize each ulock in the lock set
154: */
155:
156: for (x=0; x < n_ulocks; x++) {
157: ulock = (ulock_t) &lock_set->ulock_list[x];
158: ulock_lock_init(ulock);
159: ulock->lock_set = lock_set;
160: ulock->holder = THR_ACT_NULL;
161: ulock->blocked = FALSE;
162: ulock->unstable = FALSE;
163: ulock->ho_wait = FALSE;
164: wait_queue_init(&ulock->wait_queue, policy);
165: }
166:
167: lock_set_ownership_set(lock_set, task);
168:
169: lock_set->active = TRUE;
170: *new_lock_set = lock_set;
171:
172: return KERN_SUCCESS;
173: }
174:
175: /*
176: * ROUTINE: lock_set_destroy [exported]
177: *
178: * Destroys a lock set. This call will only succeed if the
179: * specified task is the SAME task name specified at the lock set's
180: * creation.
181: *
182: * NOTES:
183: * - All threads currently blocked on the lock set's ulocks are awoken.
184: * - These threads will return with the KERN_LOCK_SET_DESTROYED error.
185: */
186: kern_return_t
187: lock_set_destroy (task_t task, lock_set_t lock_set)
188: {
189: thread_t thread;
190: ulock_t ulock;
191: int i;
192:
193: if (task == TASK_NULL || lock_set == LOCK_SET_NULL)
194: return KERN_INVALID_ARGUMENT;
195:
196: if (lock_set->owner != task)
197: return KERN_INVALID_RIGHT;
198:
199: lock_set_lock(lock_set);
200: if (!lock_set->active) {
201: lock_set_unlock(lock_set);
202: return KERN_LOCK_SET_DESTROYED;
203: }
204:
205: /*
206: * Deactivate lock set
207: */
208: lock_set->active = FALSE;
209:
210: /*
211: * If a ulock is currently held in the target lock set:
212: *
213: * 1) Wakeup all threads blocked on the ulock (if any). Threads
214: * may be blocked waiting normally, or waiting for a handoff.
215: * Blocked threads will return with KERN_LOCK_SET_DESTROYED.
216: *
217: * 2) ulock ownership is cleared.
218: * The thread currently holding the ulock is revoked of its
219: * ownership.
220: */
221: for (i = 0; i < lock_set->n_ulocks; i++) {
222: ulock = &lock_set->ulock_list[i];
223:
224: ulock_lock(ulock);
225:
226: if (ulock->accept_wait) {
227: ulock->accept_wait = FALSE;
228: wait_queue_wakeup_one(&ulock->wait_queue,
229: LOCK_SET_HANDOFF,
230: THREAD_RESTART);
231: }
232:
233: if (ulock->holder) {
234: if (ulock->blocked) {
235: ulock->blocked = FALSE;
236: wait_queue_wakeup_all(&ulock->wait_queue,
237: LOCK_SET_EVENT,
238: THREAD_RESTART);
239: }
240: if (ulock->ho_wait) {
241: ulock->ho_wait = FALSE;
242: wait_queue_wakeup_one(&ulock->wait_queue,
243: LOCK_SET_HANDOFF,
244: THREAD_RESTART);
245: }
246: ulock_ownership_clear(ulock);
247: }
248:
249: ulock_unlock(ulock);
250: }
251:
252: lock_set_unlock(lock_set);
253: lock_set_ownership_clear(lock_set, task);
254:
255: /*
256: * Deallocate
257: *
258: * Drop the lock set reference, which inturn destroys the
259: * lock set structure if the reference count goes to zero.
260: */
261:
262: ipc_port_dealloc_kernel(lock_set->port);
263: lock_set_dereference(lock_set);
264:
265: return KERN_SUCCESS;
266: }
267:
268: kern_return_t
269: lock_acquire (lock_set_t lock_set, int lock_id)
270: {
271: ulock_t ulock;
272:
273: if (lock_set == LOCK_SET_NULL)
274: return KERN_INVALID_ARGUMENT;
275:
276: if (lock_id < 0 || lock_id >= lock_set->n_ulocks)
277: return KERN_INVALID_ARGUMENT;
278:
279: retry:
280: lock_set_lock(lock_set);
281: if (!lock_set->active) {
282: lock_set_unlock(lock_set);
283: return KERN_LOCK_SET_DESTROYED;
284: }
285:
286: ulock = (ulock_t) &lock_set->ulock_list[lock_id];
287: ulock_lock(ulock);
288: lock_set_unlock(lock_set);
289:
290: /*
291: * Block the current thread if the lock is already held.
292: */
293:
294: if (ulock->holder != THR_ACT_NULL) {
295: int wait_result;
296:
297: lock_set_unlock(lock_set);
298:
299: if (ulock->holder == current_act()) {
300: ulock_unlock(ulock);
301: return KERN_LOCK_OWNED_SELF;
302: }
303:
304: ulock->blocked = TRUE;
305: wait_queue_assert_wait(&ulock->wait_queue,
306: LOCK_SET_EVENT,
307: THREAD_ABORTSAFE);
308: ulock_unlock(ulock);
309:
310: /*
311: * Block - Wait for lock to become available.
312: */
313:
314: wait_result = thread_block((void (*)(void))0);
315:
316: /*
317: * Check the result status:
318: *
319: * Check to see why thread was woken up. In all cases, we
320: * already have been removed from the queue.
321: */
322: switch (wait_result) {
323: case THREAD_AWAKENED:
324: /* lock transitioned from old locker to us */
325: /* he already made us owner */
326: return (ulock->unstable) ? KERN_LOCK_UNSTABLE :
327: KERN_SUCCESS;
328:
329: case THREAD_INTERRUPTED:
330: return KERN_ABORTED;
331:
332: case THREAD_RESTART:
333: goto retry; /* probably a dead lock_set */
334:
335: default:
336: panic("lock_acquire\n");
337: }
338: }
339:
340: /*
341: * Assign lock ownership
342: */
343: ulock_ownership_set(ulock, current_thread());
344: ulock_unlock(ulock);
345:
346: return (ulock->unstable) ? KERN_LOCK_UNSTABLE : KERN_SUCCESS;
347: }
348:
349: kern_return_t
350: lock_release (lock_set_t lock_set, int lock_id)
351: {
352: ulock_t ulock;
353:
354: if (lock_set == LOCK_SET_NULL)
355: return KERN_INVALID_ARGUMENT;
356:
357: if (lock_id < 0 || lock_id >= lock_set->n_ulocks)
358: return KERN_INVALID_ARGUMENT;
359:
360: ulock = (ulock_t) &lock_set->ulock_list[lock_id];
361:
362: return (lock_release_internal(ulock, current_act()));
363: }
364:
365: kern_return_t
366: lock_try (lock_set_t lock_set, int lock_id)
367: {
368: ulock_t ulock;
369:
370:
371: if (lock_set == LOCK_SET_NULL)
372: return KERN_INVALID_ARGUMENT;
373:
374: if (lock_id < 0 || lock_id >= lock_set->n_ulocks)
375: return KERN_INVALID_ARGUMENT;
376:
377:
378: lock_set_lock(lock_set);
379: if (!lock_set->active) {
380: lock_set_unlock(lock_set);
381: return KERN_LOCK_SET_DESTROYED;
382: }
383:
384: ulock = (ulock_t) &lock_set->ulock_list[lock_id];
385: ulock_lock(ulock);
386: lock_set_unlock(lock_set);
387:
388: /*
389: * If the lock is already owned, we return without blocking.
390: *
391: * An ownership status is returned to inform the caller as to
392: * whether it already holds the lock or another thread does.
393: */
394:
395: if (ulock->holder != THR_ACT_NULL) {
396: lock_set_unlock(lock_set);
397:
398: if (ulock->holder == current_act()) {
399: ulock_unlock(ulock);
400: return KERN_LOCK_OWNED_SELF;
401: }
402:
403: ulock_unlock(ulock);
404: return KERN_LOCK_OWNED;
405: }
406:
407: /*
408: * Add the ulock to the lock set's held_ulocks list.
409: */
410:
411: ulock_ownership_set(ulock, current_thread());
412: ulock_unlock(ulock);
413:
414: return (ulock->unstable) ? KERN_LOCK_UNSTABLE : KERN_SUCCESS;
415: }
416:
417: kern_return_t
418: lock_make_stable (lock_set_t lock_set, int lock_id)
419: {
420: ulock_t ulock;
421:
422:
423: if (lock_set == LOCK_SET_NULL)
424: return KERN_INVALID_ARGUMENT;
425:
426: if (lock_id < 0 || lock_id >= lock_set->n_ulocks)
427: return KERN_INVALID_ARGUMENT;
428:
429:
430: lock_set_lock(lock_set);
431: if (!lock_set->active) {
432: lock_set_unlock(lock_set);
433: return KERN_LOCK_SET_DESTROYED;
434: }
435:
436: ulock = (ulock_t) &lock_set->ulock_list[lock_id];
437: ulock_lock(ulock);
438: lock_set_unlock(lock_set);
439:
440: if (ulock->holder != current_act()) {
441: ulock_unlock(ulock);
442: return KERN_INVALID_RIGHT;
443: }
444:
445: ulock->unstable = FALSE;
446: ulock_unlock(ulock);
447:
448: return KERN_SUCCESS;
449: }
450:
451: /*
452: * ROUTINE: lock_make_unstable [internal]
453: *
454: * Marks the lock as unstable.
455: *
456: * NOTES:
457: * - All future acquisitions of the lock will return with a
458: * KERN_LOCK_UNSTABLE status, until the lock is made stable again.
459: */
460: kern_return_t
461: lock_make_unstable (ulock_t ulock, thread_act_t thr_act)
462: {
463: lock_set_t lock_set;
464:
465:
466: lock_set = ulock->lock_set;
467: lock_set_lock(lock_set);
468: if (!lock_set->active) {
469: lock_set_unlock(lock_set);
470: return KERN_LOCK_SET_DESTROYED;
471: }
472:
473: ulock_lock(ulock);
474: lock_set_unlock(lock_set);
475:
476: if (ulock->holder != thr_act) {
477: ulock_unlock(ulock);
478: return KERN_INVALID_RIGHT;
479: }
480:
481: ulock->unstable = TRUE;
482: ulock_unlock(ulock);
483:
484: return KERN_SUCCESS;
485: }
486:
487: /*
488: * ROUTINE: lock_release_internal [internal]
489: *
490: * Releases the ulock.
491: * If any threads are blocked waiting for the ulock, one is woken-up.
492: *
493: */
494: kern_return_t
495: lock_release_internal (ulock_t ulock, thread_act_t thr_act)
496: {
497: lock_set_t lock_set;
498: int result;
499:
500:
501: if ((lock_set = ulock->lock_set) == LOCK_SET_NULL)
502: return KERN_INVALID_ARGUMENT;
503:
504: lock_set_lock(lock_set);
505: if (!lock_set->active) {
506: lock_set_unlock(lock_set);
507: return KERN_LOCK_SET_DESTROYED;
508: }
509: ulock_lock(ulock);
510: lock_set_unlock(lock_set);
511:
512: if (ulock->holder != thr_act) {
513: ulock_unlock(ulock);
514: lock_set_unlock(lock_set);
515: return KERN_INVALID_RIGHT;
516: }
517:
518: /*
519: * If we have a hint that threads might be waiting,
520: * try to transfer the lock ownership to a waiting thread
521: * and wake it up.
522: */
523: if (ulock->blocked) {
524: wait_queue_t wq = &ulock->wait_queue;
525: thread_t thread;
526: spl_t s;
527:
528: s = splsched();
529: wait_queue_lock(wq);
530: thread = wait_queue_wakeup_identity_locked(wq,
531: LOCK_SET_EVENT,
532: THREAD_AWAKENED,
533: TRUE);
534: /* wait_queue now unlocked, thread locked */
535:
536: if (thread != THREAD_NULL) {
537: /*
538: * JMM - These ownership transfer macros have a
539: * locking/race problem. To keep the thread from
540: * changing states on us (nullifying the ownership
541: * assignment) we need to keep the thread locked
542: * during the assignment. But we can't because the
543: * macros take an activation lock, which is a mutex.
544: * Since this code was already broken before I got
545: * here, I will leave it for now.
546: */
547: thread_unlock(thread);
548:
549: /*
550: * Transfer ulock ownership
551: * from the current thread to the acquisition thread.
552: */
553: ulock_ownership_clear(ulock);
554: ulock_ownership_set(ulock, thread);
555: ulock_unlock(ulock);
556:
557: return KERN_SUCCESS;
558: } else {
559: ulock->blocked = FALSE;
560: }
561: }
562:
563: /*
564: * Disown ulock
565: */
566: ulock_ownership_clear(ulock);
567: ulock_unlock(ulock);
568:
569: return KERN_SUCCESS;
570: }
571:
572: kern_return_t
573: lock_handoff (lock_set_t lock_set, int lock_id)
574: {
575: ulock_t ulock;
576: int wait_result;
577:
578:
579: if (lock_set == LOCK_SET_NULL)
580: return KERN_INVALID_ARGUMENT;
581:
582: if (lock_id < 0 || lock_id >= lock_set->n_ulocks)
583: return KERN_INVALID_ARGUMENT;
584:
585: retry:
586: lock_set_lock(lock_set);
587:
588: if (!lock_set->active) {
589: lock_set_unlock(lock_set);
590: return KERN_LOCK_SET_DESTROYED;
591: }
592:
593: ulock = (ulock_t) &lock_set->ulock_list[lock_id];
594: ulock_lock(ulock);
595: lock_set_unlock(lock_set);
596:
597: if (ulock->holder != current_act()) {
598: ulock_unlock(ulock);
599: lock_set_unlock(lock_set);
600: return KERN_INVALID_RIGHT;
601: }
602:
603: /*
604: * If the accepting thread (the receiver) is already waiting
605: * to accept the lock from the handoff thread (the sender),
606: * then perform the hand-off now.
607: */
608:
609: if (ulock->accept_wait) {
610: wait_queue_t wq = &ulock->wait_queue;
611: thread_t thread;
612: spl_t s;
613:
614: /*
615: * See who the lucky devil is, if he is still there waiting.
616: */
617: s = splsched();
618: wait_queue_lock(wq);
619: thread = wait_queue_wakeup_identity_locked(
620: wq,
621: LOCK_SET_HANDOFF,
622: THREAD_AWAKENED,
623: TRUE);
624: /* wait queue unlocked, thread locked */
625:
626: /*
627: * Transfer lock ownership
628: */
629: if (thread != THREAD_NULL) {
630: /*
631: * JMM - These ownership transfer macros have a
632: * locking/race problem. To keep the thread from
633: * changing states on us (nullifying the ownership
634: * assignment) we need to keep the thread locked
635: * during the assignment. But we can't because the
636: * macros take an activation lock, which is a mutex.
637: * Since this code was already broken before I got
638: * here, I will leave it for now.
639: */
640: thread_unlock(thread);
641: splx(s);
642:
643: ulock_ownership_clear(ulock);
644: ulock_ownership_set(ulock, thread);
645: ulock->accept_wait = FALSE;
646: ulock_unlock(ulock);
647: return KERN_SUCCESS;
648: } else {
649:
650: /*
651: * OOPS. The accepting thread must have been aborted.
652: * and is racing back to clear the flag that says is
653: * waiting for an accept. He will clear it when we
654: * release the lock, so just fall thru and wait for
655: * the next accept thread (that's the way it is
656: * specified).
657: */
658: splx(s);
659: }
660: }
661:
662: /*
663: * Indicate that there is a hand-off thread waiting, and then wait
664: * for an accepting thread.
665: */
666: ulock->ho_wait = TRUE;
667: wait_queue_assert_wait(&ulock->wait_queue,
668: LOCK_SET_HANDOFF,
669: THREAD_ABORTSAFE);
670: ulock_unlock(ulock);
671:
672: ETAP_SET_REASON(current_thread(), BLOCKED_ON_LOCK_HANDOFF);
673: wait_result = thread_block((void (*)(void))0);
674:
675: /*
676: * If the thread was woken-up via some action other than
677: * lock_handoff_accept or lock_set_destroy (i.e. thread_terminate),
678: * then we need to clear the ulock's handoff state.
679: */
680: switch (wait_result) {
681:
682: case THREAD_AWAKENED:
683: return KERN_SUCCESS;
684:
685: case THREAD_INTERRUPTED:
686: ulock_lock(ulock);
687: assert(ulock->holder == current_act());
688: ulock->ho_wait = FALSE;
689: ulock_unlock(ulock);
690: return KERN_ABORTED;
691:
692: case THREAD_RESTART:
693: goto retry;
694:
695: default:
696: panic("lock_handoff");
697: }
698: }
699:
700: kern_return_t
701: lock_handoff_accept (lock_set_t lock_set, int lock_id)
702: {
703: ulock_t ulock;
704: int wait_result;
705:
706:
707: if (lock_set == LOCK_SET_NULL)
708: return KERN_INVALID_ARGUMENT;
709:
710: if (lock_id < 0 || lock_id >= lock_set->n_ulocks)
711: return KERN_INVALID_ARGUMENT;
712:
713: retry:
714: lock_set_lock(lock_set);
715: if (!lock_set->active) {
716: lock_set_unlock(lock_set);
717: return KERN_LOCK_SET_DESTROYED;
718: }
719:
720: ulock = (ulock_t) &lock_set->ulock_list[lock_id];
721: ulock_lock(ulock);
722: lock_set_unlock(lock_set);
723:
724: /*
725: * If there is another accepting thread that beat us, just
726: * return with an error.
727: */
728: if (ulock->accept_wait) {
729: ulock_unlock(ulock);
730: return KERN_ALREADY_WAITING;
731: }
732:
733: if (ulock->holder == current_act()) {
734: ulock_unlock(ulock);
735: return KERN_LOCK_OWNED_SELF;
736: }
737:
738: /*
739: * If the handoff thread (the sender) is already waiting to
740: * hand-off the lock to the accepting thread (the receiver),
741: * then perform the hand-off now.
742: */
743: if (ulock->ho_wait) {
744: wait_queue_t wq = &ulock->wait_queue;
745: thread_t thread;
746: spl_t s;
747:
748: /*
749: * See who the lucky devil is, if he is still there waiting.
750: */
751: assert(ulock->holder != THR_ACT_NULL);
752: thread = ulock->holder->thread;
753:
754: wait_queue_lock(wq);
755: if (wait_queue_wakeup_thread_locked(wq,
756: LOCK_SET_HANDOFF,
757: thread,
758: THREAD_AWAKENED,
759: /* unlock? */ TRUE) == KERN_SUCCESS) {
760: /*
761: * Holder thread was still waiting to give it
762: * away. Take over ownership.
763: */
764: ulock_ownership_clear(ulock);
765: ulock_ownership_set(ulock, current_thread());
766: ulock->ho_wait = FALSE;
767: ulock_unlock(ulock);
768: return (ulock->unstable) ? KERN_LOCK_UNSTABLE :
769: KERN_SUCCESS;
770: }
771:
772: /*
773: * OOPS. The owner was aborted out of the handoff.
774: * He will clear his own flag when he gets back.
775: * in the meantime, we will wait as if we didn't
776: * even see his flag (by falling thru).
777: */
778: }
779:
780: ulock->accept_wait = TRUE;
781: wait_queue_assert_wait(&ulock->wait_queue,
782: LOCK_SET_HANDOFF,
783: THREAD_ABORTSAFE);
784: ulock_unlock(ulock);
785:
786: ETAP_SET_REASON(current_thread(), BLOCKED_ON_LOCK_HANDOFF);
787: wait_result = thread_block((void (*)(void))0);
788:
789: /*
790: * If the thread was woken-up via some action other than
791: * lock_handoff_accept or lock_set_destroy (i.e. thread_terminate),
792: * then we need to clear the ulock's handoff state.
793: */
794: switch (wait_result) {
795:
796: case THREAD_AWAKENED:
797: return KERN_SUCCESS;
798:
799: case THREAD_INTERRUPTED:
800: ulock_lock(ulock);
801: ulock->accept_wait = FALSE;
802: ulock_unlock(ulock);
803: return KERN_ABORTED;
804:
805: case THREAD_RESTART:
806: goto retry;
807:
808: default:
809: panic("lock_handoff_accept");
810: }
811: }
812:
813: /*
814: * Routine: lock_set_reference
815: *
816: * Take out a reference on a lock set. This keeps the data structure
817: * in existence (but the lock set may be deactivated).
818: */
819: void
820: lock_set_reference(lock_set_t lock_set)
821: {
822: lock_set_lock(lock_set);
823: lock_set->ref_count++;
824: lock_set_unlock(lock_set);
825: }
826:
827: /*
828: * Routine: lock_set_dereference
829: *
830: * Release a reference on a lock set. If this is the last reference,
831: * the lock set data structure is deallocated.
832: */
833: void
834: lock_set_dereference(lock_set_t lock_set)
835: {
836: int ref_count;
837: int size;
838:
839: lock_set_lock(lock_set);
840: ref_count = --(lock_set->ref_count);
841: lock_set_unlock(lock_set);
842:
843: if (ref_count == 0) {
844: size = sizeof(struct lock_set) +
845: (sizeof(struct ulock) * (lock_set->n_ulocks - 1));
846: kfree((vm_offset_t) lock_set, size);
847: }
848: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.