Index: src/pkg/runtime/sema.goc |
=================================================================== |
--- a/src/pkg/runtime/sema.goc |
+++ b/src/pkg/runtime/sema.goc |
@@ -24,20 +24,21 @@ |
typedef struct Sema Sema; |
struct Sema |
{ |
- uint32 volatile *addr; |
- G *g; |
- Sema *prev; |
- Sema *next; |
+ uint32 volatile* addr; |
+ G* g; |
+ int64 releasetime; |
+ Sema* prev; |
+ Sema* next; |
}; |
typedef struct SemaRoot SemaRoot; |
struct SemaRoot |
{ |
- Lock; |
- Sema *head; |
- Sema *tail; |
+ Lock; |
+ Sema* head; |
+ Sema* tail; |
// Number of waiters. Read w/o the lock. |
- uint32 volatile nwait; |
+ uint32 volatile nwait; |
}; |
// Prime to not correlate with any user patterns. |
@@ -97,12 +98,13 @@ |
return 0; |
} |
-void |
-runtime·semacquire(uint32 volatile *addr) |
+static void |
+semacquireimpl(uint32 volatile *addr, int32 profile) |
{ |
Sema s; // Needs to be allocated on stack, otherwise garbage collector could deallocate it |
SemaRoot *root; |
- |
+ int64 t0; |
+ |
// Easy case. |
if(cansemacquire(addr)) |
return; |
@@ -114,6 +116,12 @@ |
// sleep |
// (waiter descriptor is dequeued by signaler) |
root = semroot(addr); |
+ t0 = 0; |
+ s.releasetime = 0; |
+ if(profile && runtime·blockprofilerate > 0) { |
+ t0 = runtime·cputicks(); |
+ s.releasetime = -1; |
+ } |
for(;;) { |
runtime·lock(root); |
// Add ourselves to nwait to disable "easy case" in semrelease. |
@@ -128,12 +136,21 @@ |
// (we set nwait above), so go to sleep. |
semqueue(root, addr, &s); |
runtime·park(runtime·unlock, root, "semacquire"); |
- if(cansemacquire(addr)) |
+ if(cansemacquire(addr)) { |
+ if(t0) |
+ runtime·blockevent(s.releasetime - t0, 3); |
return; |
+ } |
} |
} |
void |
+runtime·semacquire(uint32 volatile *addr) |
+{ |
+ semacquireimpl(addr, 0); |
+} |
+ |
+void |
runtime·semrelease(uint32 volatile *addr) |
{ |
Sema *s; |
@@ -164,12 +181,15 @@ |
} |
} |
runtime·unlock(root); |
- if(s) |
+ if(s) { |
+ if(s->releasetime) |
+ s->releasetime = runtime·cputicks(); |
runtime·ready(s->g); |
+ } |
} |
func runtime_Semacquire(addr *uint32) { |
- runtime·semacquire(addr); |
+ semacquireimpl(addr, 1); |
} |
func runtime_Semrelease(addr *uint32) { |