| LEFT | RIGHT |
| 1 // Copyright 2010 The Go Authors. All rights reserved. | 1 // Copyright 2010 The Go Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "runtime.h" | 5 #include "runtime.h" |
| 6 #include "os.h" | 6 #include "os.h" |
| 7 | 7 |
| 8 int8 *goos = "plan9"; | 8 int8 *goos = "plan9"; |
| 9 | 9 |
| 10 void | 10 void |
| 11 minit(void) | 11 minit(void) |
| 12 { | 12 { |
| 13 } | 13 } |
| 14 | 14 |
| 15 void | 15 void |
| 16 osinit(void) | 16 osinit(void) |
| 17 { | 17 { |
| 18 } | 18 } |
| 19 | 19 |
| 20 void | 20 void |
| 21 initsig(int32 queue) | 21 initsig(int32 queue) |
| 22 { | 22 { |
| 23 } | 23 } |
| 24 | 24 |
| 25 void | 25 void |
| 26 exit(int32) | 26 exit(int32) |
| 27 { | 27 { |
| 28 exits(nil); | 28 » exits(nil); |
| 29 } | 29 } |
| 30 | 30 |
| 31 void | 31 void |
| 32 newosproc(M *m, G *g, void *stk, void (*fn)(void)) | 32 newosproc(M *m, G *g, void *stk, void (*fn)(void)) |
| 33 { | 33 { |
| 34 USED(m, g, stk, fn); | 34 USED(m, g, stk, fn); |
| 35 | 35 » |
| 36 m->tls[0] = m->id; // so 386 asm can find it | 36 m->tls[0] = m->id; // so 386 asm can find it |
| 37 if(0){ | 37 if(0){ |
| 38 printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/%d ostk=
%p\n", | 38 printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/%d ostk=
%p\n", |
| 39 stk, m, g, fn, rfork, m->id, m->tls[0], &m); | 39 stk, m, g, fn, rfork, m->id, m->tls[0], &m); |
| 40 }········ | 40 }········ |
| 41 | 41 » |
| 42 if (rfork(RFPROC | RFMEM, stk, m, g, fn) < 0 ) | 42 if (rfork(RFPROC | RFMEM, stk, m, g, fn) < 0 ) |
| 43 throw("newosproc: rfork failed"); | 43 throw("newosproc: rfork failed"); |
| 44 } | 44 } |
| 45 | 45 |
| 46 // Blocking locks. | 46 // Blocking locks. |
| 47 | 47 |
| 48 // Implement Locks, using semaphores. | 48 // Implement Locks, using semaphores. |
| 49 // l->key is the number of threads who want the lock. | 49 // l->key is the number of threads who want the lock. |
| 50 // In a race, one thread increments l->key from 0 to 1 | 50 // In a race, one thread increments l->key from 0 to 1 |
| 51 // and the others increment it from >0 to >1. The thread | 51 // and the others increment it from >0 to >1. The thread |
| 52 // who does the 0->1 increment gets the lock, and the | 52 // who does the 0->1 increment gets the lock, and the |
| 53 // others wait on the semaphore. When the 0->1 thread | 53 // others wait on the semaphore. When the 0->1 thread |
| 54 // releases the lock by decrementing l->key, l->key will | 54 // releases the lock by decrementing l->key, l->key will |
| 55 // be >0, so it will increment the semaphore to wake up | 55 // be >0, so it will increment the semaphore to wake up |
| 56 // one of the others. This is the same algorithm used | 56 // one of the others. This is the same algorithm used |
| 57 // in Plan 9's user-level locks. | 57 // in Plan 9's user-level locks. |
| 58 | 58 |
| 59 void | 59 void |
| 60 lock(Lock *l) | 60 lock(Lock *l) |
| 61 { | 61 { |
| 62 if(m->locks < 0) | 62 if(m->locks < 0) |
| 63 throw("lock count"); | 63 throw("lock count"); |
| 64 m->locks++; | 64 m->locks++; |
| 65 | 65 » |
| 66 if(xadd(&l->key, 1) == 1) | 66 if(xadd(&l->key, 1) == 1) |
| 67 return; // changed from 0 -> 1; we hold lock | 67 return; // changed from 0 -> 1; we hold lock |
| 68 // otherwise wait in kernel | 68 // otherwise wait in kernel |
| 69 while(plan9_semacquire(&l->sema, 1) < 0) { | 69 while(plan9_semacquire(&l->sema, 1) < 0) { |
| 70 /* interrupted; try again */ | 70 /* interrupted; try again */ |
| 71 } | 71 } |
| 72 } | 72 } |
| 73 | 73 |
| 74 void | 74 void |
| 75 unlock(Lock *l) | 75 unlock(Lock *l) |
| 76 { | 76 { |
| 77 m->locks--; | 77 m->locks--; |
| 78 if(m->locks < 0) | 78 if(m->locks < 0) |
| 79 throw("lock count"); | 79 throw("lock count"); |
| 80 | 80 |
| 81 if(xadd(&l->key, -1) == 0) | 81 if(xadd(&l->key, -1) == 0) |
| 82 return; // changed from 1 -> 0: no contention | 82 return; // changed from 1 -> 0: no contention |
| 83 | 83 » |
| 84 plan9_semrelease(&l->sema, 1); | 84 plan9_semrelease(&l->sema, 1); |
| 85 } | 85 } |
| 86 | 86 |
| 87 | 87 |
| 88 void· | 88 void· |
| 89 destroylock(Lock *l) | 89 destroylock(Lock *l) |
| 90 { | 90 { |
| 91 // nothing | 91 » // nothing |
| 92 } | 92 } |
| 93 | 93 |
| 94 // User-level semaphore implementation: | 94 // User-level semaphore implementation: |
| 95 // try to do the operations in user space on u, | 95 // try to do the operations in user space on u, |
| 96 // but when it's time to block, fall back on the kernel semaphore k. | 96 // but when it's time to block, fall back on the kernel semaphore k. |
| 97 // This is the same algorithm used in Plan 9. | 97 // This is the same algorithm used in Plan 9. |
| 98 void | 98 void |
| 99 usemacquire(Usema *s) | 99 usemacquire(Usema *s) |
| 100 { | 100 { |
| 101 if((int32)xadd(&s->u, -1) < 0) | 101 if((int32)xadd(&s->u, -1) < 0) |
| (...skipping 24 matching lines...) Loading... |
| 126 usemacquire(&n->sema); | 126 usemacquire(&n->sema); |
| 127 } | 127 } |
| 128 | 128 |
| 129 void | 129 void |
| 130 notewakeup(Note *n) | 130 notewakeup(Note *n) |
| 131 { | 131 { |
| 132 n->wakeup = 1; | 132 n->wakeup = 1; |
| 133 usemrelease(&n->sema); | 133 usemrelease(&n->sema); |
| 134 } | 134 } |
| 135 | 135 |
| LEFT | RIGHT |